WM_TIMER 已调用消息但未设置计时器
WM_TIMER message called but no timer set
我正在 Visual Studio Express 2013 中编写一个相当简单的 windows C++ 应用程序,并且在启动时遇到一个问题 window 由于 DispatchMessage 挂起 5-10 秒处理 WM_TIMER 消息。问题是,我从未创建过计时器,所以我不确定为什么会收到消息,也不知道为什么会出现这么长时间的挂起。
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 );
}
抱歉所有代码,我不确定其中有多少是相关的。大多数这些功能都封装在一个应用程序 class 中,我的 WinMain 函数创建了一个 class 的实例,调用 InitWindows() 和 运行()。它挂起的地方是在 MessagePump 函数中,在 DispatchMessage() 处。 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;
这可以阻止挂起,但随后会产生另一个问题,当我移动 window 时,我的整个 OS 会冻结大约 5-10 秒。
我已经编程了一段时间(绝不是专家)但这让我感到困惑。任何帮助表示赞赏。谢谢!
编辑:
我尝试在另外两台机器上构建和 运行。两者都没有挂。原机重启几次,去掉我觉得不需要的启动进程后,问题终于解决了,运行了~50次后问题依旧。我希望报告是哪个进程导致了它更令人满意,但我仍然没有弄清楚。
查看模块window地址75C3A95C没有进程,奇怪。
不过我注意到了一些事情:在所有机器上,WM_TIMER 消息都在传递。此外,即使使用您可以在 VS2013 Exp 中创建的默认项目 Win32Project1,也会传递这 3 WM_TIMER 条消息。此外,Win32Project1 did 也挂起,所以它确实与我的代码无关,但我猜......与我机器中的进程 运行 有一些奇怪的交互?
感谢大家的帮助。
也许另一个 运行 程序正在向您发送 WM_TIMER 消息,或者可能是您正在链接的库。在另一台干净的机器上尝试 运行。
我正在 Visual Studio Express 2013 中编写一个相当简单的 windows C++ 应用程序,并且在启动时遇到一个问题 window 由于 DispatchMessage 挂起 5-10 秒处理 WM_TIMER 消息。问题是,我从未创建过计时器,所以我不确定为什么会收到消息,也不知道为什么会出现这么长时间的挂起。
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 );
}
抱歉所有代码,我不确定其中有多少是相关的。大多数这些功能都封装在一个应用程序 class 中,我的 WinMain 函数创建了一个 class 的实例,调用 InitWindows() 和 运行()。它挂起的地方是在 MessagePump 函数中,在 DispatchMessage() 处。 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;
这可以阻止挂起,但随后会产生另一个问题,当我移动 window 时,我的整个 OS 会冻结大约 5-10 秒。
我已经编程了一段时间(绝不是专家)但这让我感到困惑。任何帮助表示赞赏。谢谢!
编辑: 我尝试在另外两台机器上构建和 运行。两者都没有挂。原机重启几次,去掉我觉得不需要的启动进程后,问题终于解决了,运行了~50次后问题依旧。我希望报告是哪个进程导致了它更令人满意,但我仍然没有弄清楚。
查看模块window地址75C3A95C没有进程,奇怪。
不过我注意到了一些事情:在所有机器上,WM_TIMER 消息都在传递。此外,即使使用您可以在 VS2013 Exp 中创建的默认项目 Win32Project1,也会传递这 3 WM_TIMER 条消息。此外,Win32Project1 did 也挂起,所以它确实与我的代码无关,但我猜......与我机器中的进程 运行 有一些奇怪的交互?
感谢大家的帮助。
也许另一个 运行 程序正在向您发送 WM_TIMER 消息,或者可能是您正在链接的库。在另一台干净的机器上尝试 运行。