已调用WM_TIMER消息但未设置计时器

时间:2015-05-07 22:58:51

标签: c++ visual-studio-2013 timer

我在Visual Studio Express 2013中编写了一个相当简单的Windows C ++应用程序,并且在启动时由于DispatchMessage处理WM_TIMER消息而导致窗口挂起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 );
}

对所有代码感到抱歉,我不确定其中有多少是相关的。大多数这些函数都封装在一个app类中,我的WinMain函数创建了一个类的实例,调用了InitWindows()和Run()。它挂起的位置在DispatchMessage()的MessagePump函数中。 WM_TIMER消息传递两次,每次都带有以下参数:

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 确实也挂了,所以它与我的代码无关,但我想......与我机器中运行的进程有一些奇怪的交互?

感谢大家的帮助。

1 个答案:

答案 0 :(得分:0)

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

相关问题