WM_TIMER消息称为,但没有计时器集

WM_TIMER message called but no timer set

本文关键字:计时器 TIMER 消息 WM      更新时间:2023-10-16

我正在在Visual Studio Express 2013中编写一个相当简单的Windows C 应用程序,并且在启动时,由于处理WM_TIMER消息的dispatchMessage处理,窗口悬挂了5-10秒。问题是,我从来没有创建过计时器,所以我不确定为什么要收到消息,也不知道为什么有这么长的挂起。

enum KRESULT
{
    K_OK,
    K_FALSE,
    K_QUIT
};
HINSTANCE g_hInstance;
HWND g_hWnd;
char* g_winName;
char* g_name;
KRESULT MessagePump( MSG &msg )
{
    if( !PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
    {
        // there weren't any messages
        return K_FALSE;
    }
    else
    {
        if( msg.message == WM_QUIT )
            return K_QUIT;
        if( msg.message == WM_CLOSE )
            return K_QUIT;
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    } 
    return K_OK;
}
void Run()
{
    MSG msg;
    bool done = false;
    while( !done )
    {
        KRESULT msgRes = K_OK;
        while( msgRes != K_FALSE )
        {
            msgRes = MessagePump( msg );
            if( msgRes == K_QUIT )
            {
                done = true;
                break;
            }
            done = !DoFrame();
        }
    }
}
bool DoFrame()
{
    // do a bunch of stuff, disabled for debugging.
    // returns false if Esc is pressed
    return true;
}
LRESULT CALLBACK MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch( uMsg )
    {
    // Code managing WM_SIZE, WM_ENTERSIZEMOVE, etc that has to do with changing the size of the window.
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    bool bRunDefault = false;
    switch( uMsg )
    {
        // check if the window is being destroyed.
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
            // check if the window is being closed.
            case WM_CLOSE:
            {
                PostQuitMessage(0);     
                return 0;
            }
            default:
            {
                bRunDefault = true;
                break;
            }
        }
    }
    if( bRunDefault )
        return MessageHandler(hWnd, uMsg, wParam, lParam);
    return 0;
}
void InitWindows()
{
    WNDCLASSEX wc;
    DEVMODE dmScreenSettings;
    int posX, posY;
    // get the instance of this application
    g_hInstance = GetModuleHandle(NULL);
    // setup the windows class with some default settings
    wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = g_hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
    wc.hIconSm       = wc.hIcon;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_name;
    wc.cbSize        = sizeof(WNDCLASSEX);
    // register the window class
    RegisterClassEx(&wc)
    // determine the resolution of the client desktop screen
    int screenWidth  = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
    int wWidth = 1366;
    int wHeight = 768;
    DWORD styleFlags;
    // place it in the middle of the screen
    posX = ( screenWidth - wWidth ) / 2;
    posY = ( screenHeight - wHeight ) / 2;
    styleFlags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
    // create the window with the screen settings and get the handle
    g_hWnd = CreateWindowEx( WS_EX_APPWINDOW, g_name, g_winName, styleFlags,
                             posX, posY, wWidth, wHeight, NULL, NULL,
                             g_hInstance, NULL );
    // bring the window up on the screen and set it as main focus
    ShowWindow( g_hWnd, SW_SHOW );
    SetForegroundWindow( g_hWnd );
    SetFocus( g_hWnd );
    // mouse cursor options
    ShowCursor( true );
}

对不起所有代码,我不确定其中有多少相关。这些功能大多数都封装在应用程序类中,我的Winmain函数创建了类的实例,调用initwindows()和run()。挂在messagePump函数中的位置,在dispatchMessage()。WM_TIMER MSG传递了两次,每个MSG都带有以下参数:

hwnd = 0x00000000 <NULL>
message = 275 (WM_TIMER)
wParam = 18876 (this is random, but varies from around 18000 to 22000 or so)
lParam = 1975757148 (this is always the same)

然后,它通过wparam = 1传递一次,lparam = 0。总是按此顺序进行,这三个WM_Timer消息每几个帧都调用。

悬挂仅发生一次,这是在开始时第一次传递消息。

悬挂在调试模式下是最糟糕的,但是在发布构建中,也发生了。

我可以在MessagePump函数中添加一个处理程序,例如:

if( msg.message == WM_TIMER )
    return K_OK;

这可以停止悬挂,但随后会产生另一个问题,当我移动窗口时,整个操作系统会冻结约5-10秒。

我已经编程了一段时间(绝不是专家),但这让我感到困惑。任何帮助都将受到赞赏。谢谢!

编辑:我尝试在另外两台机器上建造和运行。两者都不挂。在重新启动了原始机器的几次重新启动之后,删除了我觉得自己不需要的启动过程,问题终于停止了,即使经过约50次运行,问题也还不错。我希望报告哪个过程引起了它更令人满意,但我仍然没有弄清楚。

查看模块窗口时的地址75C3A95C没有过程。

我注意到的东西:在所有机器上,WM_TIMER消息都在传递。此外,即使使用默认项目,您也可以在VS2013 EXP(Win32Project1)中创建,这3个WM_TIMER消息也会传递。另外,win32project1 也挂了,所以它确实与我的代码无关,但是我想...与我的机器中运行的过程有些奇怪的互动?

感谢大家的帮助。

也许另一个运行程序正在向您的WM_TIMER消息发送您的WM_TIMER消息,或者您正在链接的库。尝试在另一台干净的机器上运行。