【问题标题】:How to reopen a closed window with the Windows API如何使用 Windows API 重新打开关闭的窗口
【发布时间】:2016-10-25 16:21:10
【问题描述】:

我正在主窗口 (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;
}

【问题讨论】:

  • 它已关闭。没有了。它已经不复存在了。它已经过期,已经去见它的制造商了。这是一只死鹦鹉。您必须再次调用 CreateWindow()。
  • 或者您可以隐藏该窗口并使用 ShowWindow 再次显示它
  • 代码显示出大量缺乏洞察力。您确实需要重新开始,并首先了解基础知识。买一本好书,比如 Petzold 的Programming Windows®, Fifth Edition
  • WindowProcedureSec() 是无限递归等待发生。

标签: c++ winapi button window


【解决方案1】:

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

应用程序可以在销毁窗口之前提示用户确认,方法是处理 WM_CLOSE 消息并仅在用户确认选择时调用 DestroyWindow 函数。

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

这在 MSDN 上有进一步讨论:

Closing the Window

因此,每次要在关闭后显示它时,您都必须使用 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;
}

【讨论】:

  • 感谢您的帮助!这两个作品!我刚开始使用 c++(windows.h 包括...),所以我不知道可以在 WindowProcedure() 上接收到的所有消息,例如 WM_CLOSE .. :p 我正在尽我所能:D
  • 这里列出了您可以接收的一些基本的常见窗口消息:Window Notifications
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-19
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
  • 2014-07-20
  • 2018-12-25
相关资源
最近更新 更多