Система автоматически создает очередь обработки сообщений для каждого потока. Если поток создает одно или несколько окон, должен быть предусмотрен цикл обработки сообщений; этот цикл извлекает сообщения из очереди сообщений потока и распределяет их соответствующим оконным процедурам.
Поскольку система направляет сообщения конкретным окнам в прикладной программе, поток должен создать по крайней мере одно окно перед стартом своего цикла обработки сообщений. Большинство прикладных программ содержат единственный поток, который создает окна. Типичная прикладная программа регистрирует класс окна для своего главного окна, создает и показывает главное окно, а затем запускает свой цикл обработки сообщений - это все в функции WinMain .
Вы создаете цикл обработки сообщений, при помощи использования функции GetMessage и DispatchMessage. Если ваша прикладная программа должна получать символьный ввод информации от пользователя, включите в цикл функцию TranslateMessage. TranslateMessage переводит сообщения виртуальных клавиш в символьные сообщения. Следующий пример показывает цикл обработки сообщений в функции WinMain простого базирующегося на Windows приложения.
Демонстрационный пример
HINSTANCE hinst; HWND hwndMain; int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; BOOL bRet; WNDCLASS wc; UNREFERENCED_PARAMETER(lpszCmdLine); // Регистрируем класс окна для главного окна. 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; // сохраним дескриптор экземпляра // Создаем главное окно. hwndMain = CreateWindow("MainWndClass", "Sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND) NULL, (HMENU) NULL, hinst, (LPVOID) NULL); // Если главное окно не может быть создано, завершаем // работу приложения. if (!hwndMain) return FALSE; // Показываем окно на экране и прорисовываем его содержимое. ShowWindow(hwndMain, nCmdShow); UpdateWindow(hwndMain); // Запускаем цикл обработки сообщений. while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { if (bRet == -1) { // обрабатываем ошибку и возможно прерываем работу программы } else { TranslateMessage(&msg); DispatchMessage(&msg); } } // Возвращаем значение кода выхода из программы в систему. return msg.wParam; } |
Следующий пример показывает цикл обработки сообщений для потока, который использует клавиши - ускорители и отображает немодальное диалоговое окно. Когда функция TranslateAccelerator или IsDialogMessage возвращают значение ИСТИНА (TRUE) (показывая, что сообщение было обработано), TranslateMessage и DispatchMessage не вызываются. Причиной для этого является то, что TranslateAccelerator и IsDialogMessage исполняют всю необходимую трансляцию и диспетчеризацию сообщений самостоятельно.
Демонстрационный пример
HWND hwndMain; HWND hwndDlgModeless = NULL; MSG msg; BOOL bRet; HACCEL haccel; // // Выполняет инициализацию и создает главное окно. // while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { if (bRet == -1) { // обрабатываем ошибку и возможно прерываем работу программы } else { if (hwndDlgModeless == (HWND) NULL || !IsDialogMessage(hwndDlgModeless, &msg) && !TranslateAccelerator(hwndMain, haccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } |