简体   繁体   English

Win32:模式对话框未返回焦点

[英]Win32: Modal dialog not returning focus

I'm writing a win32 wrapper classes, mainly to learn more about win32 programming. 我正在编写Win32包装器类,主要是为了学习有关Win32编程的更多信息。 To get around the problem of c-style callbacks, the following method stores/retrieves the pointer using SetWindowLong/GetWindowLong and passes it to the actual winproc. 为了解决c风格的回调问题,以下方法使用SetWindowLong / GetWindowLong存储/检索指针,并将其传递给实际的winproc。

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 is the class wrapping the main window created by CreateWindowEx. Winclass是包装由CreateWindowEx创建的主窗口的类。 The same WindowProc function is part of the MDlgClass wrapping the modal dialog. 相同的WindowProc函数是包装模式对话框的MDlgClass的一部分。 I'm calling the dialog like this 我这样叫对话框

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

If I pass NULL as the hWndParent, the dialog works okay as a modeless dialog but if I pass hwnd, the handle to the main window as hWndParent the dialog works correctly as a modal dialog. 如果我将NULL作为hWndParent传递,则该对话框可以作为无模式对话框正常工作,但如果我传递hwnd,作为hWndParent的主窗口句柄,则该对话框可以作为模式对话框正常工作。 However when i close the dialog it doesnt pass control back to the main parent window? 但是,当我关闭对话框时,它不会将控制权传递回主父窗口吗? Debugging in Visual Studio shows its hanging in the message pump in WinMain. 在Visual Studio中进行调试显示其在WinMain的消息泵中挂起。

I thought of using a hashmap to map the pointers but I'd rather do it using GetWindowLong etc. Is this possible? 我考虑过使用哈希映射来映射指针,但我更愿意使用GetWindowLong等来实现。这可能吗? I've tried storing the dialog pointer in DWL_USER but it doesnt help. 我试过将对话框指针存储在DWL_USER中,但没有帮助。

Any help would be appreciated, I'm still getting my head around Win32. 任何帮助将不胜感激,我仍然对Win32有所了解。

EDIT: I'm destroying the dialog using EndDialog 编辑:我正在使用EndDialog销毁对话框

EDIT: I'm storing the pointer in the GWL_USERDATA region of the main window, which is not used by windows and I'm only modifying it in WinClass::WindowProc when the window is first created. 编辑:我将指针存储在主窗口的GWL_USERDATA区域中,窗口不使用它,并且仅在首次创建窗口时才在WinClass :: WindowProc中对其进行修改。 If I don't instantiate a dialog class, I know the pointer is being accessed correctly since the application responds to menu commands processed via WindowProc and WM_COMMAND. 如果我不实例化对话框类,则我知道该指针已正确访问,因为该应用程序响应通过WindowProc和WM_COMMAND处理的菜单命令。

You can't use a WindowProc as a DialogProc. 您不能将WindowProc用作DialogProc。 Window Procedures call DefWindowProc when they don't handle a message and return a meaningful result when they do. 窗口过程不处理消息时将调用DefWindowProc,并在处理过程时返回有意义的结果。 Dialog Procedures return FALSE when they don't process a message, return TRUE when they DO, (except when they handle WM_INITDIALOG ) and, if they have a meaningful result that they need to return from the outer window procedure, that is placed in DWL_MSGRESULT . 对话框过程在不处理消息时返回FALSE,在不执行消息时返回TRUE(处理WM_INITDIALOG时除外),并且如果它们有有意义的结果需要从外部窗口过程返回,则将其放置在DWL_MSGRESULT

When you call the modal dialog box function, DialogBox, it enters a message pumping loop - which does dispatch messages to all windows in the thread so all windows continue to paint and process input - when the dialog is closed (using EndDialog), the DialogBox procedure should return. 当您调用模式对话框函数DialogBox时,它将进入一个消息泵送循环-它将消息分发到线程中的所有窗口,以便所有窗口继续绘制和处理输入-当对话框关闭(使用EndDialog)时,该DialogBox程序应该返回。

When making a class to wrap dialog boxes, the usual method is to pass the 'this' pointer to One of the DialogBoxParam functions - which can be directly extracted from the WM_INITDIALOG message. 在创建用于包装对话框的类时,通常的方法是将“ this”指针传递给DialogBoxParam函数之一-可以直接从WM_INITDIALOG消息中提取该WM_INITDIALOG

How are you closing the window? 您如何关闭窗户? Are you using DestroyWindow ? 您正在使用DestroyWindow吗? While the child window is live, the parent window will be disabled. 子窗口处于活动状态时,父窗口将被禁用。

You're saving a pointer to lpCreateParams. 您正在保存一个指向lpCreateParams的指针。 Is it possible that the associated memory block is being freed or otherwise destroyed? 相关的内存块是否可能被释放或以其他方式破坏?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM