Button aus einem Thread heraus auf enabled setzen
-
Hallo allerseits!
Ich habe ein Problem bei folgendem:
Beim beenden eines Threads soll ein Button, der kurz vorm Starten des threads auf disabled gesetzt wurde, wieder enabled werden.
Ich habe schon verschiedenes probiert, aber ohne Erfolg:
UINT CiterundvisDlg::thrFunction(LPVOID pParam) { ... while (*pFlag) { .. } ... GetDlgItem(IDC_BUTTON4)->EnableWindow(TRUE); return 0; }was liefert:
error C2352: 'CWnd::GetDlgItem' : illegal call of non-static member function
C:\Programme\Microsoft Visual Studio 8\VC\atlmfc\include\afxwin.h(2074) : see declaration of 'CWnd::GetDlgItem'aber das GetGlgItem nicht statisch ist, daran kann ich ja nichts ändern, oder?
Auch habe ich probiert:
UINT CiterundvisDlg::thrFunction(LPVOID pParam) { ... while (*pFlag) { .. } ... CiterundvisDlg::m_feldgrbutton.SetState( TRUE ); return 0; }wobei m_feldgrbutton eine Variable vom Typ CButton ist.
Dort bekomme ich allerdings nur:error C2228: left of '.SetState' must have class/struct/union
wobei ich nicht ganz verstehe, was der Unterschied zum m_Checkbutton Beispiel dort ist.
(Und ich weiß: Das würde den Button sowieso nicht enablen, das war nur ein prinzipieller Versuch...)Welche Möglichkeit bleibt also noch?
Wa kann ich tun, um den Button vom Threadende aus in den enabled Zustand zu versetzen?Danke und Gruß!
-
du könntest dem thread als startparameter z.b. die adresse des CButton objects mitgeben und dann: startparam->EnableWindow(TRUE)
-
Danke für den Tipp, ich probiere mal..

(Das Problem, was hier stand, hat sich erledigt....)
-
net schrieb:
du könntest dem thread als startparameter z.b. die adresse des CButton objects mitgeben und dann: startparam->EnableWindow(TRUE)
Funktioniert leider nicht:

In der den Thread aufrufenden Funktion steht:CButton* feldgrbutton; feldgrbutton = (CButton*) GetDlgItem(IDC_BUTTON4); ... CWinThread* pThread = AfxBeginThread (thrFunction, &feldgrbutton);Im Thread stehht:
UINT CiterundvisDlg::thrFunction(LPVOID pParam) { ... CButton* feldbutton = (CButton*) pParam; ... while (*threadschalter) { } feldbutton->EnableWindow(TRUE); return 0; }und das läßt sich auch kompilieren, beim ausführen gibt es beim Verlassen des Threads aber ein Problem:
Unhandled exception at 0x0040c39c in programmname.exe: 0xC0000005: Access violation reading location 0xfffbe591.
und im Debug Fenster wird auf winocc.cpp gezeigt, und zwar auf diese Stelle:
BOOL CWnd::EnableWindow(BOOL bEnable) { ASSERT(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL)); if (m_pCtrlSite == NULL) return ::EnableWindow(m_hWnd, bEnable); else return m_pCtrlSite->EnableWindow(bEnable); //hierhin zeigt der Pfeil }hab ich was falsch gemacht oder geht das prinzipiell nicht so?
Danke und Gruß!
-
Also ich würde es so machen:
CButton* feldgrbutton; feldgrbutton = static_cast<CButton*>(GetDlgItem(IDC_BUTTON4)); ... CWinThread* pThread = AfxBeginThread (thrFunction, static_cast<LPVOID>(feldgrbutton)); //& entferntdann im Thread:
UINT CiterundvisDlg::thrFunction(LPVOID pParam) { ... CButton* feldbutton = static_cast<CButton*>(pParam); ... while (*threadschalter) { } if(feldbutton != NULL && ::IsWindow(feldbutton->GetSafeHwnd())) //extra prüfung ob Button überhaupt gültig ist feldbutton->EnableWindow(TRUE); return 0; }Edit: Ich weis jetzt nicht ob man static_cast oder reinterpret_cast benutzen sollte (habs nicht getestet).
EDIT2: static_cast reicht aus.
-
-
dong schrieb:
CButton* feldgrbutton; feldgrbutton = (CButton*) GetDlgItem(IDC_BUTTON4); ... CWinThread* pThread = AfxBeginThread (thrFunction, &feldgrbutton); //<--Ich denke mal das es an dieser Zeile liegt. Du wandelst hier das Steuerelement in ein CButton* um (soweit richtig). Dann übergibst du der Funktion AfxBeginThread aber die "Adresse des Zeigers" der auf CButton zeigt (siehe & Operator). Das wird der Knackpunkt sein. Denn die Fkt. erwartet als Parameter ein LPVOID (sprich: long pointer auf void -> void*). Du kannst also an dieser stelle ruhig den Zeiger direkt übergeben (wenn er nach void gecastet ist).
CWinThread* pThread = AfxBeginThread (thrFunction, static_cast<LPVOID>(feldgrbutton)); //oder CWinThread* pThread = AfxBeginThread (thrFunction, (LPVOID)feldgrbutton);static_cast habe ich benutzt weil man die "alten" C-Cast's, z.B. (CButton*), nicht mehr benutzen sollte. Bei static_cast bekommt man z.B. mehr und genauere Fehlermeldungen falls man versucht zwischen falschen typen hin und her zu casten. Schau dir hier am besten mal static_cast, dynamic_cast und reinterpret_cast an.
Und dann ist ja noch die Sicherheitsabfrage:
if(feldbutton != NULL && ::IsWindow(feldbutton->GetSafeHwnd())) //extra prüfung ob Button überhaupt gültig ist feldbutton->EnableWindow(TRUE);Die Funktion ::IsWindow überprüft ob es sich auch wirklich um ein (gültiges) Fenster handelt. Wenn OnInitDialog vorher noch nicht aufgerufen wurde, dann wird FALSE zurück gegeben. Und mit feldbutton->GetSafeHwnd() bekommst du den Handle auf dieses Steuerelement. Hier kann ich dir aber nur sagen das ::IsWindow diesen Handle braucht. Mehr weis ich darüber leider auch nicht.
-
Danke für die prima Erklärung!

Bisher habe ich mich erfolgreich darum gedrückt, aber solangsam werde ich mch doch mal mit dem "casten" auseinandersetzen müssen...
