【问题标题】:Random win32 exit code随机win32退出码
【发布时间】:2012-12-04 06:11:25
【问题描述】:

我正在尝试通过一些教程来学习 win32 API。
(不过,我做了非常小的调整来创建一个无边框的固定窗口。)

但是,我最简单的窗口应用程序退出时带有一些随机代码。
我不知道为什么它没有以代码“0”退出。

有关更多信息,我使用的是 Visual Studio 2012 Pro。
源代码的文件扩展名为 .c,编译器设置可能是默认设置。
我将该项目创建为一个空的 win32 应用程序(不是控制台)。

请提供一些帮助。
谢谢。

#include <Windows.h>
#include <windowsx.h>

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

int __stdcall WinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPSTR lpCmdLine,
                      INT nCmdShow) {
    HWND hWnd;
    WNDCLASSEX wcex;
    MSG msg;

    ZeroMemory(&wcex, sizeof(WNDCLASSEX));

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc  = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"WindowClass1";
    wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wcex))
    {
        MessageBox(
            NULL,
            L"Failed to register window!",
            L"ERROR",
            MB_OK | MB_ICONEXCLAMATION);
        return EXIT_FAILURE;
    }

    hWnd = CreateWindowEx(
        0,
        L"WindowClass1",
        L"Application",
        WS_POPUP,
        0, 0,
        GetSystemMetrics(SM_CXSCREEN),
        GetSystemMetrics(SM_CYSCREEN),
        NULL, NULL, hInstance, NULL);


    if (hWnd == NULL)
    {
        MessageBox(
            NULL,
            L"Failed to create window!",
            L"ERROR",
            MB_OK |  MB_ICONEXCLAMATION);
        return EXIT_FAILURE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, hWnd, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
    case WM_CLOSE:
        DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }

    return 0;
}

【问题讨论】:

  • 您能说明您是如何读取退出代码的吗?
  • 在我使用 alt+f4 关闭窗口后,Visual Studio 中的输出窗口会告诉我我的应用程序以哪个退出代码终止。

标签: c winapi


【解决方案1】:

在您的程序中,GetMessage 实际上返回了-1,这是一个错误条件。当GetMessage 返回值GetMessage 返回-1 时它终止。

现在,由于对 GetMessage 的最终调用失败并出现错误,msg.wParam 的值没有明确定义。您不应将其作为退出代码返回。当对 GetMessage 的最终调用返回 0 时,您应该只返回 msg.wParam 作为退出代码。这一切都在 documentation 中明确说明。

如果您将消息循环更改为如下所示,您可以看到所有这些:

while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        return GetLastError();
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

return msg.wParam;

在我的机器上,bRet == -1 路由被选中,错误代码为 1400。即ERROR_INVALID_WINDOW_HANDLE。我不太确定您的应用为什么会出现这种行为,但我很满意我已经回答了您提出的有关退出代码的问题!

【讨论】:

  • 这已经很晚了,但 GetMessage 不应该是 GetMessage(&msg, 0, 0, 0) 吗?如果我对它使用 HWND,我会遇到问题。
【解决方案2】:

除了用空白窗口覆盖整个屏幕,需要使用 ALT-F4 退出您的应用程序之外,一切看起来都不错,除了一件事:

GetMessage,尽管声称返回 'BOOL' 实际上返回 int:成功时返回一些正值,接收到 WM_QUIT 时返回 0,出错时返回 -1。出于这个原因,Microsoft 从 GetMessage(和其他函数)返回“BOOL plus a lil' something something”的政策是愚蠢和危险的,因此应该受到惩罚。

如果 GetMessage 返回 -1 则 msg 的内容可能有效也可能无效;换句话说,wParam 可能为零,也可能是potato。这可能会转化为您看到的“随机”退出代码。

我建议这样:

int nRet;

do
{
    nRet = GetMessage(&msg, hWnd, 0, 0);

    if(nRet == -1)
        return GetLastError();

    if(nRet != 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
} while(nRet != 0);

return msg.wParam;

【讨论】:

  • 谢谢!但我相信大卫首先回答了这个问题。
  • 不客气。第一个或第二个无关紧要 - 重要的是你得到了你需要的答案。
  • 尼克是对的。你应该接受最好的答案,而不是最快的。在这种情况下,它们看起来几乎完全相同!
  • @DavidHeffernan:我并不是那个意思(尽管我确实认为应该接受最佳答案)。我的意思是我不介意让“接受”或“第一个”发帖。如果有人从我或其他人那里得到他们需要的答案,我很满意。是的,有趣的是我们的答案几乎相同。
  • 我没有看错。我确实经常看到草率的快速答案被接受,而不是更有价值的答案,这些答案必然需要更长的时间来写。这就是我的意思。
猜你喜欢
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多