<Подготовка структур WNDCLASS и их регистрация с помощью RegisterClass>
<Создание окон с помощью CreateWindowEx>
<Цикл GetMessage, TranslateMessage, DispatchMessage>
<Завершение приложния>
WM_CREATE и 2 WINDOW в одной нити
Как я уже написал, опыта/знаний в этом деле с гулькин нос, а вот Рихтер (в книге) советует UI обрабатывать в одной нити. Как быть? Создавать все таки еще одну нить, или же просто я что-то не так делаю. Может, кто-нибудь каркас кода для правильной работы в такой ситуации даст? Спасибо.
Код:
Код:
#include "smm.h"
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE, //legacy parameter
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
if (0 == MyRegisterClass(
CS_HREDRAW | CS_VREDRAW,
WndProc,
0,
0,
hInstance,
NULL,
NULL,
(HBRUSH)(COLOR_WINDOW + 1),
NULL,
"APP1_MAIN",
NULL))
{
return 1;
}
if (0 == MyRegisterClass(
CS_HREDRAW | CS_VREDRAW,
WndProc2,
0,
0,
hInstance,
NULL,
NULL,
(HBRUSH)(COLOR_WINDOW + 1),
NULL,
"APP1_CHILD",
NULL))
{
return 1;
}
hInst = hInstance;
hwndMain = CreateWindowEx(0, "APP1_MAIN", "APP1_MAIN", WS_OVERLAPPEDWINDOW,
15, 15, 200, 200, NULL, NULL, hInst, NULL);
if (!hwndMain)
{
return 1;
}
ShowWindow(hwndMain, nCmdShow);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(UINT style, WNDPROC lpfnWndProc,
int cbClsExtra, int cbWndExtra,
HINSTANCE hInstance, HICON hIcon,
HCURSOR hCursor, HBRUSH hbrBackground,
LPCSTR lpszMenuName,
LPCSTR lpszClassName, HICON hIconSm)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = style;
wcex.lpfnWndProc = lpfnWndProc;
wcex.cbClsExtra = cbClsExtra;
wcex.cbWndExtra = cbWndExtra;
wcex.hInstance = hInstance;
wcex.hIcon = hIcon;
wcex.hCursor = hCursor;
wcex.hbrBackground = hbrBackground;
wcex.lpszMenuName = lpszMenuName;
wcex.lpszClassName = lpszClassName;
wcex.hIconSm = hIconSm;
return RegisterClassEx(&wcex);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static bool click = false;
switch (message)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_LBUTTONUP:
if (!click)
{
hwndChild = CreateWindowEx(0, "APP1_CHILD", "APP1_CHILD", WS_OVERLAPPEDWINDOW,
40, 40, 200, 200, hwndMain, NULL, hInst, NULL);
while(true);
if (!hwndChild)
{
PostQuitMessage(0);
}
UpdateWindow(hwndChild);
ShowWindow(hwndChild, SW_SHOW);
click = true;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (WM_CREATE == message)
{
MessageBox(hwndMain, "WM_CREATE received", "NOTICE", MB_OK | MB_TOPMOST);
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE, //legacy parameter
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
if (0 == MyRegisterClass(
CS_HREDRAW | CS_VREDRAW,
WndProc,
0,
0,
hInstance,
NULL,
NULL,
(HBRUSH)(COLOR_WINDOW + 1),
NULL,
"APP1_MAIN",
NULL))
{
return 1;
}
if (0 == MyRegisterClass(
CS_HREDRAW | CS_VREDRAW,
WndProc2,
0,
0,
hInstance,
NULL,
NULL,
(HBRUSH)(COLOR_WINDOW + 1),
NULL,
"APP1_CHILD",
NULL))
{
return 1;
}
hInst = hInstance;
hwndMain = CreateWindowEx(0, "APP1_MAIN", "APP1_MAIN", WS_OVERLAPPEDWINDOW,
15, 15, 200, 200, NULL, NULL, hInst, NULL);
if (!hwndMain)
{
return 1;
}
ShowWindow(hwndMain, nCmdShow);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(UINT style, WNDPROC lpfnWndProc,
int cbClsExtra, int cbWndExtra,
HINSTANCE hInstance, HICON hIcon,
HCURSOR hCursor, HBRUSH hbrBackground,
LPCSTR lpszMenuName,
LPCSTR lpszClassName, HICON hIconSm)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = style;
wcex.lpfnWndProc = lpfnWndProc;
wcex.cbClsExtra = cbClsExtra;
wcex.cbWndExtra = cbWndExtra;
wcex.hInstance = hInstance;
wcex.hIcon = hIcon;
wcex.hCursor = hCursor;
wcex.hbrBackground = hbrBackground;
wcex.lpszMenuName = lpszMenuName;
wcex.lpszClassName = lpszClassName;
wcex.hIconSm = hIconSm;
return RegisterClassEx(&wcex);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static bool click = false;
switch (message)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_LBUTTONUP:
if (!click)
{
hwndChild = CreateWindowEx(0, "APP1_CHILD", "APP1_CHILD", WS_OVERLAPPEDWINDOW,
40, 40, 200, 200, hwndMain, NULL, hInst, NULL);
while(true);
if (!hwndChild)
{
PostQuitMessage(0);
}
UpdateWindow(hwndChild);
ShowWindow(hwndChild, SW_SHOW);
click = true;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (WM_CREATE == message)
{
MessageBox(hwndMain, "WM_CREATE received", "NOTICE", MB_OK | MB_TOPMOST);
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
Прога регистрирует два класса для окон, создает окно для первого класса и по клику в этом окне создает второе окно. Причем сразу после создания второго окна отправляется в бесконечный цикл. Только перед этим циклом успевает выдать месджбокс, а ведь он вызывается по событию WM_CREATE для второго окна. Каким образом нить умудряется перескочить из бесконечного цикла в WndProc2, а затем обратно? Далее оба окна намертво висят, т. е. больше таких скачков из wndProc в WndProc2 не случается. Я полагал, что пока WndProc (любая) не вернет значение, никакие другие сообщения обработаны не будут. Однако получается что нет. Поделитесь мыслями, знаниями, ссылками на источники, где этот вопрос разъясняется. У меня только догадки.
---
Нашел ответ дебаггером. CreateWindow перед возвратом вызывает _InternalCallWinProc@20, которая передает управление WndProc создаваемого окна. Теперь стало яснее. =)
Конечно же. При создании окна ему сразу же посылается WM_CREATE, WM_SIZE, WM_PAINT и многое другое. А зачем бесконечный цикл? Ты его для проверки вставил? Модальные окна иначе создаются.