Для создания окна используется функция CreateWindow(). Во время ее выполнения окно получает несколько сообщений:
WM_GETMINMAXINFO 0 &MINMAXINFO
Информация о допустимых размерах окна; данные в структуре MINMAXINFO задаются ДО передачи сообщения, так что вы можете их не изменять, а только прочитать при необходимости. (Для получения данных Вы можете вместо обработки этого сообщения воспользоваться функцией GetWindowPlacement()).
WM_NCCREATE 0 &CREATESTRUCT
Созданиевнешней (non-client) областиокна. Обработка, предусмотренная процедурой DefWindowProc() инициализирует необходимые структуры и, в частности, выделяет пространство для хранения заголовка окна. Никакого рисования не выполняется. Возвращаемый процедурой 0 указывает на возникшую ошибку и окно не создается; не 0 указывает на успешное создание внешней области.
WM_NCCALCSIZE flag &NCCALCSIZE_PARAMS
Определение размера внутренней (client) части окна; кроме этого определяется часть окна, которая может быть скопирована без изменений при перемещении окна или изменении его размеров.
WM_CREATE 0 &CREATESTRUCT
Предусмотрено для выполнения Вами необходимых действий для создания внутренней (client) области окна. При этом Вы производите инициализацию связанных объектов, создание дочерних окон и пр. Как и WM_NCCREATE функция возвращает подтвержение о успешном выполнении нужных действий. Однако “успех” обозначается 0, а ошибка: -1 (!).
Сейчас мы рассмотрим еще несколько последовательностей сообщений, получаемых главным окном приложения. Рассматривать мы их будем на примере создания и отображения главного окна приложения. Для начала мы выделим несколько сообщений в две обычных последовательности, которые можно назвать “активацией” и “деактивацией” приложения. Эти цепочки сообщений возникают при передаче активности (фокуса ввода) от одного приложения другому. За время работы одного приложения эти цепочки могут возникать многократно. Обычно сразу за созданием главного окна приложения следует активация этого приложения.
Активация приложения:
WM_ACTIVATEAPP TRUE hTask
сообщение, информирующее об активации приложения. Если приложение имеет несколько окон “верхнего уровня” (т.е. окон стиля WS_OVERLAPPED или WS_POPUP), то все они получают эти сообщения. Младшее слово lParam содержит хендл той задачи, которая была активна до этого момента.
WM_NCACTIVATE TRUE minimized & hWnd
активация (или деактивация, смотря по параметру wParam) внешней области окна. Обработка этого сообщения по умолчанию перерисовывает внешнюю область окна для выделения цветом активного/неактивного состояний. При этом активность или неактивность окна запоминается в структуре описания окна. Вы можете сами посылать WM_NCACTIVATE для изменения состояния окна. В документации параметр ‘lParam’ не описывается, однако он может быть не 0, и содержать такие же данные, как и в сообщении WM_ACTIVATE (см. ниже). Это сообщение может быть получено не только главным окном приложения, так как информирует об активации окна, а не приложения.
Если окно активируется, то возвращаемое значение может быть любым, а если деактивируется то значение 0 запрещает его дальнейшую деактивацию. Дочерние не MDI окна (стиль WS_CHILD) часто этого сообщения не получают.
WM_GETTEXT bufsize &buffer
при обработке этого сообщения указанный буфер заполняется названием активируемого окна. В данном случае это сообщение порождается при перерисовке внешней области окна - WM_GETTEXT “вложено” в обработку WM_NCACTIVATE. Если окно не имеет заголовка (caption bar), то это сообщение не посылается.
WM_ACTIVATE 1 или 2 minimized & hWnd
активация внутренней области окна. Это сообщение может быть получено не только главным окном приложения, так как информирует об активации окна, а не приложения. Однако дочерние окна (например, управляющие элементы диалогов) могут этого сообщения не получать. Параметр wParam информирует о том, что окно активируется с помощью нажатия кнопки мыши (2) или иным путем (0). Параметр lParam содержит в старшем слове не 0, если окно минимизировано, а в младшем слове - хендл окна бывшего до этого активным.
<получение фокуса ввода>
сообщения получения/потери фокуса ввода окном см. ниже.
В этой цепочке можно выделить две фазы:
1) активация приложения (если требуется)
2) активация окна, которая тоже выполняется в несколько фаз:
· активация внешней области
· активация внутренней области
Вся цепочка часто порождается функцией SetWindowPos(...); при этом такая цепочка входит в более сложную группу, начинающуюся с WM_WINDOWPOSCHAINGING и заканчивающуюся WM_WINDOWPOSCHANGED. При активации окна “щелчком мышкой” перед этой цепочкой проходит WM_MOUSEACTIVATE и пара сообщений WM_WINDOWPOSCHAINGING, WM_WINDOWPOSCHANGED. (См. ниже)
При деактивации приложения также можно выделить две фазы - деактивацию окна и деактивацию приложения. Однако вопреки обычной практике выполнения обратных действий в обратном порядке Windows выполняет деактивацию окна в том-же порядке, как и активацию - сначала внешнюю, а затем внутреннюю области.
WM_NCACTIVATE FALSE minimized & hWnd
деактивация начинается с сообщения о деактивации внешней области окна, о чем говорит параметр wParam == FALSE. Параметр lParam содержит в младшем слове хендл окна, становящегося активным, старшее указывает на состояние Вашего окна. (Более подробно - см. выше “активация приложения”)
WM_GETTEXT bufsize &buffer
Это сообщение порождается при перерисовке внешней области окна.
WM_ACTIVATE FALSE minimized & hWnd
затем деактивируется внутренняя область окна (wParam == FALSE). Параметр lParam содержит в младшем слове хендл окна, становящегося активным, старшее указывает на состояние Вашего окна.
WM_ACTIVATEAPP FALSE hTask
и в конце деактивируется все приложение. Параметр hTask указывает на приложение, которое становится активным.
<потеря фокуса ввода окном>
сообщения получения/потери фокуса ввода окном см. ниже.
Цепочки сообщений активации и деактивации приложения сопровождаются сообщениями, передающими фокус ввода нужному окну активного приложения. Понятие фокус ввода требует некоторого пояснения. Ранее (на первой лекции) мы говорили о том, что окно, взаимодействующее с клавиатурой, является активным. Сейчас мы введем дополнительное понятие окна, имеющего фокус ввода - то есть получающего данные от клавиатуры. Различие двух понятий - активного окна и окна, имеющего фокус ввода мы рассмотрим позже. Пока что мы можем отметить, что окно имеющее фокус ввода всегда активно (но не наоборот).
Как правило последовательность собщений активации окна заканчивается сообщением о получении фокуса ввода, и сообщения о деактивации заканчиваются сообщением о потере фокуса ввода (опять-таки не в обратном порядке).
получение фокуса ввода окном:
WM_SETFOCUS hWnd losing focus 0
получаем фокус ввода, причем параметр wParam указывает хендл окна, теряющего фокус ввода (или NULL).
потеря фокуса ввода окном:
WM_KILLFOCUS hWnd received focus 0
теряем фокус ввода, причем параметр wParam указывает хендл окна, приобретающего фокус ввода (или NULL).
Обычно, после создания главного окна приложения, мы вызываем функцию ShowWindow() для отображения главного окна в нужном нам состоянии.
Обработка ShowWindow():
WM_SHOWWINDOW TRUE/FALSE 0
Параметр wParam указывает на требуемое действие - показать (TRUE) или “спрятать” (FALSE) окно. Младшее слово lParam содержит 0, если сообщение послано функцией ShowWindow().
<Сообщения активации приложения>
Если мы вызываем ShowWindow() для активации приложения, то сейчас проходит цепочка сообщений об активации приложения и передачи фокуса ввода.
WM_NCPAINT 0 0
Это сообщение, как и WM_NCACTIVATE выполняет рисование внешней области окна (кроме них этим занимаются еще и другие сообщения, например WM_NCLBUTTONDOWN и WM_SYSCOMMAND). В документации указано, что параметры wParam и lParam не используются. В Borland Help указано, что wParam является хендлом региона, определяющего область где рисование требуется, а lParam не используется. На самом деле wParam может быть 0 (при этом внешняя область не перерисовывается), может быть хендлом региона, может быть 1 (рисование внешней области требуется). Параметр lParam может быть 0, или может содержать в младшем слове хендл окна а в старшем еще какие-то данные.
WM_GETTEXT bufsize &buffer
Как и в случае WM_NCACTIVATE это сообщение “вложено” в обработку WM_NCPAINT.
WM_ERASEBKGND hDC 0
Очищается фон внутренней области окна. Для этого обычно используется кисть, определенная в структуре описания окна. Параметр wParam задает хендл контекста устройства, соответствующего внутренней области окна. Если Вы планируете сами закрашивать фон окна, то для определения размеров внутренней области окна надо использовать функцию GetClientRect(). Это связано с тем, что при создании видимого окна (имеющего стиль WS_VISIBLE) сообщение WM_ERASEBKGND встречается до первого сообщения WM_SIZE, а сообщение WM_WINDOWPOSCHANGING в этом случае хотя и обрабатывается до WM_ERASEBKGND, но содержит нулевые размеры внутренней области окна.
WM_SIZE type height & width
Задается размер окна, причем параметр wParam информирует о “типе” размера - окно может быть максимизировано, может быть минимизировано или отображено в нормальном состоянии. Это сообщение, кроме того, посылается окну если оно закрывается каким-либо максимизированным окном, или становится видимым, когда закрывавшее его максимизированное окно стало нормальным или превратилось в иконку.
WM_MOVE 0 y & x
Задается положение окна на экране (или во внутренней области окна-родителя).
Обычно при перемещении (в X, Y или Z направлении), изменении размеров окна или при изменении его состояния, помимо WM_SIZE и WM_MOVE Вы будете получать сообщения WM_WINDOWPOSCHANGING и WM_WINDOWPOSCHANGED. При этом все сообщения посылются функцией SetWindowPos(...) (или эквивалентной) в следующем порядке: