如何使用 Windows API 重新打开已关闭的 window

How to reopen a closed window with the Windows API

我在主 window ( hwnd ) 中制作了一个按钮,当你点击一个按钮时,它会打开新的 window ( hwndSec ),它可以由主 window! 当我点击一个按钮时,hwndSec 出现了!当我点击其他按钮时,它可以被修改......但是当我关闭它并尝试再次打开它时它没有响应!所以按钮变得无用了!
这是单个按钮的简单示例,仅用于打开 window 然后尝试再次打开它。

我为 hwndSec 设置的设置:

wincl.hInstance = hInstance;
wincl.lpszClassName = "HwndSecClass";
wincl.lpfnWndProc = WindowProcedureSec;      
wincl.style = CS_DBLCLKS;                 
wincl.cbSize = sizeof (WNDCLASSEX);

/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;                 
wincl.cbClsExtra = 0;                      
wincl.cbWndExtra = 0;                      
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

if (!RegisterClassEx (&wincl))
    return 0;

hwnd = CreateWindowEx (
       0,                   
       wincl.lpszClassName,        
       _T("Window 2"),       
       WS_OVERLAPPEDWINDOW, 
       CW_USEDEFAULT,       
       CW_USEDEFAULT,       
       500,                 
       500,                 
       HWND_DESKTOP,        
       NULL,                
       hInstance,       
       NULL                
       );

我做了两个window程序:

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WindowProcedureSec (HWND, UINT, WPARAM, LPARAM);

当我点击一个按钮时,我调用这个函数:

ShowWindow(hwndSec,SW_SHOW);

然后第二个 window 正常出现,当我关闭 window 它不会再次出现。

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch (message)                  /* handle the messages */
 {
 case WM_CREATE:
    CreateWindow("BUTTON",
                "open",
                WS_CHILD | WS_VISIBLE ,
                200,100,
                100,50,
                hwnd,
                (HMENU) ID_BUTTON,
                NULL,
                NULL);
    break;
case WM_COMMAND:
    switch(LOWORD(wParam))
    {
    case ID_BUTTON :
        //printf("%s",(char*)GetLastError());
        ShowWindow(hwndSec,SW_SHOW);
        break;
    }
    break;
    case WM_DESTROY:
        PostQuitMessage (0);
        break;
    default:
        return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}


LRESULT CALLBACK WindowProcedureSec (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
{
    case WM_DESTROY:
        PostMessage(hwnd, WM_CLOSE, 0, 0);
        break;
    default:
        return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}

当 window 被关闭时,它会收到一条 WM_CLOSE 消息。如果该消息传递给 DefWindowProc(),默认行为是 销毁 window:

An application can prompt the user for confirmation, prior to destroying a window, by processing the WM_CLOSE message and calling the DestroyWindow function only if the user confirms the choice.

By default, the DefWindowProc function calls the DestroyWindow function to destroy the window.

这在 MSDN 上有进一步讨论:

Closing the Window

因此,每次您想要在关闭后显示它时,您都必须使用 CreateWindow/Ex() 重新创建您的辅助 window:

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    ...
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case ID_BUTTON :
            if (!hwndSec)
            {
                hwndSec = CreateWindowEx(
                    0,
                    _T("HwndSecClass"),
                    _T("Window 2"),
                    WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT,
                    CW_USEDEFAULT,
                    500,
                    500,
                    HWND_DESKTOP,
                    NULL,
                    hInstance,
                    NULL
                );
            }
            ShowWindow(hwndSec, SW_SHOW);
            break;
        }
        break;
    ...
    }

    return 0;
}

LRESULT CALLBACK WindowProcedureSec (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        hwndSec = NULL;
        break;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}

如果您不想这样做,则需要让辅助 window 处理 WM_CLOSE 消息,而不是将其传递给 DefWindowProc()。例如,改为调用 ShowWindow(SW_HIDE),然后您可以稍后在需要时调用 ShowWindow(SH_SHOW)

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    ...
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case ID_BUTTON :
            ShowWindow(hwndSec, SW_SHOW);
            break;
        }
        break;
    ...
    }

    return 0;
}


LRESULT CALLBACK WindowProcedureSec (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CLOSE:
        ShowWindow(hwnd, SW_HIDE);
        break;

    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    return 0;
}