2009-05-28 16 views
0

Ich schreibe eine Win32 Wrapper-Klassen, vor allem, um mehr über Win32-Programmierung zu lernen. Um das Problem der c-style Rückrufe zu umgehen, speichert/ruft die folgende Methode den Zeiger mit SetWindowLong/GetWindowLong und übergibt es an die tatsächliche winproc.Win32: Modal Dialog nicht zurück Fokus

LRESULT CALLBACK WinClass::WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    // On window creation, WindowProc receives lParam as a LPCREATESTRUCT 
    // Store *this* pointer as long in GWL_USERDATA 
    if (msg == WM_NCCREATE) 
     ::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams)); 

    // Retrieve the pointer 
    WinClass *wnd = reinterpret_cast<WinClass*>(::GetWindowLongPtr(hwnd, GWL_USERDATA)); 

    // Call the actual winproc function 
    if (wnd) 
     return wnd->WndProc(hwnd, msg, wParam, lParam); 
    // Default to DefWindowProc message handler function 
    return ::DefWindowProc(hwnd, msg, wParam, lParam); 
} 

Winclass ist die Klasse, die das von CreateWindowEx erstellte Hauptfenster einhüllt. Die gleiche WindowProc-Funktion ist Teil der MDlgClass, die den modalen Dialog einhüllt. Ich bin den Dialog wie dieser

DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(id), hwnd, DialogProc); 

Aufruf Wenn ich übergeben NULL als hWndParent, funktioniert der Dialog in Ordnung als modalen Dialog, aber wenn ich Hwnd passieren, wobei der Griff in das Hauptfenster als hWndParent der Dialog funktioniert ordnungsgemäß als ein modaler Dialog Aber wenn ich den Dialog schließe, übergibt er die Kontrolle nicht zurück an das Haupt-Eltern-Fenster? Das Debuggen in Visual Studio zeigt, dass es in der Nachrichtenpumpe in WinMain hängt.

Ich dachte an eine hashmap, um die Zeiger abzubilden, aber ich würde es lieber mit GetWindowLong etc. machen. Ist das möglich? Ich habe versucht, den Dialogzeiger in DWL_USER zu speichern, aber es hilft nicht.

Jede Hilfe würde geschätzt werden, ich bin immer noch um Win32.

EDIT: Ich Zerstören den Dialog EndDialog Verwendung

EDIT: Ich Speichere die Zeiger in dem GWL_USERDATA Bereich des Hauptfensters, die nicht durch Fenster verwendet wird, und ich bin Modifizieren nur in WinClass :: WindowProc, wenn das Fenster zum ersten Mal erstellt wird. Wenn ich eine Dialogklasse nicht instanziiere, weiß ich, dass auf den Zeiger korrekt zugegriffen wird, da die Anwendung auf Menübefehle reagiert, die über WindowProc und WM_COMMAND verarbeitet werden.

Antwort

0

Wie schließen Sie das Fenster? Verwenden Sie DestroyWindow? Während das untergeordnete Fenster aktiv ist, wird das übergeordnete Fenster deaktiviert.

0

Sie speichern einen Zeiger auf lpCreateParams. Ist es möglich, dass der zugehörige Speicherblock freigegeben oder anderweitig zerstört wird?

4

Sie können ein WindowProc nicht als DialogProc verwenden. Window Procedures rufen DefWindowProc auf, wenn sie eine Nachricht nicht verarbeiten und wenn sie ein sinnvolles Ergebnis zurückgeben. Dialogprozeduren geben FALSE zurück, wenn sie eine Nachricht nicht verarbeiten, geben TRUE zurück, wenn sie es tun (außer wenn sie WM_INITDIALOG behandeln) und wenn sie ein bedeutungsvolles Ergebnis haben, dass sie von der äußeren Fensterprozedur zurückkehren müssen DWL_MSGRESULT.

Wenn Sie die modale Dialogfeldfunktion DialogBox aufrufen, wird eine Nachrichtenpumpschleife aufgerufen, die Meldungen an alle Fenster im Thread sendet, damit alle Fenster weiterhin malen und Eingaben verarbeiten, wenn der Dialog geschlossen wird (mit EndDialog)), sollte die DialogBox-Prozedur zurückkehren.

Beim Erstellen einer Klasse zum Umbrechen von Dialogfeldern besteht die übliche Methode darin, den 'this' -Zeiger an eine der DialogBoxParam-Funktionen zu übergeben, die direkt aus der Nachricht WM_INITDIALOG extrahiert werden kann.

0
 
//static method 
BOOL CALLBACK WinClass::DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    // Store *this* pointer as long in GWL_USERDATA 
    if (msg == WM_INITDIALOG) 
    { 
     ::SetWindowLongPtr(hwnd, DWLP_USER, reinterpret_cast(lParam)); 
     m_hWnd = hWnd; // I assume you really don't want to keep passing the hwnd around 
    } 

    WinClass* wnd = reinterpret_cast(::GetWindowLongPtr(hwnd, GWL_USERDATA)); 
    if (wnd) 
     return wnd->DlgProcImpl(umsg, wParam, lParam); 
    return FALSE; 
} 

BOOL WinClass::DlgProcImpl(UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (uMsg) 
    { 
     // your code goes here 

      return FALSE; 
    } 

    return FALSE; 
} 

INT_PTR WinClass:DoModalDialog(HINSTANCE hInst, HWND hwndParent, LPCTSTR template) 
{ 
    return ::DialogBoxParam(hInst, template, hwndParent, WinClass::DlgProc, this); 
}