2009-05-28 11 views
0

주로 win32 프로그래밍에 대해 자세히 알아 보려면 win32 래퍼 클래스를 작성합니다. C 스타일 콜백 문제를 해결하기 위해 SetWindowLong/GetWindowLong을 사용하여 포인터를 저장/검색 한 다음 실제 winproc에 전달합니다.Win32 : 모달 대화 상자가 포커스를 반환하지 않습니다.

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는 CreateWindowEx로 만든 주 창을 래핑하는 클래스입니다. 동일한 WindowProc 함수는 모달 대화 상자를 래핑하는 MDlgClass의 일부입니다. 나는 내가 hWndParent NULL을 전달하면이

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

같은 대화 상자를 호출하고있어, 대화 상자는 모덜리스 대화로 괜찮 작동하지만 내가 HWND를 통과하면, hWndParent으로 메인 윈도우에 대한 핸들이 대화 상자는 다음과 같이 올바르게 작동 모달 대화 상자. 그러나 대화 상자를 닫을 때 주 상위 창으로 제어가 전달되지 않습니까? Visual Studio에서의 디버깅은 WinMain의 메시지 펌프에 매달려 있음을 보여줍니다.

포인터를 매핑하는 데 hashmap을 사용한다고 생각했지만 GetWindowLong 등을 사용하여이를 수행하고 싶습니다. 가능합니까? DWL_USER에 대화 상자 포인터를 저장하려고 시도했지만 도움이되지 않습니다.

어떤 도움을 주시면 감사하겠습니다. 아직 Win32에서 머리를 쓰고 있습니다.

편집 : 나는 EndDialog에

를 사용하여 대화 상자를 파괴하고있어

편집 : 나는 창에서 사용하지 않는 메인 윈도우의 GWL_USERDATA 지역에서 포인터를 저장하고있어 난 단지 WinClass에서 수정 해요 :: WindowProc 창을 처음 만들 때. 대화 상자 클래스를 인스턴스화하지 않으면 응용 프로그램이 WindowProc 및 WM_COMMAND를 통해 처리 된 메뉴 명령에 응답하기 때문에 포인터가 올바르게 액세스되고 있음을 알 수 있습니다.

답변

0

어떻게 창을 닫고 있습니까? DestroyWindow을 사용하고 있습니까? 하위 창이 실행되는 동안 상위 창이 비활성화됩니다.

0

lpCreateParams에 대한 포인터를 저장하고 있습니다. 연결된 메모리 블록이 해제되었거나 삭제 될 수 있습니까?

4

WindowProc을 DialogProc로 사용할 수 없습니다. 창 프로시 저는 메시지를 처리하지 않을 때 DefWindowProc을 호출하고 의미있는 결과를 반환 할 때 DefWindowProc을 호출합니다. 대화 프로 시저가 메시지를 처리하지 않을 때 FALSE를 반환하고 수행 할 때 TRUE를 반환하고 (WM_INITDIALOG을 처리 할 때를 제외하고), 외부 창 프로 시저에서 반환해야하는 의미있는 결과가있는 경우 DWL_MSGRESULT.

모달 대화 상자 함수 DialogBox를 호출하면 메시지 펌핑 루프가 시작됩니다.이 루프는 대화 상자가 닫힐 때 (모든 대화 상자가 닫히고 대화 상자가 닫힐 때 모든 창에서 입력을 계속 처리하도록 스레드의 모든 창에 메시지를 전달합니다.), DialogBox 프로 시저를 반환해야합니다.

대화 상자를 감싸는 클래스를 만들 때 일반적인 방법은 'this'포인터를 DialogBoxParam 함수 중 하나에 전달하는 것입니다.이 메서드는 WM_INITDIALOG 메시지에서 직접 추출 할 수 있습니다.

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); 
} 

관련 문제