如何正确处理 win32 GUI 消息循环
How to properly handle a win32 GUI message loop?
我正在制作一个简单的文本编辑器win32应用程序。我的程序遇到了一个特殊的问题。似乎我的程序在退出时没有返回零。相反,它正在返回1385929。当我的主 GUI 窗口被破坏时,我使用 PostQuitMessage( 0 )
,但似乎这不是我的主函数message.wParam
中返回的内容。这是我到目前为止的代码,
#define WIDTH 500
#define HEIGHT 400
#define EDIT_ID 10
LRESULT CALLBACK windowProc( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
{
static HDC deviceContext = INVALID_HANDLE_VALUE;
static HWND editControl = INVALID_HANDLE_VALUE;
switch ( message )
{
case WM_CREATE :
deviceContext = GetDC( window );
if ( !deviceContext )
{
showWindowsError( "Creating Device Context", FALSE );
DestroyWindow( window );
}
editControl = CreateWindow(
"EDIT",
NULL,
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT |
ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL,
0,
0,
0,
0,
window,
( HMENU )EDIT_ID,
( HINSTANCE )GetWindowLong( window, GWL_HINSTANCE ),
NULL
);
if ( !editControl )
{
showWindowsError( "Creating Edit Control", TRUE );
DestroyWindow( window );
}
return 0;
break;
case WM_COMMAND :
switch ( wParam )
{
case WM_UNDO :
SendMessage( editControl, WM_UNDO, 0, 0 );
break;
case WM_CUT :
SendMessage( editControl, WM_CUT, 0, 0 );
break;
case WM_COPY :
SendMessage( editControl, WM_COPY, 0, 0 );
break;
case WM_PASTE :
SendMessage( editControl, WM_PASTE, 0, 0 );
break;
case WM_CLEAR :
SendMessage( editControl, WM_CLEAR, 0, 0 );
break;
default:
return DefWindowProc( window, message, wParam, lParam );
}
case WM_SIZE :
MoveWindow( editControl, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );
return 0;
break;
case WM_DESTROY :
ReleaseDC( window, deviceContext );
DestroyWindow( editControl );
PostQuitMessage( 0 );
return 0;
break;
}
return DefWindowProc( window, message, wParam, lParam );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR CmdArgs, int nCmdShow )
{
WNDCLASSEX windowClass = { 0 };
HWND window = INVALID_HANDLE_VALUE;
MSG message = { 0 };
HBRUSH windowColor = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
windowClass.cbSize = sizeof( windowClass );
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = windowProc;
windowClass.hInstance = hInstance;
windowClass.hCursor = LoadCursor( NULL, IDC_ARROW );
windowClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
windowClass.hbrBackground = windowColor;
windowClass.lpszClassName = "TextEditorWindow";
if ( !RegisterClassEx( &windowClass ) )
{
DeleteObject( windowColor );
showWindowsError( "Registering Windows Class", TRUE );
}
window = CreateWindow(
"TextEditorWindow",
"Text Editor",
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
WIDTH,
HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
if ( !window )
{
DeleteObject( windowColor );
showWindowsError( "Creating GUI", TRUE );
}
ShowWindow( window, SW_SHOW );
UpdateWindow( window );
do
{
TranslateMessage( &message );
DispatchMessage( &message );
} while ( GetMessage( &message, window, 0, 0 ) > 0 );
DeleteObject( windowColor );
return message.wParam;
}
您对 GetMessage()
的调用将第二个参数设置为窗口的HWND
,这将接收的消息限制为仅发送到该窗口的消息 - 请参阅 API 函数的文档。
另一方面,WM_QUIT
是发送到运行消息泵的线程的消息,没有任何特定的窗口。由于该过滤器,您不会收到它,并且message.wParam
永远不会设置为该0
。
但是为什么循环结束并且程序仍然关闭?由于window
中的HWND
在窗口关闭后无效,因此GetMessage()
以错误结尾并返回-1
。
此外,您当前正在调用 TranslateMessage()
并在第一次迭代中用 message
填充任何正确的数据之前使用它DispatchMessage()
。循环应该是这样的:
while ( GetMessage( &message, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &message );
DispatchMessage( &message );
}
相关文章:
- OpenGL 的 Win32 主消息循环
- Winapi:可以通过异步程序调用中断消息循环
- WinApi消息循环,Postmessage的工作原理与SendMessage类似
- 如何从VCL项目的消息循环中调用其他功能
- Win32 消息循环 - 我应该中断还是返回
- WinAPI设备通知-未进入消息循环
- SetWindowsHookEx忽略来自消息循环的PostMessage
- 相对于 3D 应用程序中的 Windows 消息循环的计时错误
- infine windows消息循环-c++
- EDSDK消息循环在Windows 8.1下不起作用
- Sleep() in Windows 消息循环
- 对话框消息是否发送到自定义消息循环
- 是否可以捕获翻译/调度消息循环中的窗口消息/事件
- 为什么会有这种行为 - 我的全局钩子与消息循环一起使用,但不适用于空循环
- C++ WTL8.1 如何在具有消息循环的新线程中创建窗口
- WINAPI的消息循环让我发疯
- WinAPI-带有自己回调的消息循环
- WinProc()与主消息循环
- CAppModule与CAtlExeModuleT,获取应用程序消息循环
- 当挂接 Windows 的消息循环时,KBDLLHOOKSTRUCT 的 dwExtraInfo 有什么用