【问题标题】:How do I prevent a Win32 application from running in the background after the main window is closed?关闭主窗口后,如何防止 Win32 应用程序在后台运行?
【发布时间】:2012-03-05 17:45:48
【问题描述】:

我是 Win32 API 的初学者,但我对 C++ 有中等经验。出于学习的目的,我根据参考资料、教程和示例创建了一个非常简单的 Win32 应用程序。

问题是,在主窗口关闭后,它的进程仍然在后台运行。我怎样才能防止这种情况?在我的 WndProc 函数中,我确实有一个带有 DestroyWindow 的 WM_DESTROY 案例,但它似乎没有起到作用。代码如下:

#include <cstdio>
#include <cstdlib>

#ifdef UNICODE
#include <tchar.h>
#endif

#include <Windows.h>

HINSTANCE hinst;
HWND hwnd;

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

#ifdef UNICODE
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
#else
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
#endif
{
    MSG msg;
    WNDCLASSEX mainclass;
    BOOL bRet;
    UNREFERENCED_PARAMETER(lpCmdLine);

    mainclass.cbSize =          sizeof(WNDCLASSEX);
    mainclass.style =           CS_VREDRAW | CS_HREDRAW;
    mainclass.lpfnWndProc =     (WNDPROC) WndProc;
    mainclass.cbClsExtra =      NULL;
    mainclass.cbWndExtra =      NULL;
    mainclass.hInstance =       hInstance;
    mainclass.hIcon =           NULL;
    mainclass.hCursor =         LoadCursor(NULL, IDC_ARROW);
    mainclass.hbrBackground =   (HBRUSH) COLOR_WINDOW;
    mainclass.lpszMenuName =    NULL;
    mainclass.lpszClassName =   TEXT("MainWindowClass");
    mainclass.hIconSm =         NULL;

    if (!RegisterClassEx(&mainclass))
        return FALSE;

    hinst = hInstance;

    hwnd = CreateWindowEx(
        WS_EX_WINDOWEDGE,
        TEXT("MainWindowClass"),
        TEXT("Test Window"),
        WS_CAPTION | WS_VISIBLE | WS_SIZEBOX | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hinst,
        NULL);

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
    {
        if (bRet != -1)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    switch(uMsg)
    {
    case WM_DESTROY:
        DestroyWindow(hwnd);
        break;
    case WM_PAINT:
        BeginPaint(hwnd, &ps);
        EndPaint(hwnd, &ps);
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

【问题讨论】:

  • 您可以使用调试器来帮助您。当您关闭主窗口并且您的程序仍在运行时,暂停执行并查看调用堆栈以找出您的程序仍在忙于做什么。这可以为您提供有关程序希望您做什么以使其停止运行的线索。例如,如果您发现您的程序仍在运行消息循环,您可以安排满足循环的终止条件。
  • 这里有一个更好的参考/教程/示例:Raymond Chen's C++ scratch program。这里也是a link to the C scratch program

标签: c++ windows winapi visual-c++


【解决方案1】:

不要打电话给DestroyWindow()。该消息告诉您您的窗口已被破坏。拨打PostQuitMessage(0)退出申请。

【讨论】:

  • 其实你想让WM_CLOSE触发DestroyWindow(hwnd)。不过这可能是默认设置。
  • 啊,谢谢!我误解了 WM_DESTROY 消息的使用。 PostQuitMessage(0) 修复了它。
  • @BenVoigt 这似乎是默认设置。我不需要为明显的自动 DestroyWindow 添加这种情况。
  • 我想指出,DestroyWindow 本质上调用了 WM_DESTROY,在你的情况下它又调用了 DestroyWindow,等等。
  • 对于那些新的或不熟悉 PostQuitMessage() 的人,它是在您的消息队列中放置一个 WM_QUIT 的原因,它会导致 GetMessage() 返回 FALSE,从而终止您的主消息泵的 while() 循环。在 Visual Studio 附带的 SDK 文档中了解更多信息。
【解决方案2】:

在您的 WndProc 中为 WM_CLOSE 添加一个案例并调用 PostQuitMessage。

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  case WM_CLOSE:
  PostQuitMessage(0);
  break;
  // other cases
}

当用户单击关闭按钮(或从系统菜单)时,Windows 将发布 WM_CLOSE 消息。这将导致您的主 Windows 消息处理程序退出。这反过来将确保您的应用程序正确退出。

【讨论】:

    猜你喜欢
    • 2021-05-17
    • 2014-03-17
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多