Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
50
Добавлен:
08.05.2015
Размер:
124.42 Кб
Скачать

Дополнительная информация об обработке сообщений в главном окне

Перед тем, как перейти к рассмотрению дочерних окон документов, разберемся с обработкой сообщений в FrameWndProc. При выборе в меню File опции Close программа MDIDEMO закрывает активное дочернее окно. Описатель активного дочернего окна она получает, посылая окну - сообщение WM_MDIGETACTIVE. Если дочернее окно отвечает утвердительно на сообщение WM_QUERYENDSESSION, то программа MDIDEMO для закрытия дочернего окна посылает окну - сообщение WM_MDIDESTROY.

Для обработки опции Exit меню File необходимо только, чтобы оконная процедура главного окна послала себе сообщение WM_CLOSE.

Обработать опции Tile, Cascade и Arrange Icons из подменю Window проще простого, нужно только послать окну - сообщения WM_MDITILE, WM_MDICASCADE и WM_MDIICONARRANGE.

Обработка опции Close All несколько сложнее. FrameWndProc вызывает функцию EnumChildWindows, передавая указатель на функцию CloseEnumProc. Эта функция посылает сообщение WM_MDIRESTORE каждому дочернему окну, затем сообщение WM_QUERYENDSESSION и сообщение WM_MDIDESTROY. Этого не делается для окна заголовка значка, определяемого, если возвращаемое значение функции GetWindow c параметром GW_OWNER не равно NULL.

Все сообщения , которые оконная процедура главного окна не обрабатывает , должны передаваться в DefFrameProc. Эта функция заменяет в оконной процедуре главного окна функцию DefWindowProc. Даже если оконная процедура главного окна и перехватывает сообщения WM_MENUCHAR, WM_SETFOCUS или WM_SIZE, все равно они должны передаваться в DefFrameProc.

Необрабатываемые сообщения WM_COMMAND также должны передаваться в DefFrameProc. В частности, FrameWndProc не обрабатывает сообщений WM_COMMAND, появившихся в результате того, что пользователь выбирает один из документов из списка в подменю Window. ( параметра wParam для этих опций начинается с IDM_FIRSTCHILD.) Эти сообщения передаются в DefFrameProc и обрабатываются там. Обратите внимание , что главному окну не нужно поддерживать список описателей окон всех созданных документов . При необходимости (, при обработке опции Close All из меню ), эти описатели можно получить , вызывая функцию EnumChildWindows.

Дочерние окна документов

Теперь рассмотрим HelloWndProc — оконную процедуру тех дочерних окон документов , которые выводят на экран фразу "Привет, мир!".

Как и для любого класса окна, который используется более , чем для одного окна , статические переменные, определенные в оконной процедуре (и в любой функции , вызываемой из оконной процедуры ), совместно используются всеми окнами , созданными на основе этого класса окна. Данные, уникальные для каждого окна , должны храниться в форме , отличной от статических переменных. Один из таких приемов подразумевает применение свойств окна. При другом подходе используется область памяти , зарезервированная путем определения отличного от нуля значения в поле cbWndExtra структуры WNDCLASSEX, используемой при регистрации класса окна.

Оконная процедура окна документа получает сообщение WM_MDIACTIVATE всегда, когда окно становится активным или перестает быть активным ( зависимости от того , содержится ли описатель окна в параметре lParam этого сообщения ). Вспомните, что в программе MDIDEMO имеется три различных меню: MdiMenuInit выводится, если нет ни одного окна документа, MdiMenuHello выводится, если активно окно документа Hello, и MdiMenuRect выводится , если активно окно документа с прямоугольниками .

Сообщение WM_MDIACTIVATE дает возможность окну документа изменить меню. Если в параметре lParam этого сообщения содержится описатель окна (окно становится активным), HelloWndProc изменяет меню на MdiMenuHello. Если в параметре lParam этого сообщения содержится описатель другого окна, HelloWndProc преобразует меню в MdiMenuInit.

HelloWndProc изменяет меню путем отправки сообщения WM_MDISETMENU окну - администратору. Окно - администратору обрабатывает это сообщение, удаляя список документов из текущего меню и присоединяя его к новому меню. Таким образом список документов попадает из меню MdiMenuInit (является результатом создания первого документа) в меню MdiMenuHello. Не используйте для изменения меню в приложении MDI функцию SetMenu.

Значения параметров wParam и lParam сообщения WM_MDIACTIVATE являются, соответственно, описателями окна , которое перестает быть активным, и окна, становящегося активным. Оконная процедура получает первое сообщение WM_MDIACTIVATE с параметром lParam равным описателю текущего окна , когда это окно впервые создается , а когда окно закрывается , она получает последнее сообщение WM_MDIACTIVATE с параметром lParam равным другому значению . Когда пользователь переключается с одного документа на другой, первое окно документа получает сообщение WM_MDIACTIVATE с параметром lParam равным описателю первого окна ( это время оконная процедура устанавливает меню в MdiMenuInit). Второе окно документа получает сообщение WM_MDIACTIVATE с параметром wParam равным описателю второго окна (это время оконная процедура устанавливает меню либо в MdiMenuHello, либо в MdiMenuRect, в зависимости от описателя). При закрытии всех окон документов остается только меню MdiMenuInit. Вспомните, что FrameWndProc посылает дочернему окну асинхронное сообщение WM_QUERYENDSESSION, когда пользователь выбирает в меню опцию Close или Close All. HelloWndProc обрабатывает сообщения WM_QUERYENDSESSION и WM_CLOSE, выводя на экран окно сообщений с запросом пользователю о том, можно ли закрывать окно . ( реальной программе в этом окне сообщений может появляться запрос о том , нужно ли сохранять файл .) Если пользователь выбирает опцию , соответствующую тому , что окно закрывать не следует , оконная процедура возвращает 0.

Все необрабатываемые сообщения должны передаваться в DefMDIChildProc (не в DefWindowProc) для их обработки по умолчанию. Некоторые сообщения должны быть переданы в DefMDIChildProc независимо от того, обрабатываются ли они как - в оконной процедуре или нет . Такими сообщениями являются:

WM_CHILDACTIVATE, WM_GETMINMAXINFO, WM_MOVE, WM_SETFOCUS, WM_SIZE, WM_MENUCHAR и WM_SYSCOMMAND.

RectWndProc почти полностью аналогична HelloWndProc, поэтому нет смысла ее специально рассматривать.

Освобождение захваченных ресурсов

Программа MDIDEMO в функции WinMain использует функцию LoadMenu для загрузки трех меню, определенных в файле описания ресурсов. Обычно Windows удаляет меню, когда закрывается окно, к которому меню относится. Это касается и меню MdiMenuInit. Однако, меню, не относящиеся к какому бы то ни было окну (программе MDIDEMO это меню Hello и Rect), будут продолжать занимать некоторую область памяти, даже после завершения программы . Поэтому , для освобождения памяти, занимаемой меню Hello и Rect, в программе MDIDEMO функция DestroyMenu в WinMain вызывается дважды .

Сила оконной процедуры

Большая часть того, что в Windows создано для поддержки многооконного интерфейса, заключено в классе окна MDICLIENT. В этом совершенно отчетливо проявляется сила объектной архитектуры Windows. Оконная процедура окна - служит, как бы, связующим звеном между главным окном и различными окнами документов.