如何使用Windows API重新打开关闭的窗口

How to reopen a closed window with the Windows API

本文关键字:开关 窗口 新打 何使用 Windows API      更新时间:2023-10-16

我正在制作一个按钮在主窗口(hwnd),当你点击一个按钮,它打开新的窗口(hwndSec),可以由主窗口控制!当我点击一个按钮,hwndSec出现了!当我点击其他按钮时,它可以被修改…但是当我关闭它并试图重新打开它时,它没有响应!这样按钮就没用了!
这是一个简单的例子,一个按钮只是打开窗口,然后试图再次打开它。

设置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                
       );

我做了两个窗口程序:

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

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

ShowWindow(hwndSec,SW_SHOW);

然后第二个窗口正常出现,当我关闭窗口时,它不会再出现。

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

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

应用程序可以提示用户确认,在破坏窗口之前,通过处理WM_CLOSE消息并调用DestroyWindow函数,只有当用户确认选择。

默认情况下,DefWindowProc函数调用DestroyWindow函数销毁窗口。

这在MSDN上进一步讨论:

关闭窗口

所以,你将不得不重新创建你的辅助窗口与CreateWindow/Ex()每次你想显示它已经关闭:

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

如果您不想这样做,那么您需要让辅助窗口处理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;
}