non modal Dialog in einem Thread createn?



  • Hi...

    Hab das noch nie anders probiert...Gibt's da einen Grund, warum du nicht mit der AFX was machen willst?
    Ah ja, was ich noch gesehen habe: Du hast jetzt das Create im Konstruktor deiner Hauptklasse...Muss das so sein? Ich dachte mir eben, dass du von deiner Hauptklasse aus einen zweiten Dialog (non-modal) aufrufst, welcher dann in einem Thread läuft.
    Oder ist das anders?
    Wenn das nämlich so ist, dann geht das sicher nicht so...Du musst deinen Dialog schon komplett im Thread erstellen, sonst klappt das nicht...
    Geh doch nochmal auf den Link, welchen ich dir bereits unten gepostet habe. Zweite Hälfte...Da gibt's eine genaue Anleitung, wie man vorzugehen hat. Ich habe das mal in einem Testprojekt ausprobiert, bevor es "ans Eingemachte ging", dies hat gut hingehauen.

    [url]
    http://www.codeproject.com/threads/threads_and_mfc.asp
    [/url]

    Das mit dem Zugreifen auf Variablen der Hauptklassen geht...Guck mal hier:
    [url]
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39101.html
    [/url]

    Leider habe ich keine Seite auf die ich das projekt hochladen könnte...Daher musst du dich mit der Anleitung in Englisch auf Codeproject begnügen..

    Folgendes noch zum allgemeinen Ablauf (So wie's bei mir läuft):

    Hauptapplikation öffnet Hauptfenster in Hauptthread -> Hauptapplikation startet neuen Thread -> THREAD startet zweiten, non modalen Dialog (in der InitInstance)-> Die Create Methode wird im Konstruktor vom zweiten Dialog platziert und wird beim Start des zweiten Dialogs durchlaufen...

    Nur nicht verzweifeln, das kriegen wer schon noch irgendwie hin... 😉

    Gruz Dan



  • hi,

    ich habs mal versucht...jedoch mit mehr oder weniger erfolg;-)
    was fehlt mir noch?...das müsste man doch bald mal zum laufen bekommen.. *hrrr*
    sorry für den vielen code...ich post lieber alles bevor unklarheiten entstehen...

    bye

    // testDlg.h : Headerdatei
    //
    
    #pragma once
    
    #include "Send_Dialog.h"
    #include <vector>
    #include <iostream>
    using namespace std;
    
    class THREADCLASS;
    
    // CtestDlg Dialogfeld
    class CtestDlg : public CDialog
    {
    // Konstruktion
    public:
    	CtestDlg(CWnd* pParent = NULL);	// Standardkonstruktor
    
    	~CtestDlg();
    
    // Dialogfelddaten
    	enum { IDD = IDD_TEST_DIALOG };
    
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV-Unterstützung
    
    // Implementierung
    protected:
    	HICON m_hIcon;
    
    	// Generierte Funktionen für die Meldungstabellen
    	virtual BOOL OnInitDialog();
    	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    	afx_msg void OnPaint();
    	afx_msg HCURSOR OnQueryDragIcon();
    	DECLARE_MESSAGE_MAP()
    public:
    	afx_msg void OnBnClickedButtonopenDialog();
    public:
    	vector<Send_Dialog*> m_vec;
    	THREADCLASS *_param;
    };
    
    class THREADCLASS : public CWinThread
    {
    public:
        CtestDlg* _this;
    };
    
    // testDlg.cpp : Implementierungsdatei
    //
    
    // includes....
    
    HANDLE h_open_dialog;
    void ThreadFunction(void *pParam);
    
    void createDebugConsole()
    {
    	AllocConsole();
    
    	freopen("CONOUT$", "w", stdout);
    	freopen("CONOUT$", "w", stderr);
    	freopen("CONIN$", "r", stdin);
    }
    
    //.......sachen vom CAboutDlg
    //.......sachen vom CAboutDlg
    
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    END_MESSAGE_MAP()
    
    // CtestDlg Dialogfeld
    
    CtestDlg::CtestDlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CtestDlg::IDD, pParent)
    {
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
        h_open_dialog = CreateEvent(NULL, FALSE, FALSE, NULL);
    
        _param = new THREADCLASS;
        _param->_this = this;
    }
    
    CtestDlg::~CtestDlg()
    {
    	delete _param;
    }
    
    void CtestDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    }
    
    BEGIN_MESSAGE_MAP(CtestDlg, CDialog)
    	ON_WM_SYSCOMMAND()
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	//}}AFX_MSG_MAP
    	ON_BN_CLICKED(ID_Button_open_Dialog, OnBnClickedButtonopenDialog)
    END_MESSAGE_MAP()
    
    // CtestDlg Meldungshandler
    
    BOOL CtestDlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	//....initialisierungen........
    
    	// TODO: Hier zusätzliche Initialisierung einfügen
    
    	AfxBeginThread (ThreadFunction, _param);
    
    	createDebugConsole();
    
    	return TRUE;  // Geben Sie TRUE zurück, außer ein Steuerelement soll den Fokus erhalten
    }
    
    //....void CtestDlg::OnSysCommand(UINT nID, LPARAM lParam)
    
    //....void CtestDlg::OnPaint() 
    
    //....HCURSOR CtestDlg::OnQueryDragIcon()
    
    void CtestDlg::OnBnClickedButtonopenDialog()
    {
        // TODO: Add your control notification handler code here
    
        SetEvent(h_open_dialog); 
    }
    
    void ThreadFunction(void *pParam)
    {
    	WaitForSingleObject(h_open_dialog, INFINITE);
    
    	CtestDlg *ptr = static_cast<CtestDlg*>(pParam);
    
    	// Dialog-Objekt erstellen
    	ptr->m_vec.push_back(new Send_Dialog(ptr));
    
    	// nicht modalen Dialog erstellen und anzeigen
    	ptr->m_vec[ptr->m_vec.size()-1]->SetForegroundWindow();
    	ptr->m_vec[ptr->m_vec.size()-1]->ShowWindow(SW_NORMAL);
    
    	while(1)
    	{
    		Sleep(100);
    	}
    }
    

    error:

    Compiling...
    testDlg.cpp
    c:\testDlg.cpp(120) : error C2665: 'AfxBeginThread' : none of the 2 overloads can convert parameter 1 from type 'void (__cdecl *)(void *)'
            c:\Programme\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\afxwin.h(4105): could be 'CWinThread *AfxBeginThread(AFX_THREADPROC,LPVOID,int,UINT,DWORD,LPSECURITY_ATTRIBUTES)'
            c:\Programme\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\afxwin.h(4108): or       'CWinThread *AfxBeginThread(CRuntimeClass *,int,UINT,DWORD,LPSECURITY_ATTRIBUTES)'
            while trying to match the argument list '(void (__cdecl *)(void *), THREADCLASS *)'
    


  • Dan McHould schrieb:

    Hi...

    Hab das noch nie anders probiert...Gibt's da einen Grund, warum du nicht mit der AFX was machen willst?
    Ah ja, was ich noch gesehen habe: Du hast jetzt das Create im Konstruktor deiner Hauptklasse...Muss das so sein? Ich dachte mir eben, dass du von deiner Hauptklasse aus einen zweiten Dialog (non-modal) aufrufst, welcher dann in einem Thread läuft.
    Oder ist das anders?

    hi,
    vielleicht, da mir das mit AFX zu komplex erscheint...
    Grund warum create im konstr. der hauptklass ist:
    Im Beschrieb musst du ja im Konstruktor von deiner Dialogklasse das Dialogfeld Createn...steht doch auch auf der codeproject seite so...wo soll dann das create hin?

    bei mir läuft es so ab:
    ich arbeite ja noch mit sockets...dh wenn ich auf dem socket was bestimmtest empfange das passiert im thread dann muss ich einen neuen non modal dialog aufmachen...das beispiel hier hab ich nur mal mit dem button gemacht um das zu vereinfachen...damit es mal läuft irgendwann*g*

    cu



  • ps.: und wie viel non modal dialoge ich erstelle und anzeige, hängt nur davon an was ich im thread am socket empfange...

    cu



  • marko. schrieb:

    Grund warum create im konstr. der hauptklass ist:
    Im Beschrieb musst du ja im Konstruktor von deiner Dialogklasse das Dialogfeld Createn...steht doch auch auf der codeproject seite so...wo soll dann das create hin?

    Willst du bei jedem Socketempfang einen neuen Hauptdialog erstellen? Oder ist der nicht modale Dialog ein anderer bzw. ein zweiter?
    Theoretisch dürfte das nochmalige Aufrufen des Hauptdialogs gehen...Muss aber auch zuerst auschecken.

    Auf Codeproject steht das Create aber im Konstruktor des aufzurufenden, zweiten Dialogfelds...

    Ich poste dir am besten doch mal das Wichtigste von meinem Demoprojekt

    // DialogThread.h : Haupt-Header-Datei für die Anwendung DIALOGTHREAD
    //
    
    #if !defined(AFX_DIALOGTHREAD_H__CBD00115_76F0_48AB_A794_2E7D73EDD68B__INCLUDED_)
    #define AFX_DIALOGTHREAD_H__CBD00115_76F0_48AB_A794_2E7D73EDD68B__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    #ifndef __AFXWIN_H__
    	#error include 'stdafx.h' before including this file for PCH
    #endif
    
    #include "resource.h"		// Hauptsymbole
    
    /////////////////////////////////////////////////////////////////////////////
    // CDialogThreadApp:
    // Siehe DialogThread.cpp für die Implementierung dieser Klasse
    //
    
    class CDialogThreadApp : public CWinApp
    {
    public:
    	CDialogThreadApp();
    	CWinThread* m_pThread[5];
    // Überladungen
    	// Vom Klassenassistenten generierte Überladungen virtueller Funktionen
    	//{{AFX_VIRTUAL(CDialogThreadApp)
    	public:
    	virtual BOOL InitInstance();
    	//}}AFX_VIRTUAL
    
    // Implementierung
    
    	//{{AFX_MSG(CDialogThreadApp)
    		// HINWEIS - An dieser Stelle werden Member-Funktionen vom Klassen-Assistenten eingefügt und entfernt.
    		//    Innerhalb dieser generierten Quelltextabschnitte NICHTS VERÄNDERN!
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    
    };
    
    extern CDialogThreadApp theApp;
    /////////////////////////////////////////////////////////////////////////////
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ fügt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein.
    
    #endif // !defined(AFX_DIALOGTHREAD_H__CBD00115_76F0_48AB_A794_2E7D73EDD68B__INCLUDED_)
    
    // DialogThread.cpp : Legt das Klassenverhalten für die Anwendung fest.
    //
    
    #include "stdafx.h"
    #include "DialogThread.h"
    #include "DialogThreadDlg.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // CDialogThreadApp
    
    BEGIN_MESSAGE_MAP(CDialogThreadApp, CWinApp)
    	//{{AFX_MSG_MAP(CDialogThreadApp)
    		// HINWEIS - Hier werden Mapping-Makros vom Klassen-Assistenten eingefügt und entfernt.
    		//    Innerhalb dieser generierten Quelltextabschnitte NICHTS VERÄNDERN!
    	//}}AFX_MSG
    	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CDialogThreadApp Konstruktion
    
    CDialogThreadApp::CDialogThreadApp()
    {
    	// ZU ERLEDIGEN: Hier Code zur Konstruktion einfügen
    	// Alle wichtigen Initialisierungen in InitInstance platzieren
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // Das einzige CDialogThreadApp-Objekt
    
    CDialogThreadApp theApp;
    
    /////////////////////////////////////////////////////////////////////////////
    // CDialogThreadApp Initialisierung
    
    BOOL CDialogThreadApp::InitInstance()
    {
    	AfxEnableControlContainer();
    
    	// Standardinitialisierung
    	// Wenn Sie diese Funktionen nicht nutzen und die Größe Ihrer fertigen 
    	//  ausführbaren Datei reduzieren wollen, sollten Sie die nachfolgenden
    	//  spezifischen Initialisierungsroutinen, die Sie nicht benötigen, entfernen.
    
    #ifdef _AFXDLL
    	Enable3dControls();			// Diese Funktion bei Verwendung von MFC in gemeinsam genutzten DLLs aufrufen
    #else
    	Enable3dControlsStatic();	// Diese Funktion bei statischen MFC-Anbindungen aufrufen
    #endif
    
    	CDialogThreadDlg dlg;
    	m_pMainWnd = &dlg;
    	int nResponse = dlg.DoModal();
    	if (nResponse == IDOK)
    	{
    		// ZU ERLEDIGEN: Fügen Sie hier Code ein, um ein Schließen des
    		//  Dialogfelds über OK zu steuern
    	}
    	else if (nResponse == IDCANCEL)
    	{
    		// ZU ERLEDIGEN: Fügen Sie hier Code ein, um ein Schließen des
    		//  Dialogfelds über "Abbrechen" zu steuern
    	}
    
    	// Da das Dialogfeld geschlossen wurde, FALSE zurückliefern, so dass wir die
    	//  Anwendung verlassen, anstatt das Nachrichtensystem der Anwendung zu starten.
    	return FALSE;
    }
    
    // DialogThreadDlg.h : Header-Datei
    //
    
    #if !defined(AFX_DIALOGTHREADDLG_H__4A95B482_54CF_4202_B7ED_C05130448FB6__INCLUDED_)
    #define AFX_DIALOGTHREADDLG_H__4A95B482_54CF_4202_B7ED_C05130448FB6__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    /////////////////////////////////////////////////////////////////////////////
    // CDialogThreadDlg Dialogfeld (HAUPTDIALOGFELD!!!)
    
    class CDialogThreadDlg : public CDialog
    {
    // Konstruktion
    public:
    	CDialogThreadDlg(CWnd* pParent = NULL);	// Standard-Konstruktor
    
    // Dialogfelddaten
    	//{{AFX_DATA(CDialogThreadDlg)
    	enum { IDD = IDD_DIALOGTHREAD_DIALOG };
    		// HINWEIS: der Klassenassistent fügt an dieser Stelle Datenelemente (Members) ein
    	//}}AFX_DATA
    
    	// Vom Klassenassistenten generierte Überladungen virtueller Funktionen
    	//{{AFX_VIRTUAL(CDialogThreadDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV-Unterstützung
    	//}}AFX_VIRTUAL
    
    // Implementierung
    protected:
    	HICON m_hIcon;
    
    	// Generierte Message-Map-Funktionen
    	//{{AFX_MSG(CDialogThreadDlg)
    	virtual BOOL OnInitDialog();
    	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    	afx_msg void OnPaint();
    	afx_msg HCURSOR OnQueryDragIcon();
    	afx_msg void OnButton1();
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ fügt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein.
    
    #endif // !defined(AFX_DIALOGTHREADDLG_H__4A95B482_54CF_4202_B7ED_C05130448FB6__INCLUDED_)
    
    // DialogThreadDlg.cpp : Implementierungsdatei Hauptdialogfeld
    //
    
    #include "stdafx.h"
    #include "DialogThread.h"
    #include "DialogThreadDlg.h"
    #include "MyThread.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // CAboutDlg-Dialogfeld für Anwendungsbefehl "Info"
    
    class CAboutDlg : public CDialog
    {
    public:
    	CAboutDlg();
    
    // Dialogfelddaten
    	//{{AFX_DATA(CAboutDlg)
    	enum { IDD = IDD_ABOUTBOX };
    	//}}AFX_DATA
    
    	// Vom Klassenassistenten generierte Überladungen virtueller Funktionen
    	//{{AFX_VIRTUAL(CAboutDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterstützung
    	//}}AFX_VIRTUAL
    
    // Implementierung
    protected:
    	//{{AFX_MSG(CAboutDlg)
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    
    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    	//{{AFX_DATA_INIT(CAboutDlg)
    	//}}AFX_DATA_INIT
    }
    
    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CAboutDlg)
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    	//{{AFX_MSG_MAP(CAboutDlg)
    		// Keine Nachrichten-Handler
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CDialogThreadDlg Dialogfeld
    
    CDialogThreadDlg::CDialogThreadDlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CDialogThreadDlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CDialogThreadDlg)
    		// HINWEIS: Der Klassenassistent fügt hier Member-Initialisierung ein
    	//}}AFX_DATA_INIT
    	// Beachten Sie, dass LoadIcon unter Win32 keinen nachfolgenden DestroyIcon-Aufruf benötigt
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }
    
    void CDialogThreadDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CDialogThreadDlg)
    		// HINWEIS: Der Klassenassistent fügt an dieser Stelle DDX- und DDV-Aufrufe ein
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CDialogThreadDlg, CDialog)
    	//{{AFX_MSG_MAP(CDialogThreadDlg)
    	ON_WM_SYSCOMMAND()
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CDialogThreadDlg Nachrichten-Handler
    
    BOOL CDialogThreadDlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	// Hinzufügen des Menübefehls "Info..." zum Systemmenü.
    
    	// IDM_ABOUTBOX muss sich im Bereich der Systembefehle befinden.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		CString strAboutMenu;
    		strAboutMenu.LoadString(IDS_ABOUTBOX);
    		if (!strAboutMenu.IsEmpty())
    		{	
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// Symbol für dieses Dialogfeld festlegen. Wird automatisch erledigt
    	//  wenn das Hauptfenster der Anwendung kein Dialogfeld ist
    	SetIcon(m_hIcon, TRUE);			// Großes Symbol verwenden
    	SetIcon(m_hIcon, FALSE);		// Kleines Symbol verwenden
    
    	// ZU ERLEDIGEN: Hier zusätzliche Initialisierung einfügen
    
    	return TRUE;  // Geben Sie TRUE zurück, außer ein Steuerelement soll den Fokus erhalten
    }
    
    void CDialogThreadDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    	{
    		CAboutDlg dlgAbout;
    		dlgAbout.DoModal();
    	}
    	else
    	{
    		CDialog::OnSysCommand(nID, lParam);
    	}
    }
    
    // Wollen Sie Ihrem Dialogfeld eine Schaltfläche "Minimieren" hinzufügen, benötigen Sie 
    //  den nachstehenden Code, um das Symbol zu zeichnen. Für MFC-Anwendungen, die das 
    //  Dokument/Ansicht-Modell verwenden, wird dies automatisch für Sie erledigt.
    
    void CDialogThreadDlg::OnPaint() 
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // Gerätekontext für Zeichnen
    
    		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
    
    		// Symbol in Client-Rechteck zentrieren
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// Symbol zeichnen
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    	else
    	{
    		CDialog::OnPaint();
    	}
    }
    
    // Die Systemaufrufe fragen den Cursorform ab, die angezeigt werden soll, während der Benutzer
    //  das zum Symbol verkleinerte Fenster mit der Maus zieht.
    HCURSOR CDialogThreadDlg::OnQueryDragIcon()
    {
    	return (HCURSOR) m_hIcon;
    }
    
    void CDialogThreadDlg::OnButton1() 
    {
    
    	for(int i=0;i<5;i++)
        theApp.m_pThread[i]=AfxBeginThread(RUNTIME_CLASS(CMyThread));
    	// TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
    
    }
    
    #if !defined(AFX_MYDIALOG_H__D562F696_4331_41A1_9C86_C78148086447__INCLUDED_)
    #define AFX_MYDIALOG_H__D562F696_4331_41A1_9C86_C78148086447__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // MyDialog.h : Header-Datei
    //
    
    /////////////////////////////////////////////////////////////////////////////
    // Dialogfeld CMyDialog (2., neues Dialogfeld)
    
    class CMyDialog : public CDialog
    {
    // Konstruktion
    public:
    	CString m_ThreadNr;
    	CMyDialog(CWnd* pParent = NULL);   // Standardkonstruktor
    
    // Dialogfelddaten
    	//{{AFX_DATA(CMyDialog)
    	enum { IDD = IDD_DIALOG1 };
    		// HINWEIS: Der Klassen-Assistent fügt hier Datenelemente ein
    	//}}AFX_DATA
    
    // Überschreibungen
    	// Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen
    	//{{AFX_VIRTUAL(CMyDialog)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterstützung
    	//}}AFX_VIRTUAL
    
    // Implementierung
    protected:
    
    	// Generierte Nachrichtenzuordnungsfunktionen
    	//{{AFX_MSG(CMyDialog)
    	afx_msg void OnTimer(UINT nIDEvent);
    	afx_msg void OnButton1();
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ fügt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein.
    
    #endif // AFX_MYDIALOG_H__D562F696_4331_41A1_9C86_C78148086447__INCLUDED_
    
    // MyDialog.cpp: Implementierungsdatei (2., neues Dialogfeld)
    
    //
    
    #include "stdafx.h"
    #include "DialogThread.h"
    #include "MyDialog.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // Dialogfeld CMyDialog 
    
    CMyDialog::CMyDialog(CWnd* pParent /*=NULL*/)
    	: CDialog(CMyDialog::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CMyDialog)
    		// HINWEIS: Der Klassen-Assistent fügt hier Elementinitialisierung ein
    	//}}AFX_DATA_INIT
    	Create(IDD_DIALOG1,NULL);
    	int static nr=1;
            CString s;
            char buf[10];
            itoa(nr,buf,10);
            s="Thread #";
            s+=buf;
            s+= " Dialog Window";
            SetWindowText(s);
            switch(nr)
            {
                    case 1:{m_ThreadNr="1";break;}
                case 2:{m_ThreadNr="2";break;} 
                case 3:{m_ThreadNr="3";break;}
                case 4:{m_ThreadNr="4";break;}
                case 5:{m_ThreadNr= "5";break;}
                            break;
             }
             // we want to be informed which thread is the current thread after 1 second
            SetTimer(nr,1000,NULL);      
                    nr++;
    }
    
    void CMyDialog::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CMyDialog)
    		// HINWEIS: Der Klassen-Assistent fügt hier DDX- und DDV-Aufrufe ein
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
    	//{{AFX_MSG_MAP(CMyDialog)
    	ON_WM_TIMER()
    	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // Behandlungsroutinen für Nachrichten CMyDialog 
    
    void CMyDialog::OnTimer(UINT nIDEvent) 
    {
    	// TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
    	CString str= "Thread";
            str+=m_ThreadNr;
            TextOut(NULL,0,0,str,0);
    
    		//m_speaker.Speak(str);
               //you may delete this line if you want to hear the threads continuously
            KillTimer(nIDEvent);      
    	CDialog::OnTimer(nIDEvent);
    }
    
    void CMyDialog::OnButton1() 
    {
    	// TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
    	DestroyWindow();
    }
    
    #if !defined(AFX_MYTHREAD_H__DEB7E8BC_EC49_47D6_B27F_8FCCEFB837AB__INCLUDED_)
    #define AFX_MYTHREAD_H__DEB7E8BC_EC49_47D6_B27F_8FCCEFB837AB__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // MyThread.h : Header-Datei
    //
    
    /////////////////////////////////////////////////////////////////////////////
    // Thread CMyThread (Die Threadklasse, abgeleitet von CWinThread)
    
    class CMyThread : public CWinThread
    {
    	DECLARE_DYNCREATE(CMyThread)
    protected:
    	CMyThread();           // Dynamische Erstellung verwendet geschützten Konstruktor
    
    // Attribute
    public:
    
    // Operationen
    public:
    
    // Überschreibungen
    	// Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen
    	//{{AFX_VIRTUAL(CMyThread)
    	public:
    	virtual BOOL InitInstance();
    	virtual int ExitInstance();
    	//}}AFX_VIRTUAL
    
    // Implementierung
    protected:
    	virtual ~CMyThread();
    
    	// Generierte Nachrichtenzuordnungsfunktionen
    	//{{AFX_MSG(CMyThread)
    		// HINWEIS - Der Klassen-Assistent fügt hier Member-Funktionen ein und entfernt diese.
    	//}}AFX_MSG
    
    	DECLARE_MESSAGE_MAP()
    };
    
    /////////////////////////////////////////////////////////////////////////////
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ fügt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein.
    
    #endif // AFX_MYTHREAD_H__DEB7E8BC_EC49_47D6_B27F_8FCCEFB837AB__INCLUDED_
    
    // MyThread.cpp: Implementierungsdatei (ThreadKlasse abgeleitet von CWinThread)
    //
    
    #include "stdafx.h"
    #include "DialogThread.h"
    #include "MyThread.h"
    #include "MyDialog.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // CMyThread
    
    IMPLEMENT_DYNCREATE(CMyThread, CWinThread)
    
    CMyThread::CMyThread()
    {
    }
    
    CMyThread::~CMyThread()
    {
    }
    
    BOOL CMyThread::InitInstance()
    {
    	// ZU ERLEDIGEN:  Initialisierungen für jeden Thread hier durchführen
    		m_pMainWnd=new CMyDialog;
            m_pMainWnd->SetForegroundWindow();
            m_pMainWnd->ShowWindow(SW_SHOW);
    
    	return TRUE;
    }
    
    int CMyThread::ExitInstance()
    {
    	// ZU ERLEDIGEN:  Bereinigungen für jeden Thread hier durchführen
    	return CWinThread::ExitInstance();
    }
    
    BEGIN_MESSAGE_MAP(CMyThread, CWinThread)
    	//{{AFX_MSG_MAP(CMyThread)
    		// HINWEIS - Der Klassen-Assistent fügt hier Zuordnungsmakros ein und entfernt diese.
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // Behandlungsroutinen für Nachrichten CMyThread
    

    Gruz Dan



  • Willst du bei jedem Socketempfang einen neuen Hauptdialog erstellen? Oder ist der nicht modale Dialog ein anderer bzw. ein zweiter?
    Theoretisch dürfte das nochmalige Aufrufen des Hauptdialogs gehen...Muss aber auch zuerst auschecken.

    Auf Codeproject steht das Create aber im Konstruktor des aufzurufenden, zweiten Dialogfelds...

    Ich poste dir am besten doch mal das Wichtigste von meinem Demoprojekt

    ich will ja nicht mehrere male den hauptdialog (CtestDlg) erstellen sondern habe 1 hauptdialog, und der thread erzeugt mehrere dialoge(Send_Dialog)...also ein anderer!!

    cu



  • hi!
    kannst du mir mal dein beispiel mailen an: 5aht@gmx.at ....hab das gefühl das liegt eher am compiler...hab den mvc 7.1 ...
    weil das codeproject demo funzt auch nicht...beim ausführen gibs nen absturz;-(

    für was brauchst du das void CMyDialog::OnTimer(UINT nIDEvent ...) ?

    cu



  • Hmm...

    Na ja, ich habe mein Beispiel mit VC6.0 erstellt..Mal sehen, ob's klappt...
    Die OnTimer Methode ist nur noch pro Forma drin...Habe da mal noch was ausprobiert... 😃
    Nur nicht irritieren lassen...

    Gruz Dan



  • hi,
    das klappt;-) komisch*g*
    warum brauchst du da ne DialogThreadDlg.h u .cpp und ne DialogThread.h u .cpp

    MyDialog ist ja der Dialog den du beim anklicken auf den button aufmachen willst...und MyThread ist der thread...

    bye...big thx!!!



  • warum brauchst du da ein:

    extern CDialogThreadApp theApp;
    

    ??

    cu



  • Hi...

    warum brauchst du da ne DialogThreadDlg.h u .cpp und ne DialogThread.h u .cpp

    DialogThread.h und .cpp ist die Klasse in der der Hauptdialog meiner Anwendung inititalisiert wird.
    DialogThreadDlg.h und .cpp ist die Klasse des HAUPTDIALOGS. Meine Applikation wurde als dialogfeldbasierende Anwendung erstellt.

    MyDialog ist ja der Dialog den du beim anklicken auf den button aufmachen willst

    Genau. Der Button liegt jedoch noch auf dem HAUPTDIALOG. Und den Code zum Button findest du in der Klasse DialogThreadDlg.
    Wenn dieser Button gedrückt wird, werden 5 Threads nacheinander gestartet und JEDER EINZELNE THREAD erzeugt ein neues Dialogfeld. Jedes im jeweiligen Thread erzeugte Dialogfeld ist nicht modal und eine Instanz von der Klasse MyDialog. Jedes der Dialofelder läuft nachher IN einem separaten Thread.

    Das bedeutet: MyDialog ist also ein ZWEITES Dialogfeld mit einer eigenen, separaten Klasse.

    warum brauchst du da ein:
    C/C++ Code:
    extern CDialogThreadApp theApp;

    Na ja, ich erzeuge eine Instanz der Klasse DialogThread global, damit ich überall auf die jeweiligen Threads Zugriff habe. Dies ist vorallem wichtig, wenn du von irgendwoher einen Thread wieder löschen musst.

    Gruz

    Dan



  • danke;-)

    also im thread erzeuge ich einen dialog mit m_pMainWnd->ShowWindow(SW_HIDE);
    wie kann ich nun aus dem hauptdialog (zb.: ich mach nen 2 button dazu, dann:) sagen m_pMainWnd->ShowWindow(SW_SHOW);???
    oder vom hauptdialog aus in einem dialog irgendwas in ein textfeld schreiben?

    wenn das geht..perfekt;-)

    cu



  • Hi

    Da musste die Threads ein wenig anders erzeugen:

    theApp.m_pThread[i]=(CMyThread*)AfxBeginThread(RUNTIME_CLASS(CMyThread));
    

    Nun solltest du auf die Variablen und Instanzen der jeweiligen Threadinstanz Zugriff haben.

    Also zum Beispiel das Dialogfeld im Thread 1:

    theApp.m_pThread[0]->DeinDialog->ShowWindow(SW_SHOW); oder so...
    

    Hoffe das klappt so...Probiers mal aus... 😃 😃 😃

    Gruz

    Dan



  • hi,
    du hast das CWinThread* m_pThread[5]; in der klasse CDialogThreadApp!

    ich brauche CWinThread* m_pThread[5]; aber in der klasse CDialogThreadDlg!!!

    wie mach ich das dann am besten? ein GetParent?

    cu



  • hi,

    hab noch ne frage...

    ich will ja daten von nem socket empfangen...das läuft in einem thread mit ner endloschleife...der thread bekommt einen pointer auf die hauptklasse...
    ich lege jetzt in diesem thread neue AfxThreads an, wenn ich einen neuen dialog erzeugen will...da der thread ja nachrichtenbasierend ist, muss ich den ja nachrichten schicken, wenn ich zb in ein editfeld etwas schreiben will...
    in der hauptklasse hab ich das array mit den pointern auf die threads...jedoch weiss ich da nicht wie ich da aus diesen thread, der ja einen pointer auf die hauptklasse hat ne methode zb.: void Show_Window(....) aufrufen kann, die der ThreadKlasse gehört!?

    wie findest du das konzept?

    cu



  • du hast das CWinThread* m_pThread[5]; in der klasse CDialogThreadApp!
    ich brauche CWinThread* m_pThread[5]; aber in der klasse CDialogThreadDlg!!!

    Das geht, wenn du eine globale Instanz deklariert hast (Von der CDialogThreadApp)
    Siehe Beitrag um 10.07 von heute...

    ich lege jetzt in diesem thread neue AfxThreads an, wenn ich einen neuen dialog erzeugen will...da der thread ja nachrichtenbasierend ist, muss ich den ja nachrichten schicken, wenn ich zb in ein editfeld etwas schreiben will...

    Musst du nicht. Initialisiere den jeweiligen Thread so, wie ich's bereits beschrieben habe (Beitrag 11.57 von heute). Dann solltest du direkt auf die jeweilige Membervariable des bestimmten Editfelds zugreifen können.

    in der hauptklasse hab ich das array mit den pointern auf die threads...jedoch weiss ich da nicht wie ich da aus diesen thread, der ja einen pointer auf die hauptklasse hat ne methode zb.: void Show_Window(....) aufrufen kann, die der ThreadKlasse gehört!?

    Das sollte aber möglich sein...Siehe wieder Beitrag um 10.07 von heute...
    Geht da nicht irgenwie sowas wie (im Socketthread):
    Wenn du das Array mit den Pointern nicht globalisierst, dann sollte doch das so gehen: DeinPtraufHauptklasse->m_pThread[2]->m_xy.Format("blah");

    Wenn der Socketthread immer läuft, dann kannste das glaub ich schon so machen...
    Gib mir mal n'Feedback, wenn's läuft... 😃

    Gruz Dan



  • ich lege jetzt in diesem thread neue AfxThreads an, wenn ich einen neuen dialog erzeugen will...da der thread ja nachrichtenbasierend ist, muss ich den ja nachrichten schicken, wenn ich zb in ein editfeld etwas schreiben will...

    Musst du nicht. Initialisiere den jeweiligen Thread so, wie ich's bereits beschrieben habe (Beitrag 11.57 von heute). Dann solltest du direkt auf die jeweilige Membervariable des bestimmten Editfelds zugreifen können.

    hatte heute ne diskussion mit jemanden, der sagte folgendes:

    wenn du von einem Thread auf einem Formular in einem anderen Thread (bei dir der App-Thread) zugreifst, muss die sache in die Hose gehen
    du kannst in einem Thread nur auf Sachen zugreifen, die auch in deinem Thread erstellt wurden
    die App gehört sicherlich nciht dazu
    ein ausweg wäre die Syncronisierung deines Workerthreads mit den Hauptthread
    so dass die Threads gleich laufen
    also als ein Thread angesehen werden können.
    dann darfst du zugreifen.
    die Syncronisation ist aber immer etwas schwierig.
    es geht, aber wenn man das umgehen kann, vermeidet man das
    weil mit einer Syncronisation natürlich auch die parallelität nicht mehr da ist
    du hebs den eigentlichen zweck des Threads auf
    das kann man umgehen indem man das Processmodel von Windows nutzt
    alle Nachrichtenschleifen werden vom Prozess und dem App-Thread der Anwendung gesteuert. Diese müssen nciht syncronisert werden.
    man muss sich das wie ein Stack vorstellen
    du packst mit SendMessage eine Nachricht auf den Schleifenstapel
    und die Anwendung / Formular nimmt sich die Nachrichten von unten immer nacheinander weg
    das führt zu einer indirekten syncronisation ein SendMessage- Aufruf muss also nicht synconisiert werden
    AndreasW folglich bleibt der Thread auch voll funktionsfähig
    und wird nicht ausgebremst

    also sowas:

    SendMessage (EditBoxHandel, SET_TEXT, "Mein Text");
    so brauchst du nciht mal nen Pointer auf das Formular
    
    mit #defin WM_MYRECIVEMESSAGE
    mit #define WM_MYRECIVEMESSAGE
    dann eine struct oder class
    und mit dieser WM_MYRECIVEMESSAGE an das Handle von der CWinApp-Instanz schicken (mit SendMessage)
    dort ein fenster aufmachen und anzeigen
    überlass die Organisation der Fenster dem Hauptthread ist besser
    
    CWinApp ist überigens von CWinThread abgeleitet
    m_hThread ist dann überigens das Handle des Hauptthreads
    
    wie kommt man aufs App-Handle?
    

    ps.: hab deine variante noch nicht probiert, da ging vorher noch was schief!!
    cu



  • hi, es funzt nun....ich sende einfach eine PostMessage aus dem thread an den Hauptdialog....PostMessage ruft eine funktion auf und der erstellt mir dann den dialog,-) geht ja viel einfacher;-) aber danke noch mal....zu viele threads sind sowieso nie gut...

    cu


Anmelden zum Antworten