Вызов СreateWindowEx возвращает дескриптор созданного окна. Этот дескриптор хранится в переменной hWnd. Для многих функций Windows в качестве параметра требуется hWnd, указывающий Windows, к какому окну применить функцию. Если функция СreateWindowEx не может создать окно, она возвращает NULL.
Отображение и корректировка окна.
Хотя функция СreateWindowEx и создает окно, она автоматически не индицирует его. Программа должна предусмотреть индикацию окна с помощью функции ShowWindow и корректировку области пользователя окна с помощью функции UpdateWindow.
Функция ShowWindow побуждает Windows индицировать новое окно:
bret = ShowWindow (hWnd, nCmdShow)
hWnd – дескриптор созданного функцией CreateWindowEx окна;
nCmdShow – величина, передаваемая в качестве параметра функции WinMain и задающая начальный вид окна на экране;
bret – логическая переменная, содержащая возвращаемое функцией значение.
Функция ShowWindow выводит окно на экран. Вызов функции UpdateWindow вызывает затем перерисовку рабочей области:
bret = UpdateWindow (hWnd).
При обработке этого вызова в оконную процедуру посылается сообщение WМ_РАINТ.
Обе функции при успешном завершении возвращают TRUE, в противном случае – FALSE.
Вид главного окна Компоновщика расчетных схем представлен на рисунке 3.1.
Как видно из рис. 3.1, главное окно Компоновщика содержит заголовок, строчку меню (структура которого была рассмотрена во 2‑ой главе), рабочую область, а также панель инструментов и панель состояния, которые более подробно будут рассмотрены ниже.
Цикл обработки сообщений
Итак, окно окончательно выведено на экран. Теперь программа должна подготовить себя для получения информации от пользователя через клавиатуру и мышь. Windows поддерживает «очередь сообщений» для каждой программы, работающей в данный момент в системе Windows. При вводе информации Windows преобразует ее в «сообщение», которое помещается в очередь сообщений программы.
Цикл обработки сообщений – это программный цикл, при работе в котором функция WinMain извлекает сообщения из очереди сообщений и направляет их соответствующим окнам. Для рассматриваемой программы цикл обработки сообщений выглядит следующим образом:
do while (GetMessage (mesgt, NULL, 0, 0))! Получить сообщение
i = 0
if (hDlgModeLess. NE. NULL) then ! Диалоговое окно активно?
if (IsDialogMessage (hDlgModeLess, mesgt)) i =1! Есть сообщение
! для немодального диалогового окна
end if
………! Аналогичным образом распределяются
………! сообщения для других немодальных
………! диалоговых окон, создаваемых программой
if (i.ne.0) cycle
i = TranslateMessage (mesgt) ! Транслировать сообщение
i = DispatchMessage (mesgt) ! Отправить сообщение
end do
Вызов функции GetMessage, с которого начинается цикл обработки сообщений, извлекает сообщение из очереди сообщений. Этот вызов передает Windows указатель на структуру mesgt типа T_МSG. Второй, третий и четвертый параметры, установленные в NULL или 0, показывают, что программа получает все сообщения от всех окон, созданных этой программой. Windows заполняет поля структуры сообщений информацией об очередном сообщении из очереди сообщений. Наиболее важными полями этой структуры являются:
à hWnd – дескриптор окна, для которого предназначено сообщение;
à message – тип сообщения;
à wParam, lParam – два 32‑разрядных параметра сообщения, смысл и значение которых зависят от особенностей сообщения.
Если поле message сообщения, извлеченного из очереди сообщений, равно любому значению, кроме WМ_QUIТ, то функция GetMessage возвращает TRUE. Сообщение WМ_QUIТ заставляет программу прервать цикл обработки сообщений.
При организации цикла обработки сообщений программы, создающей в ходе работы немодальные окна диалога[1], необходимо учитывать, что сообщения для немодальных окон диалога проходят через очередь сообщений программы. Цикл обработки сообщений должен передавать такие сообщения соответствующим оконным процедурам окон диалога. Это реализуется следующим образом. Функция создания немодального диалога CreateDialog возвращает дескриптор окна (не равный 0), который запоминается в глобальной переменной (например, hDlgModeLess). Если диалог создан и сообщение предназначено для него, то функция IsDialogMessage отправляет сообщение оконной процедуре окна диалога, возвращая TRUE, тогда вспомогательная переменная i принимает значение 1, сигнализируя тем самым о перехвате сообщения диалоговым окном. В противном случае функция возвращает FALSE и переменная i не меняется. Если созданы и другие активные немодальные диалоги, то для них реализуются аналогичные операции. Таким образом гарантируется, что функции TranslateMessage и DispatchMessage будут вызываться только тогда, когда немодальные окна диалога не созданы или нет сообщений для них.
Т.к. программе необходимо обрабатывать вводимые с клавиатуры символы, нужно преобразовывать каждое полученное сообщение с помощью функции TranslateMessage. Эта функция отыскивает пары сообщений WM_KEYDOWN и WM_KEYUP и генерирует соответствующее сообщение WM_CHAR.
Функция DispatchMessage отправляет сообщение для его обработки соответствующей оконной процедуре. В рассматриваемой программе такой оконной процедурой является функция MainWndProc. После того, как MainWndProc обработает сообщение, оно возвращается в Windows, которая все еще обслуживает вызов функции DispatchMessage. Windows возвращает управление в программу к следующему за вызовом DispatchMessage оператору и цикл обработки сообщений в очередной раз возобновляет работу, вызывая GetMessage.
Реальная работа начинается в оконной процедуре, которая обеспечивает реакцию на вводимую информацию и сообщения системы управления окнами, получаемые от Windows.
3.2 Процедура обработки сообщений
Оконная процедура определяется следующим образом:
integer function MainWndProc (hWnd, mesg, wParam, lParam).
Первым параметром является hWnd, дескриптор получающего сообщение окна. Второй параметр – число, которое идентифицирует сообщение. Параметры wParam и lParam содержат дополнительную информацию о сообщении и называются «параметрами сообщения». Конкретное значение этих параметров определяется типом сообщения.
Обработка сообщений
Оконная процедура получает сообщения от Windows. Это могут быть сообщения о вводе, переданные функцией WinMain (например, WM_KEYDOWN, WM_KEYUP, WM_MOUSEMOVE, WM_TIMER), или сообщения системы управления окнами, поступающие непосредственно от Windows в обход очереди прикладной программы или цикла обработки сообщений (например, WM_CREATE, WM_DESTROY, WM_PAINT). Каждое получаемое окном сообщение идентифицируется номером, который содержится в параметре mesg оконной процедуры. В модуле MSFWINTY.F90 Fortran PowerStation 4.0 определены именованные константы, начинающиеся с префикса WМ для каждого типа сообщений.
Обычно используется конструкция select case для определения того, какое сообщение получила оконная процедура и как его обрабатывать. Если оконная процедура обрабатывает сообщение, то ее возвращаемым значением должен быть 0. Все сообщения, не обрабатываемые оконной процедурой, должны передаваться функции Windows, которая называется DefWindowProc. Значение, возвращаемое этой функцией, должно быть возвращаемым значением оконной процедуры.
Первое сообщение, которое получает оконная процедура – это WМ_СRЕАТЕ. Когда Windows обрабатывает функцию СreateWindowEx в WinMain, она вызывает MainWndProc с дескриптором окна в качестве первого параметра и с WМ_СRЕАТЕ в качестве второго. MainWndProc обрабатывает сообщение WМ_СRЕАТЕ и передает управление обратно в Windows, которая, в свою очередь, возвращается обратно в WinMain.
Следующим обрабатывается сообщение WM_SIZE. Определяются размеры рабочей области, панели инструментов и панели состояния. Windows посылает в оконную процедуру сообщение WM_SIZE при любом изменении размеров окна. Переменная lParam, переданная в оконную процедуру, содержит ширину рабочей области в младшем слове и высоту в старшем слове.
Сообщения WM_PARENTNOTIFY и WM_RBUTTONDOWN обрабатывают сообщения, поступающие соответственно от панели инструментов и всплывающего меню.
В программе необходимо обрабатывать символы клавиатуры, поэтому она должна обрабатывать сообщения WM_CHAR. Параметр lParam, передаваемый в оконную процедуру как часть символьного сообщения, является таким же, как параметр lParam аппаратного сообщения клавиатуры, из которого сгенерировано символьное сообщение. Параметр wParam – это код символа ASCII. Особым образом обрабатываются клавиши <Backspace>, <Tab> и <Enter>. Все остальные символы обрабатываются похожим образом.
Сообщение WM_KEYDOWN используется для определения нажатой клавиши или комбинации клавиш.
При щелчке мыши на разрешенном пункте меню генерируется сообщение WM_COMMAND (при выборе недоступного или запрещенного пункта меню данное сообщение не генерируется).
Сообщение WМ_РАINТ сообщает программе, что часть или вся рабочая область окна недействительна, и ее следует перерисовать.
При создании окна недействительна вся рабочая зона, поскольку программа еще ничего в окне не нарисовала. При изменении размера окна рабочая область также становится недействительной и содержимое рабочей области не сохраняется. В графической среде это привело бы к тому, что пришлось бы хранить слишком много данных. Вместо этого Windows делает недействительным все окно. Оконная процедура получает сообщение WМ_РАINТ и восстанавливает содержимое окна.