Aus GUI Thread auf CDC* von Dialog zugreifen
-
Guten Morgen,
ich habe folgendes Problem. Ich möchte aus einem GUI Thread auf den Window DC zugreifen um darauf zu zeichnen. Ich bringe es aber einfach nicht hin. Ich hab schon zig Methoden ausprobiert.
Meine Vermutung ist, dass ich den DC irgendwie immer mit übergeben muss. Also erst vom Dialog in den Worker Thread und dann vom Worker Thread mit Send Message in die GUI Funktion.
Hat jemand von euch eine Idee ?
Vielen Dank,
Gruß Pmb
-
Hallo,
ich verstehe Dein Setup gerade nicht. Wie meinst Du das, wenn du von "einem" GUI-Thread sprichst?
Fenster und all die Zeichenfunktionen, die auf ihren Handles arbeiten, sind an den Thread gebunden, in dem sie erzeugt wurden. Die einzige Ausnahme davon sind die Nachrichten-Funktionen. Aber die Nachrichtenbehandlung findet im selben Thread statt.
-
Also hier mal zum Verständnis mein Code:
// Thread Funktion anlegen ( global in TestDlg.h ) UINT ThreadTest(LPVOID pParam); ... protected: // Thread zum Vorschau anzeigen afx_msg LRESULT OnThreadTest(UINT wParam, LONG lParam);
// Threads definieren ( TestDlg.cpp ) #define WM_THREAD_TEST (WM_APP + 31)
// Threadfunktion ( TestDlg.cpp ) UINT ThreadTest(LPVOID pParam) { // Variablen und Objekteanlegen HWND wnd_local; CWnd *cwnd; CTestDlg *m_ctlMenu; int iReturn = 0; // Beenden if(pParam == "999") { PostQuitMessage(-1); return 0; } // Handle von Main-Window suchen m_ctlMenu = new CTestDlg(); cwnd = m_ctlMenu->FindWindowEx(NULL,NULL,NULL, "Test"); wnd_local = HWND(cwnd->m_hWnd); if(wnd_local==0x000000) { MessageBox(0,"Das Handle konnte nicht gefunden werden!","Thread -> ThreadTest!",MB_ICONINFORMATION); return 0; } // Funktion als Endlos-Schleife aufrufen for(;;) { iReturn = ::SendMessage(wnd_local, WM_THREAD_TEST, (WPARAM)0, (LPARAM)0); if(iReturn == 1) { PostQuitMessage(-1); return 0; } Sleep(1); } return 1; }
// Thread Messagehandler ( TestDlg.cpp ) LRESULT CTestDlg::OnThreadTest(UINT wParam, LONG lParam) { ... ... return 0; }
// Thread starten ( TestDlg.cpp / InitInstance ) AfxBeginThread(ThreadTest,0,THREAD_PRIORITY_NORMAL);
Nun will ich aus dem Thread Messagehandler den DC des Dialogs ansprechen und darauf zeichnen. Ich kann aber nicht aus dieser Funktion darauf zugreifen. Es kommt immer Error.
-
Wo wird der Dialog erzeugt? Läuft der Dialog modal? Wenn nicht, wo ist seine Nachrichtenschleife? Wenn ja, wie kommst du überhaupt zu dem Code im Thread, der nach der Konstruktion stattfindet?
Das sieht da alles ziemlich wirr aus, aber scheint ja auch Experimentier-Code zu sein.
-
Der Dialog wird im MainFrame erzeugt.
if(m_dlgPane && m_dlgPane->GetSafeHwnd()) { m_dlgPane->ShowPane(TRUE,FALSE,TRUE); return ; } m_dlgPane = new CAnzeige; UINT style = WS_CHILD | CBRS_RIGHT |CBRS_FLOAT_MULTI; CString strTitle = _T("Anzeige"); if (!m_dlgPane->Create(strTitle, this, CRect(0, 0, 300, 400), TRUE, IDD_DIALOG_ANZEIGE, style,AFX_CBRS_OUTLOOK_TABS)) { TRACE0("Failed to create dialog pane\n"); SAFE_DELETE(m_dlgPane); return ; } m_dlgPane->EnableDocking(CBRS_ALIGN_ANY); DockPane((CBasePane*)m_dlgPane,AFX_IDW_DOCKBAR_RIGHT); CDockablePane* pTabbedBar = NULL; if(m_splitePane && m_splitePane->GetSafeHwnd()) m_dlgPane->AttachToTabWnd(m_splitePane, DM_SHOW, TRUE, &pTabbedBar); else m_dlgPane->ShowPane(TRUE,FALSE,TRUE); RecalcLayout();
-
SendMessage würde den Workerthread anhalten ...
Wenn es ein Workerthread ist sollte dieser der GUI per
PostMessage(hWndMain, SOME_CUSTOM_MESSAGE, 0, 0);
mitteilen, wenn es was neus zum Anzeigen gibt. Die GUI sollte
Zugriff auf die anzuzeigenden Daten haben und das erledigen.Möglicherweise hilft hier auch
MSDN Communicating Between Threads
http://msdn.microsoft.com/en-us/library/h14y172e(v=vs.71).aspx
-
Wenn ich mich recht erinnere sollten DCs nicht zwischen mehreren Threads ausgetauscht/benutzt werden.
D.h. DCs sind nicht thread sicher!Siehe
http://msdn.microsoft.com/de-de/library/ms386465(v=vs.71).aspx
-
Hat geklappt.
Vielen Dank