Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Windows API不会退出_C++_Windows_Winapi_User Interface - Fatal编程技术网

C++ Windows API不会退出

C++ Windows API不会退出,c++,windows,winapi,user-interface,C++,Windows,Winapi,User Interface,由于某种原因,在我关闭此窗口后,我的程序将不会退出并进入无限循环。此问题的解决方案似乎是将GetMessage(&message,handel,0,0)更改为GetMessage(&message,NULL,0,0)。但是我不明白为什么会这样。谁能解释一下吗。我也不明白为什么我要调用UpdateWindow(handel),因为窗口显示时没有它 #include <iostream> #include <Windows.h> using namespace std;

由于某种原因,在我关闭此窗口后,我的程序将不会退出并进入无限循环。此问题的解决方案似乎是将GetMessage(&message,handel,0,0)更改为GetMessage(&message,NULL,0,0)。但是我不明白为什么会这样。谁能解释一下吗。我也不明白为什么我要调用UpdateWindow(handel),因为窗口显示时没有它

#include <iostream>
#include <Windows.h>

using namespace std;

LRESULT CALLBACK EventHandler(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, PSTR args, int cmd)
{
    MSG message;
    HWND handel;
    WNDCLASS win_class;

    win_class.style = CS_HREDRAW | CS_VREDRAW;
    win_class.cbClsExtra = 0;
    win_class.cbWndExtra = 0;
    win_class.lpszClassName = "Window";
    win_class.hInstance = inst;
    win_class.hbrBackground = GetSysColorBrush(COLOR_3DDKSHADOW);
    win_class.lpszMenuName = NULL;
    win_class.lpfnWndProc = EventHandler;
    win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
    win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClass(&win_class);
    handel = CreateWindow(win_class.lpszClassName, "Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 350, 250, NULL, NULL, inst, NULL);
    ShowWindow(handel, cmd);
    UpdateWindow(handel);

    //Loop does not end.
    while(GetMessage(&message, handel, 0, 0))
    {
         cout << "LOOP" << endl;
         DispatchMessage(&message);
    }
    return WM_QUIT;
}

LRESULT CALLBACK EventHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static long long count = 0;
    count++;
    cout << "CALL #" << count << endl;
    if(msg == WM_DESTROY)
    {
         PostQuitMessage(0);
         return 0;
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}
#包括
#包括
使用名称空间std;
LRESULT回调事件处理程序(HWND、UINT、WPARAM、LPARAM);
int WINAPI WinMain(HINSTANCE inst、HINSTANCE prev、PSTR参数、int cmd)
{
消息;
汉德尔;
WNDCLASS win_class;
win_class.style=CS_HREDRAW | CS_VREDRAW;
win_class.cbClsExtra=0;
win_class.cbWndExtra=0;
win_class.lpszClassName=“窗口”;
win_class.hInstance=inst;
win_class.hbrBackground=GetSysColorBrush(彩色阴影);
win_class.lpszMenuName=NULL;
win_class.lpfnWndProc=EventHandler;
win_class.hCursor=LoadCursor(空,IDC_箭头);
win_class.hIcon=LoadIcon(空,IDI_应用程序);
注册类(win_类);
handel=CreateWindow(win_class.lpszClassName,“窗口”,WS_重叠窗口| WS_可见,100100350250,NULL,NULL,inst,NULL);
ShowWindow(handel,cmd);
更新窗口(韩德尔);
//循环不会结束。
while(GetMessage(&message,handel,0,0))
{

cout
WM_QUIT
不会发送到任何窗口,只是放置在线程的消息队列中,没有
HWND
,这就是它与您的筛选器不匹配的原因。

这里有一个很好的机会来锻炼您的“搜索MSDN文档”能力:

首先,让我们查阅以下文档:

指示终止应用程序的请求,并在 应用程序调用PostQuitMessage函数 使GetMessage函数返回零

WM_QUIT消息与窗口无关,因此将 永远不要通过窗口的窗口过程接收。它将被检索 仅通过GetMessagePeekMessage功能

然后,让我们查阅以下文档:

从调用线程的消息队列中检索消息 函数将发送传入的消息,直到发送的消息被发送为止 可供检索

hWnd[输入,可选]类型:hWnd

要检索其消息的窗口的句柄。该窗口 必须属于当前线程

如果hWnd为NULL,则GetMessage将检索任何窗口的消息 属于当前线程,以及当前线程上的任何消息 hwnd值为NULL的线程消息队列(请参阅消息 因此,如果hWnd为NULL,则窗口消息和线程 消息被处理

因此,您希望使用
NULL
作为
GetMessage()
的窗口句柄,而不是
handel
,因为
WM\u QUIT
与任何窗口都没有关联

还有来自MSDN的消息


正如旁注所述,窗口关闭事件的消息是,这反过来会导致默认情况下窗口被销毁。
WM\u DESTROY
表示您的窗口已经在被销毁的过程中。因此,如果您想要截获关闭事件(比如要求用户保存任何更改),您将处理
WM\u close
事件

另外,如
GetMessage()
文档所示,您的
GetMessage()
循环实际上应该如下所示:

BOOL bRet;

while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}
因为
GetMessage()
实际上可以返回1、0或-1(尽管它返回的是
BOOL
)。

看看MSDN中的和

如果
GetMessage
函数的
hWnd
参数为NULL,则GetMessage将检索属于当前线程的任何窗口的消息,以及当前线程消息队列中hWnd值为NULL的任何消息


PostQuitMessage函数将WM_QUIT消息发布到线程的消息队列,而不是当前窗口。

有误导性。“请注意,GetMessage始终检索WM_QUIT消息,无论您为wMsgFilterMin和wMsgFilterMax指定了哪个值。”正如这个问题和您的答案所显示的,它并不总是被检索。但是,它是否被检索并不取决于wMsgFilterMin和wMsgFilterMax。@hvd:我将该语句解释为“wMsgFilterMin和wMsgFilterMax参数不影响WM_QUIT处理”,但我同意这有误导性(或充其量是模棱两可的)。虽然我很容易看出误解,但文档是正确的。如果手动将
WM_QUIT
发布到特定窗口,则使用HWND和筛选器的代码将检索到它,即使它与筛选器不匹配。通过询问为什么传递非空句柄,可以使问题更有趣。推荐使用雷丁:(所以不,循环不需要这样。)@hvd:旧的新的东西,虽然它是一个奇妙的博客,但不是官方文档。另外,请注意,它永远不会返回-1,只有在某些情况下(尽管是最常见的,也可能是唯一合理的)。我更喜欢编写尽可能健壮的程序,而且测试-1不会有什么坏处。您的答案是将其称为
GetMessage(&msg,NULL,0,0)
,这正是在某些情况下,您永远不会得到-1的返回值。如果您想检查,也可以,我不会说您的循环是错误的,只是这里没有必要。@hvd:我同意您的看法。我希望看到文档更新以反映这一点,这样我就不必再链接到Raymond Chen的博客whe我从来没有链接到MSDN以及。