【问题标题】:Is possible run window application without message loop可以在没有消息循环的情况下运行窗口应用程序
【发布时间】:2013-12-03 06:07:20
【问题描述】:

我有一个非常旧的应用程序,我很惊讶。此应用程序在没有消息循环的情况下运行。 (GetMessagePeekMessage)。

这怎么可能?

从 Visual Studio 编辑的示例:

HINSTANCE g_hInstance = NULL;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);

ATOM _RegisterClass(HINSTANCE hInstance);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    _RegisterClass(hInstance);

    InitInstance(hInstance, SW_NORMAL);

    return 0;
}

ATOM _RegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXA wcex = {0};
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_SAVEBITS;
    wcex.lpfnWndProc    = WndProc;
    wcex.hInstance      = hInstance;
    wcex.lpszClassName  = "TEST_CLASS";

    ATOM a = 0;

    a =  RegisterClassExA(&wcex);

    return a;
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd;

    g_hInstance = hInstance; // Store instance handle in our global variable

    hWnd = CreateWindowA("TEST_CLASS", "TEST_WINDOW", WS_OVERLAPPEDWINDOW,
        0, 0, 0, 0, NULL, NULL, hInstance, NULL);

    if (!hWnd)
    {
        return FALSE;
    }

     SendMessageW(hWnd, WM_USER, 111, 0);

    return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_CREATE:
        OutputDebugStringA("Create called.\n");
        break;

case WM_USER:
    {
        if (wParam == 111)
        {

            OutputDebugStringA("User called.\n");
        }
    }
            break;

    case WM_DESTROY:
        OutputDebugStringA("Destroy called.\n");
        break;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

调试输出:

创建调用。 用户调用。 销毁调用。 程序“[2152] Test.exe: Native”已退出,代码为 0 (0x0)。

【问题讨论】:

  • 应用程序是否创建窗口?
  • 是的,当然要创建窗口。
  • 它是用什么语言编写的?它使用什么框架?它是如何创建它的主窗口的?
  • 这是不可能的,只是你还没有发现它是如何做到的。要么是 DOS 应用程序,要么是 DOS 应用程序,您将命令窗口误认为是 Windows 窗口。
  • 它在不显示窗口的情况下运行并完成。我看不到任何消息处理。 WM_CREATE 作为CreateWindow 的结果传递给您的WindowProc,但这并不意味着您有一个消息循环。

标签: c windows winapi message-queue


【解决方案1】:

这是预期的行为。

CreateWindow 调用SendMessageWM_NCCREATEWM_CREATE 发送到正在创建的窗口。 SendMessage 的行为如下(引用自 MSDN):

如果指定的窗口是由调用线程创建的,则窗口过程作为子程序立即被调用。

您的程序调用CreateWindow,它随后调用您的窗口过程(在WM_CREATE 上输出“创建调用”)然后返回。它验证窗口句柄是非空的,这是这种情况,并返回退出代码 0 而不是进入消息泵。
它不会输出“Destroy called”(如您所料),因为这没有发生。窗口没有被销毁(好吧,最终是,由操作系统),程序只是退出。

关于修改后的代码:
新代码的不同之处在于调用SendMessageW,它再次直接调用窗口过程。因此,虽然没有消息泵,但还是收到了用户消息。
似乎破坏消息现在也通过了,这无疑有点令人惊讶。不知道是什么原因。

请注意,该窗口是使用“A”函数创建的,因此通常不建议调用“W”函数(即使它似乎在这里“工作”)。

【讨论】:

  • 有趣,看我编辑的例子,还是没有循环,那么WM_USER是怎么传递的?
  • > WM_USER 是如何交付的? ;您正在直接发送消息。尝试用PostMessage发消息,会看到收不到消息。
猜你喜欢
  • 2012-05-21
  • 2010-10-30
  • 1970-01-01
  • 2019-01-27
  • 2022-01-09
  • 1970-01-01
  • 2016-03-24
  • 2011-05-03
  • 1970-01-01
相关资源
最近更新 更多