创建消息循环(Creating a Message Loop)
系统自动为每个线程创建一个消息队列。如果一个线程创建一个或多个窗口,那么不需提供一个消息循环。这个消息循环从线程消息队列中获取消息并把这些消息发配给合适的窗口过程。
因为系统为程序中单个的窗口指定消息,一个线程必须至少创建一个窗口在开始它的消息循环之前。大部分Win32程序包含只一个线程来创建窗口。一个典型的应用程序为它的主窗口注册窗口类,创建并显示主窗口,之后开始消息循环——以上这些是在WinMain函数中。
你可以创建利用GetMessage和DispatchMessage函数创建一个消息循环。如果你的应用程序必须包含字符输入,那么在消息循环中要包括TranslateMessage函数。TranslateMessage函数把虚拟键(virtual-key)消息转换成字符消息。下面的例子显示了一个简单Win32程序的WinMain函数中的消息循环。
HINSTANCE hinst;
HWND hwndMain;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wc;
UNREFERENCED_PARAMETER(lpszCmdLine);
// Register the window class for the main window.
if (!hPrevInstance)
{
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "MainMenu";
wc.lpszClassName = "MainWndClass";
if (!RegisterClass(&wc))
return FALSE;
}
hinst = hInstance; // save instance handle
// Create the main window.
hwndMain = CreateWindow("MainWndClass",
"Sample",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
(HWND) NULL,
(HMENU) NULL,
hinst,
(LPVOID) NULL);
// If the main window cannot be created, terminate
// the application.
if (!hwndMain)
return FALSE;
// Show the window and paint its contents.
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
// Start the message loop.
while (GetMessage(&msg, (HWND) NULL, 0, 0)>0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Return the exit code to the system.
return msg.wParam;
}
下面的例子是关于一个使用快捷键并显示非模态对话框的线程的消息循环。当TranslateAccelerator或IsDialogMessage函数返回TRUE(这表明消息已经被处理)时,TranslateMessage和DispatchMessage函数不会被调用。这是因为TranslateMessage和IsDialogMessage函数执行了必要的转换和分配。
HWND hwndMain;
HWND hwndDlgModeless = NULL;
MSG msg;
HACCEL haccel;
// Perform initialization and create a main window.
while (GetMessage(&msg, (HWND) NULL, 0, 0)>0)
{
if (hwndDlgModeless == (HWND) NULL ||
!IsDialogMessage(hwndDlgModeless, &msg) &&
!TranslateAccelerator(hwndMain, haccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
系统自动为每个线程创建一个消息队列。如果一个线程创建一个或多个窗口,那么不需提供一个消息循环。这个消息循环从线程消息队列中获取消息并把这些消息发配给合适的窗口过程。
因为系统为程序中单个的窗口指定消息,一个线程必须至少创建一个窗口在开始它的消息循环之前。大部分Win32程序包含只一个线程来创建窗口。一个典型的应用程序为它的主窗口注册窗口类,创建并显示主窗口,之后开始消息循环——以上这些是在WinMain函数中。
你可以创建利用GetMessage和DispatchMessage函数创建一个消息循环。如果你的应用程序必须包含字符输入,那么在消息循环中要包括TranslateMessage函数。TranslateMessage函数把虚拟键(virtual-key)消息转换成字符消息。下面的例子显示了一个简单Win32程序的WinMain函数中的消息循环。
HINSTANCE hinst;
HWND hwndMain;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wc;
UNREFERENCED_PARAMETER(lpszCmdLine);
// Register the window class for the main window.
if (!hPrevInstance)
{
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "MainMenu";
wc.lpszClassName = "MainWndClass";
if (!RegisterClass(&wc))
return FALSE;
}
hinst = hInstance; // save instance handle
// Create the main window.
hwndMain = CreateWindow("MainWndClass",
"Sample",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
(HWND) NULL,
(HMENU) NULL,
hinst,
(LPVOID) NULL);
// If the main window cannot be created, terminate
// the application.
if (!hwndMain)
return FALSE;
// Show the window and paint its contents.
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
// Start the message loop.
while (GetMessage(&msg, (HWND) NULL, 0, 0)>0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Return the exit code to the system.
return msg.wParam;
}
下面的例子是关于一个使用快捷键并显示非模态对话框的线程的消息循环。当TranslateAccelerator或IsDialogMessage函数返回TRUE(这表明消息已经被处理)时,TranslateMessage和DispatchMessage函数不会被调用。这是因为TranslateMessage和IsDialogMessage函数执行了必要的转换和分配。
HWND hwndMain;
HWND hwndDlgModeless = NULL;
MSG msg;
HACCEL haccel;
// Perform initialization and create a main window.
while (GetMessage(&msg, (HWND) NULL, 0, 0)>0)
{
if (hwndDlgModeless == (HWND) NULL ||
!IsDialogMessage(hwndDlgModeless, &msg) &&
!TranslateAccelerator(hwndMain, haccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}