C++ - 窗口消息循环冻结

发布于 2024-09-26 03:29:52 字数 4003 浏览 0 评论 0原文

我这里有这门课,是我根据我的另一门课制作的。它应该处理整个创建窗口和其他东西,但现在似乎陷入了困境。旧版本曾经工作正常,我不知道我可能忘记添加什么内容到这个版本中,这可能会导致它像这样挂起。

这是消息循环:

int Window::HandleMessages()
{
    while(GetMessage(&this->windat.msgs, NULL, 0, 0))
    {
        TranslateMessage(&this->windat.msgs);
        DispatchMessage(&this->windat.msgs);
    }
    return this->windat.msgs.wParam;
}

非常基本的东西,我不知道为什么,但它会简单地挂起......当我运行程序时,它只会向我显示一个空的提示窗口,通过测试,我得到了它如果我在 while 循环之前使用它,则会显示一个消息框,但在它内部不起作用。我一直在尝试比较这个类和旧的类,但还没有弄清楚这可能有什么问题。谁能告诉我什么可能会触发这种行为? 谢谢


,好的,现在这让我很困惑。通过搞乱 GetLastError,它似乎在我把它放在任何地方都返回错误 2(文件未找到),即使是在 Main 的开头,在我实例化 Window 类之前。如果我在 CreateWindowEx 之后的任何时候调用 GetLastError ,它都会返回一个错误,例如 1047 之类的,关于找不到类之类的错误。 HWND 也变成 NULL
这是 main.cpp 的代码:

#include "SimpWin/SimpWin.h"
#include <stdio.h>

//  Make the class name into a global variable
char szClassName[] = "WindowsApp";


void ErrorExit(LPTSTR lpszFunction)
{
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message and exit the process

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
        (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
    sprintf((char*)lpDisplayBuf,
        TEXT("%s failed with error %d: %s"),
        lpszFunction, dw, lpMsgBuf);
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    ExitProcess(dw);
}

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

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    ErrorExit(TEXT("CreateWindowEx"));
    Window* win = Window::CreateWindowClass(hThisInstance, szClassName, WindowProcedure);
    if(!win->Register())
    {
        return 0;
    }


    win->Show(nFunsterStil);

    int res = win->HandleMessages();

    delete win;

    return res;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc (hwnd, message, wParam, lParam);
}

这是 Window::Register 函数的代码:

int Window::Register()
{
    if(this->windat.wincl.hIcon == NULL)
    {
        this->windat.wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    }
    if(this->windat.wincl.hIconSm == NULL)
    {
        this->windat.wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    }

    if(!RegisterClassEx(&this->windat.wincl))
    {
        return 0;
    }



    this->windat.hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           (char*) this->windat.sName,                  /* Classname */
           (char*) this->windat.sTitle,       /* Title Text */
           WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           this->windat.cDimension.width,         /* The programs width */
           this->windat.cDimension.height,        /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           this->windat.hInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    return 1;
}

我在这里迷路了,我不知道为什么会发生这种情况... :/

I have this class here that I made based on another one I had. It is supposed to handle the whole creating windows and stuff, but it seems to be getting into a hang now. The older version used to work fine, I don't know WHAT I may have forgotten to add to this one that might be causing it to hang like this.

This is the message loop:

int Window::HandleMessages()
{
    while(GetMessage(&this->windat.msgs, NULL, 0, 0))
    {
        TranslateMessage(&this->windat.msgs);
        DispatchMessage(&this->windat.msgs);
    }
    return this->windat.msgs.wParam;
}

Pretty basic stuff, I don't know why, but it will simply hang... When I run the program, it'll just show me an empty prompt window, and by testing, I got it to show a message box if I used it before the while loop, but inside it doesn't work. I've been trying to compare both this class and the older one and haven't figured out what might be wrong with this. Could anyone tell me what could possibly trigger this behaviour?
Thanks


OK, now this left me pretty confused. By messing around with GetLastError, it seems that it is returning error 2 (file not found) ANYWHERE I put it, even if right at the start of the Main, before I instantiate my Window class. If I call GetLastError anytime after CreateWindowEx, it'll return an error like 1047 or something, about class not found or something. HWND becomes NULL too
Here is the code for the main.cpp:

#include "SimpWin/SimpWin.h"
#include <stdio.h>

//  Make the class name into a global variable
char szClassName[] = "WindowsApp";


void ErrorExit(LPTSTR lpszFunction)
{
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message and exit the process

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
        (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
    sprintf((char*)lpDisplayBuf,
        TEXT("%s failed with error %d: %s"),
        lpszFunction, dw, lpMsgBuf);
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    ExitProcess(dw);
}

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

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    ErrorExit(TEXT("CreateWindowEx"));
    Window* win = Window::CreateWindowClass(hThisInstance, szClassName, WindowProcedure);
    if(!win->Register())
    {
        return 0;
    }


    win->Show(nFunsterStil);

    int res = win->HandleMessages();

    delete win;

    return res;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc (hwnd, message, wParam, lParam);
}

This here, is the code for the Window::Register function:

int Window::Register()
{
    if(this->windat.wincl.hIcon == NULL)
    {
        this->windat.wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    }
    if(this->windat.wincl.hIconSm == NULL)
    {
        this->windat.wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    }

    if(!RegisterClassEx(&this->windat.wincl))
    {
        return 0;
    }



    this->windat.hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           (char*) this->windat.sName,                  /* Classname */
           (char*) this->windat.sTitle,       /* Title Text */
           WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           this->windat.cDimension.width,         /* The programs width */
           this->windat.cDimension.height,        /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           this->windat.hInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    return 1;
}

I'm lost here, I don't know why the eff this is going on... :/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

去了角落 2024-10-03 03:29:52

检查GetMessage() 的返回值 - 如果出现错误,您的 while 循环将不会退出。它应该看起来像这样:

while (GetMessage(&this->windat.msgs, NULL, 0, 0) > 0)
{
 ...
}

Check the return value to GetMessage() - your while loop won't exit if there are errors. It should look like this:

while (GetMessage(&this->windat.msgs, NULL, 0, 0) > 0)
{
 ...
}
一场春暖 2024-10-03 03:29:52

尽管它很旧......来自 MSDN 上的 GetMessage

GetMessage 不同,PeekMessage 函数在返回之前不会等待消息发布。

也就是说,GetMessage 等待下一条消息可用。您将正在进行的等待视为冻结,据说是因为您实际上并不打算等待消息。

请注意,您可以在假定冻结时附加调试器,暂停执行并检查线程的调用堆栈。一旦您找到您的线程及其调用堆栈以及堆栈上正在进行的 GetMessage - 您就可以很好地隔离问题,以便知道在哪里阅读记录的行为。

Even though it's pretty old... from MSDN on GetMessage:

Unlike GetMessage, the PeekMessage function does not wait for a message to be posted before returning.

That is, GetMessage waits for next message to become available. You treat this wait in progress as a freeze, supposedly because you did not actually have the intention to wait for messages.

Note that you can attach debugger at the time of supposed freeze, pause the execution and inspect the call stacks of the threads. Once you find your thread and its call stack and its GetMessage in progress on the stack - you isolate the problem well enough to know where to read on documented behavior.

梦醒灬来后我 2024-10-03 03:29:52

使用 PeekMessage 而不是 GetMessage。

Use PeekMessage instead of GetMessage.

疾风者 2024-10-03 03:29:52

好吧,我终于成功了! :D

它实际上与我在这里上的一个完全不相关的课程有关。它是我制作的一个 String 类(从 Array 派生),并且复制函数有一个错误,它会复制我传递给它的字符数组,但不会更新该类的长度字段......
每当我必须通过operator=将类设置为一个值时,就会调用该复制函数。运算符 char* 需要该长度才能将类转换为 C 格式字符串。当将 ClassName 和 Title 值传递给 CreateWindowEx 时,我会使用该转换,它会返回一个包含 0 个字符的数组,这就是地狱发生的地方。
现在我修复了该库,现在工作正常。谢谢:D

Well, I finally got it working! :D

It actually had to do with a completely unrelated class I had here. It is a String class (which descended from Array) which I made, and the copy function had a bug, it would copy the character array I passed to it, but would not update the length field of the class...
That copy function would be called whenever I had to set the class to a value through operator=. The length is required for the operator char* to convert the class to c-format string. I'd use that cast when passing the ClassName and Title values to CreateWindowEx, and it would return me an array of 0 chars, and that's where hell happened.
Now I fixed that lib up, and it's working fine now. Thanks :D

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文