Реферат по предмету "Информатика, программирование"


Окна приложений в среде Windows

Основы организации приложения всреде Windows
Итак, мы рассмотрим основы оранизации приложения в средеWindows и отметим несколько нюансов:
Приложение в среде Windows, как и в среде DOS, содержит такназываемую “главную функцию” (WinMain), вызываемую при запуске приложения. Приложениезавершается практически при окончании работы функции WinMain.
Обычно, хотя это и не обязятельно, функция WinMain реализуетследующую схему:
1)    выполняются требуемыеинициализационные действия
2)    создается главное окноприложения, для чего часто регистрируется новый класс окон (оконная функция);
3)    организуется цикл обработкисообщений приложения. Обычно цикл завершается при закрытии главного окнаприложения (не всегда)
4)    после завершения циклаобработки сообщений выполняется “деинициализация” данных и освобождение занятыхресурсов, после чего функция WinMain() закнчивается.
Несколько замечаний:
Замечание 1. Если приложение содержит непродолжительные (порядка 1 сек.)операции, не требующие взаимодействия с пользователем (например, только файл-ориентированныйввод-вывод или настройка другого приложения), то эти действия могут бытьвыполнены непосредственно функцией WinMain() без создания окон и безорганизации цикла обработки сообщений.
Замечание 2. В некоторых случаях приложение может обойтись безрегистрации класса окон и организации цикла обработки сообщений, применяя вкачестве главного окна модальный диалог.
Замечание 3. В момент вызова функции WinMain() ей, через аргументы,передается несколько параметров, например хендл копии приложения (hInstance).До вызова WinMain() приложение “не знает” этих данных. Поэтому могут возникатьсложности с использованием статических конструкторов объектно-ориентрованныхязыков (C++).
Эта особенность, вообще говоря совершенно неестественна. Делов том, что функция WinMain() вызывается не непосредственно средой Windows, апромежуточным startup-кодом, являющимся частью run-time библиотеки (как и вDOS-приложениях). Этот код инициализирует стандартные переменные, кучу, стек,обнуляет неинициаизированные статические данные и вызывает конструкторыстатических объектов до вызова функции WinMain().
Windows вызывает непосредственно этот startup-код, передаваяему нужные данные через регистры. То есть, в тот момент, когда вызываютсяконструкторы статических объектов, параметры функции WinMain() уже известны, и,более того, они даже сохранены в статических переменных. Однако по непонятнымсоображениям эти переменные не декларированы как публичные и являютсялокальными для startup-кода.
Замечание 4. Цикл обработки сообщений, в том виде, который рекомендованруководствами, не проверяет наличие окон у приложения. Для егозавершения используется сообщение WM_QUIT, извлечение которого из очередиприводит к завершению цикла.
При этом требуется, что бы сообщение WM_QUIT посылалось спомощью функций PostMessage(), PostAppMessage() или PostQuitMessage() (толькотогда оно попадает в очередь приложения). Обычно это сообщение посылается приуничтожении главного окна приложения (при обработке сообщения WM_DESTROYнаправленного этому окну). В более общем случае подразумевается последнее окноприложения.
Вы обязаны сами предусмотреть средства для посылки сообщенияWM_QUIT, так как ни один стандартный обработчик не посылет его. Конечно, Выможете предусмотреть собственные, альтернативные методы для прерывания циклаобработки сообщений. Так, например, Вы можете в цикле обработки сообщенийпроверять корректность хендла главного окна:
while (IsWindow( hMainWnd ) ) {
if ( !GetMessage( &msg, NULL,NULL, NULL ) ) break;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
Если цикл обработки сообщений не будет прерван приуничтожении последнего окна приложения, то приложение останется активным, а уВас уже не будет средств для его завершения, кроме выхода из Windows. При этомВаше приложение исчезнет из списка приложений Task Manager (этот список, вообщеговоря, содержит не задачи, а главные окна приложений).
Замечание 5. Windows не является объектно-ориентированной средой. Хотяокно и может быть названо объектом ООП, но лишь с достаточной натяжкой. Самоесущественное отличие окна в Windows от объекта ООП заключается в том, чтосообщение, обрабатываемое оконной функцией, во многих случаях не выполняетдействий, а является “информативным”, указывая на то, что над окном выполняетсята или иная операция какиой-либо внешней функцией.
Поясним это на примере создания окна. В случае “чистого” ООПдля создания объекта он должен получить сообщение “create”, обработка которогоприведет к его инициализации. В Windows сообщение WM_CREATE не выполняетникаких функций по созданию окна. Оно только информирует окно о том, что в этовремя окно создается средствами обычной функциональной библиотеки, напримерпосредством функции CreateWindowEx(). Вы можете вообще игнорировать этосообщение, возвращать любой результат, вызывать или не вызывать функциюобработки по умолчанию — окно все равно будет создано.
Если бы все сообщения, получаемые окном были толькоинформационными, то к этому легко можно было бы приспособиться. Однако длянекоторых сообщений должна выполняться обработка по умолчанию, если Вы ее невыполнили сами, а для других такая обработка должна выполняться обязательно,даже если Вы уже обработали это сообщение. Все это заметно усложняет написаниеприложений в среде Windows.
Ситуация дополнительно усугубляется тем, что в документациикак правило ничего не сообщается о том, какая обработка сообщения выполняетсяпо умолчанию и, кроме того, по некоторым сообщениям приводятся некорректные(или неполные) сведения об их параметрах, выполняемым функциям, условиям возникновенияи возвращаемом результате. Help, сопровождающий компиляторы Borland наиболееполный из всех (но не исчерпывающий).
Для окон, использующих в качестве процедуры обработкисообщений по умолчанию не DefWindowProc(), а иную функцию (например, DefMDIChildProc()),можно уточнить список сообщений обязательно подлежащих обработке по умолчанию.Однако это уточнение касается только тех сообщений, обработку которых дляDefWindowProc() можно игнорировать, а для иных функций нельзя, список же того,что можно игнорировать для DefWindowProc(), а что нельзя остается неизвестным.
Замечание 6. В Windows существует определенная путаница терминов.Попробуем разобраться с некоторыми из них. Как известно, окно может находитьсяв нескольких состояниях:
·   максимизированом, то есть быть “распахнутым” на весьэкран — при этом внутренняя область окна занимает весь экран, кроме небольшихполос сверху — где размещается заголовок и меню, снизу — горизонтальная полосапрокрутки и справа — вертикальная полоса прокрутки; рамка окна находится запределами экрана, мы ее не видим, перемещение окна невозможно.
Для максимизации окна мы можемвоспользоваться функцией ShowWindow со следущими возможными параметрами:
ShowWindow(hWnd, SHOW_FULLSCREEN );
ShowWindow( hWnd, SW_SHOWMAXIMIZED);
ShowWindow( hWnd, SW_MAXIMIZE );
максимизированое окно всегда активнои имеет фокус ввода. Когда какое-либо окно максимизируется, все остальныеверхние окна получают сообщение WM_SIZE, информирующее о том, что они “закрыты”максимизированным окном.
Мы можем узнать, является ли нашеокно максимизированным с помощью функции
BOOL IsZoomed( hWnd );
При использовании системного менюоперации максимизации окна соответствует пункт Maximize, выбор которогопорождает системную команду SC_MAXIMIZE (или синоним SC_ZOOM).(см. сообщение WM_SYSCOMMAND)
Здесь вместо термина maximizeможет использоваться zoom.
·   минимизированным, то есть представленным в видеиконки. Для того, что превратить окно в иконку мы должны воспользоваться однимиз способов:
ShowWindow(hWnd, SHOW_ICONWINDOW );
ShowWindow( hWnd, SW_SHOWMINIMIZED);
ShowWindow( hWnd,SW_SHOWMINNOACTIVE );
ShowWindow( hWnd, SW_MINIMIZE );
CloseWindow( hWnd );
Разные способы, использующиеShowWindow, отличаются только правилами активации окна. SW_SHOWMINIMIZEDи SHOW_ICONWINDOW отображает окно в виде иконки, делая его активным; SW_SHOWMINNOACTIVEне изменяет текущего активного окна; SW_MINIMIZE (как и функцияCloseWindow()) делает активным следующее окно в списке Windows. Последнийспособ эффективен при минимизации главного окна приложения — так какминимизированное главное окно обычно обозначает передачу активности другомуприложению.
Проверить состояние окна можно спомощью функции
BOOL IsIconic( hWnd );
При использовании системного менюпревращению окна в иконку соответствует пункт ‘Minimize’, порождающийсистемную команду SC_MINIMIZE (или синоним SC_ICON). (см.сообщение WM_SYSCOMMAND)
В этом случае используется сразу триразных термина для обозначения одного и того-же: minimize, closeи iconic. При этом функция CloseWindow() является единственной,интерпретирующей термин close таким способом; в остальных случаях closeозначает действительно закрытие (иногда уничтожение) окна. Здесь же надо, чттотермин open, применяемый к минимизированному окну обозначает егомаксимизацию или восстановление нормальных размеров.
·   нормальным, то есть мы видим (или можемувидеть) его рамку, мы можем перемещать окно по экрану. Когда окно находится внормальном состоянии, то для него определены максимально и минимальнодопустимый размеры. Эти размеры нельзя путать с максимизированным иминимизированным состояниями. Максимальный размер нормального окна может дажепревышать размер окна в максимизированном состоянии, минимальный размер этообычно такой размер, при котором окно еще может быть корректно представлено ввиде окна.
Для перехода из минимизированогосостояния к нормальному можно воспользоваться функцией OpenIcon( hWnd ); или,как из минимизированого, так и из максимизированого состояния можнопользоваться функцией ShowWindow() с параметрами:
ShowWindow(hWnd, SHOW_OPENWINDOW );
ShowWindow( hWnd, SW_SHOWNORMAL );
ShowWindow( hWnd, SW_RESTORE );
ShowWindow( hWnd, SW_SHOWNOACTIVATE);
В документации (SDK Help) указано,что SW_RESTORE и SW_SHOWNORMAL эквивалентны, но это далеко не так — SW_RESTOREвосстанавливает предыдущее состояние, а не нормальное. То есть, если Выминимизировали окно из максимизированного, то SW_RESTORE вернет Вас кмаксимизированному окну, а SW_SHOWNORMAL — к нормальному. SW_SHOWNORMAL имеет синонимSHOW_OPENWINDOW.
Если окно восстанавливается илимаксимизируется из минимизированного состояния, то Ваше окно получит сообщениеWM_QUERYOPEN — обрабатывая которое Вы можете разрешить или запретить дальнейшиедействия. Если Вы возвращаете TRUE, то окно будет раскрыто, а если Вы вернетеFALSE, то окно останется минимизированным.
Замечание 7. Дополнительно надо разобраться с несколькими терминамиWindows, которые постоянно применяются, но никак в документации не описаны.Речь идет о хендлах копии приложения (HINSTANCE), модуля (HMODULE) и задачи(HTASK). Все эти хендлы используются разными функциями, причем разница междуними никак не поясняется. Поэтому нам надо рассмотреть эти хендлы болееподробно:
·   HTASK описывает задачу.
В Windows 3.x под задачей подразумевается конкретныйзапущеный процесс, для которого определены командная строка, текущаявыполняемая инструкция, указатель на стек, переменные окружения, PDB(эквивалент префикса задачи (PSP) в среде DOS) и пр. Хендл задачи можнополучить с помощью функции
HTASK     GetCurrentTask(void );
В Win32 хендл задачи не применяется, а вместо негонадо пользоваться хендлами и идентификаторами процесса и потока. Их можно получить с помощью функций:
HANDLE  GetCurrentProcess(void );
HANDLE  OpenProcess( fdwAccess,fInherit, dwIDProccess );
DWORD   GetCurrentProcessId( void);
HANDLE  GetCurrentThread( void );
DWORD   GetCurrentThreadId( void );
Функции GetCurrentProcess и GetCurrentThread возвращают так называемый псевдодескриптор процесса(потока). Псевдодескриптор – это некотораявеличина, рассматриваемая в качестве дескритора текущего процесса(потока). То есть эта величина, применяемая в контексте другого процесса(потока), будет описывать его, а не данный поток. Для получения “настоящего”хендла надо воспользоваться функцией:
BOOL  DuplicateHandle(
hSourceProcess, hSourceHandle,hTargetProcess, lphTargetHandle,
fdwAccess, fInherit, fdwOptions
);
·   HINSTANCE описывает копию приложения.
в Windows 3.x этот хендл указывает на сегмент данныхприложения, который содержит стек и локальную кучу. Для каждого запущенногоприложения создается свой собственный сегмент данных, что позволяет однозначноопределить конкретную копию приложения по его сегменту данных или организоватьобмен данными между двумя копиями одного приложения. Так функцияGetInstanceData позволяет скопировать данные, принадлежащие сегменту данныхдругой копии, в то-же самое место текущей копии.
int         GetInstanceData(hInstance, pByte, cbData );
В функцию WinMain передается какхендл текущей копии приложения, так и хендл предыдущей копии, что позволяеторганизовать взаимодействие двух копий между собой, предотвратить запуск другихкопий, если это может привести к ошибке, или для выполнения действий,необходимых только в первой копии приложения.
В Win32 для каждогозапущенного приложения (т.е. процесса) выделяется виртуальное адресноепространство в 4G в едином сегменте. Поэтому данный хендл описывает не сегментданных (который описывает весь 4G сегмент), а адрес в виртуальном пространстве,с которого был загружен данный модуль. В адресном пространстве одного процессаникаких других приложений не существует, поэтому этот хендл не можетприменяться для обнаружения других копий приложения и тем более для обменаданными между разными копиями приложений. В приложениях Win32 hPrevInstanceвсегда равен NULL, а хендл текущей копии приложения в большинстве случаевсовпадает. При необходимости обнаружения других копий приложения надоиспользовать какие–либо иные методы, например функцию:
HWND FindWindow(lpszClassName, lpszWindowTitle );
Хендл окна в Win32 являетсяуникальным и может идентифицировать конкретное окно в любом приложении.
Для обмена данными между приложениями(процессами) приходится передавать данные из адресного пространства одногопроцесса в адресное пространство другого. Для выполнения этих операцийпредусмотрено сообщение WM_COPYDATA. Когда Вы посылаете это сообщениеокну, созданному другим процессом, указанные Вами данные копируются в адресноепространство другого процесса и могут быть прочитаны оконной процедуройокна–получателя. Этот механизм может применяться и для обмена данными между16-ти и 32-х битовыми приложениями, однако для этого необходимо определитьномер сообщения WM_COPYDATA и специальную структуру COPYDATASTRUCT для16-ти битовой платформы – так как файл windows.h не содержит этих определений:
#defineWM_COPYDATA             0x004A
typedef structtagCOPYDATASTRUCT {
DWORD dwData;
DWORD cbData;
LPVOID lpData;
} COPYDATASTRUCT, FAR* PCOPYDATASTRUCT;
·   HMODULE описывает отдельный модуль.
В Windows 3.x под модулем понимается отдельныйвыполняемый файл или библотека динамической компоновки. Для описания модулясоздается специальный сегмент описания модуля, содержащий информацию о всехсегментах данного модуля и их атрибутах. Хендл модуля идентифицирует этотсегмент. Для любого приложения создается только один описывающий сегмент,который разделяется между всеми копиями этого приложения. Для получения хендламодуля Вы можете воспользоваться функциями:
HMODULE    GetModuleHandle(lpszFileName );
int         GetModuleFileName(hInstance, lpsBuffer, cbMaxSize );
В большинстве случаев, функции Windows API, работающие схендлом модуля, корректно выполняются при передачи им хендла копии приложения,так что в документации возможен некоторый разнобой в используемых терминах.
В Win32 хендл модуля являетсясинонимом хендла копии приложения. В документации встречаются оба термина, какони перекочевали из 16-ти битовых Windows, хотя они тождественны.
Сообщения. Посылка и передача сообщений
Ранее, на первых лекциях, мы рассматривали метод передачисообщений, называемый “посылкой” сообщений (post). При использовании этогометода сообщение ставится в очередь приложения и позже извлекается из нее. Однакоэтот механизм не всегда удобен, так как не позволяет получить результатаобработки сообщения, или дождаться его завершения. Точнее, позволяет, но оченьгромоздким способом.
Для решения этих задач вводится альтернативный механизм,называемый передачей сообщений. При этом сообщение в очередь не попадает инаправляется непосредственно оконной функции. По сути его можно рассматриватькак непосредственный вызов оконной функции с передачей ей указанных параметров.Это накладывает некоторые ограничения; так, например, нельзя передаватьсообщение WM_QUIT — оно обязательно должно пройти через очередь сообщений, иныесообщения (скажем, клавиатуры) дополнительно обрабатываются в цикле обработкисообщений и их тоже надо посылать а не передавать и т.д.
Кроме того сложности возникают при использованиимногопоточных приложений Win32 API — там принято, что сообщения, направленныеокну, обязательно обрабатываются тем потоком, который это окно создал. Этосущественно усложняет процесс передачи (не посылки) сообщений окну, созданномудругим потоком — передающий сообщение поток помещает это сообщение в очередьпринимающего потока с флагом ‘переданное сообщение’ и приостанавливаетсядо получения ответа. Принимающий поток, закончив обработку текущего сообщения,извлекает из очереди первыми сообщения, помеченные как переданные, обрабатыветих и после этого возобновляет работу пославшего потока. Однако при этомвозможно зависание обеих потоков, если поток, принимающий сообщение, пытаетсяпередать вызывающему потоку подтверждение — тот находится в остановленномсостоянии и не может обработать подтверждения, а принимающий в свою очередьостанавливается, пока подверждение не будет обработано.
Для посылки и передачи сообщений могут применяться следующиефункции:
BOOL PostMessage(hWnd, wMsg, wPar, lPar );
Посылает указанное сообщение окну (через очередь сообщений).
LONGSendMessage( hWnd, wMsg, wPar, lPar );
Передает сообщение окну (прямой вызов обработчика сообщений)и звращает управление в вызвавшую процедуру после обработки указанногосообщения. При этом она возвращает значение, возвращаемое оконной функцией. Прииспользовании этой функции сообщение вообще не поступает в очередь приложения(кроме приложений Win32 API). То есть Вы можете воспользоваться этой функцией дляобработки тех или иных сообщений до организации цикла обработкисообщений.
BOOLPostAppMessage( hTask, wMsg, wPar, lPar );               // Windows 3.x
BOOL PostAppMessage( dwProccessId,wMsg, wPar, lPar );         // Win32 API
BOOL PostThreadMessage( dwThreadId,wMsg, wPar, lPar );     // Win32 API
Посылает сообщение конкретной задаче. При этом в очередьсоответствующего приложения помещается сообщение, имеющее нулевой хендл окна — получателя. Соответственно такое сообщение не диспетчеризуется никакому окну.
Хендл задачи hTask не является хендлом копии приложения. Выможете использовать функцию GetCurrentTask для получения хендла задачи в средеWindows 3.x, а также функции GetCurrentThreadId и GetCurrentProcessId в Win32API.
для получения этого хендла.
BOOL PostQuitMessage(wPar );
Посылает сообщение WM_QUIT с заданным параметром wPar вашемуприложению. Сообщение WM_QUIT используется для завершения главного циклаобработки сообщений.Типичные последовательности сообщений,получаемых окном.
Сейчас мы займемся изучением основных сообщений, используемыхокном. При этом мы рассмотрим несколько типичных последовательностей сообщений,получаемых окном. Так, например, мы рассмотрим последовательность сообщений,получаемых окном при его создании. При этом надо считать, что приводимыесообщения в последовательности являются как бы “скелетом”, а реальнаяпоследовательность может иметь большее число сообщений, или некоторые могутотсутствовать. Это определяется характеристиками окна, его свойствами ивыполняемой дополнительной обработкой сообщений. (Так, например,последовательности сообщений, получаемых “скрытыми” окнами или окнами вминимизированном состоянии могут существенно отличаться).
В рассматриваемых нами последовательностях сообщенийбольшинство сообщений не проходят через очередь сообщений, а передаютсянепосредственно оконной процедуре какой-либо функцией. Именно логика выполненияэтой функции и определяет последовательность получения сообщений. Кроме того, некоторыесообщения в этих цепочках являются как бы “вложенными” — то есть онипорождаются при обработке какого-либо иного сообщения.Инициализацияокна
Для создания окна используется функция 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. Если окно не имеет заголовка (captionbar), то это сообщение не посылается.
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 losingfocus   0
получаем фокус ввода, причем параметрwParam указывает хендл окна, теряющего фокус ввода (или NULL).
потеря фокуса ввода окном:
WM_KILLFOCUS                                  hWndreceived 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(...) (или эквивалентной) вследующем порядке:
WM_WINDOWPOSCHANGING          0 &WINDOWPOS
cообщение указывает на то, чтоположение или состояние окна изменяется. Параметр lParam содержит указатель наструктуру WINDOWPOS, описывающую положение окна и выполняемую операцию. Изменивсоответствующие поля структуры можно изменить положение и размеры окна илиповлиять на выполняемые действия.

если окно просто активируется, тообычно следующее сообщение WM_WINDOWPOSCHANGED, завершающее всю цепочку, безвсех рассматриваемых нами промежуточных сообщений, применяемых при измененииразмеров или положения.
WM_GETMINMAXINFO                      0 &MINMAXINFO
проверка новых размеров окна
WM_NCCALCSIZE                               flag  &NCCALCSIZE_PARAMS
определение размера внутреннейобласти
WM_NCPAINT     0                                0
отображение внешней области окна
WM_ERASEBKGND                              hDC 0
очистка фона окна
WM_WINDOWPOSCHANGED            0 &WINDOWPOS
состояние окна изменено. ПараметрlParam является указателем на структуру WINDOWPOS, содержащую данные оположении и размерах окна. Сообщения WM_WINDOWPOSCHANGING… WM_WINDOWPOSCHANGEDчасто не содержат между собой никаких иных сообщений, если состояние, размер иположение не изменились. (Часто это бывает, если окно активируется в ответ на“щелчок мышкой”).
WM_MOVE           0                                y& x
WM_SIZE              type                           height& width
Эти сообщения информируют о новомположении и размерах окна. Они посылаются при соответствующих измененияхпроцедурой DefWindowProc() при обработке сообщения WM_WINDOWPOSCHANGED. Хотя вдокументации указано, что можно несколько ускорить работу, перехватывая вместоWM_MOVE и WM_SIZE сообщение WM_WINDOWPOSCHANGED и не вызывая при этомDefWindowProc(), но использовать этот прием нужно очень осторожно — так каксообщения WM_SIZE и WM_MOVE используются MDI окнами.
Рассмотренная нами цепочка сообщенийпорождается функцией SetWindowPos (или эквивалентной) и эти сообщениянепосредственно передаются окну, а не посылаются.
WM_PAINT           0                                0
рисование внутренней области окна. Врезультате выполненной операции окно (или его часть), как правило, маркируетсякак неверное, что приводит к перерисовке окна. Сообщение WM_PAINT извлекаетсяиз очереди сообщений и может обрабатываться с некоторой задержкой послеизменения размеров, положения или состояния окна.Обновлениеокна
После вызова ShowWindow() в WinMain() обычно следуетпроцедура UpdateWindow(). Эта процедура проверяет наличие неверныхпрямоугольников и, если они есть, передает сообщение WM_PAINT (не ставит вочередь, а вызывает обработку этого сообщения).
Обработка UpdateWindow():
WM_PAINT           0                                0
Нарисовать внутреннюю область окна.Если для получения хендла контекста устройства используется функцияBeginPaint(), то она может передавать сообщение WM_ERASEBKGND для очистки фонав неверном прямоугольнике (если при его создании было указано, что фон долженбыть восстановлен).
WM_ERASEBKGND                              hDC 0
Обрабатывая это сообщение, мы должнызакрасить фон окна, используя переданный нам хендл контекста устройства, иливызвать обработку по умолчанию.

Уничтожение окна
Для уничтожения окна надо вызвать функцию DestroyWindow(),которая выполнит требуемые действия по закрытию окна. Причем при этомпосылаются:

Иногда бывает так, что сообщениядеактивации окна не поступают, происходит деактивация приложения и уничтожениеокна;
WM_DESTROY    0                                0
Уничтожение внутренней области окна.
WM_NCDESTROY                                0 0
Уничтожение внешней области окна.
Сообщения WM_DESTROY и WM_NCDESTROY являются последнимисообщениями, получаемыми окном. После WM_NCDESTROY окно не получит ни одногосообщения, поэтому Вы можете смело разрушать все созданные для окна структурыданных.
Сообщение WM_DESTROY удобно применять для уничтожения всехобъектов, связянных с данным окном, в том числе и дочерних окон.
Внимание: во время обработки сообщений WM_DESTROY и WM_NCDESTROY нельзяактивировать каких-либо дочерних окон. (В том числе нельзя применять функциюMessageBox, передавая ей хендл уничтожаемого окна в качестве родительского) — это приведет к появлению дополнительных сообщений, направленных уничтожаемомуокну, и, в конечном результате, к ошибке “General protection fault...”
Если Вы хотите получить подтверждение перед закрытием окна,то Вы должны использовать сообщение WM_CLOSE. Функция DefWindowProc,обрабатывая это сообщение, вызывает функцию DestroyWindow. Вы можете легко вставитьсобственные средства для обработки сообщения WM_CLOSE, и вызывать DestroyWindowили процедуру по умолчанию только при положительном ответе на запрос. СообщениеWM_CLOSE лучше посылать, а не передавать.
Событие WM_CLOSE используется самой средой, причем обычнопредваряется последовательностью сообщений, приводящей к закрытию окна.Например такой: активация системного меню — выбор пункта ‘Close’ — завершениеменю — посылка WM_SYSCOMMAND с параметром SC_CLOSE — посылка WM_CLOSE —уничтожение окна.Завершениеработы Windows
Существует еще два сообщения, которое могут привести кзакрытию окна:
WM_QUERYENDSESSION                  0 0
Это сообщение информирует о том, чтоWindows заканчивает работу когда приложение активно. Оно посылается ко всемзапущеным приложениям. Если все возвращают TRUE, то Windows завершает работу.
Обрабатывая это сообщение, Вы должнывернуть TRUE, если Ваше приложение может быть завершено, или FALSE в противномслучае. При этом Windows продолжит нормальную работу.
WM_ENDSESSION                                TRUE/FALSE 0
Это сообщение посылается активномуприложению, если оно ответило TRUE на сообщение WM_QUERYENDSESSION. Флаг впараметре ‘wPar’ равный TRUE указывает, что работа Windows может завершитьсясразу после обработки этого сообщения. Вы не обязаны уничтожать окно и посылатьсебе WM_QUIT для завершения работы, если завершается работа всего Windows./>
 

Клавиатура.Сообщенияклавиатуры
 
Сейчас мы рассмотрим основные сообщения клавиатуры инесколько функций, предназначенных для работы с ней. Когда мы нажимаем на любуюкнопку, наше (точнее — активное) приложение получает сообщение
WM_KEYDOWN  VkCode                    dwKeyData
Параметр wPar содержит виртуальныйкод нажатой клавиши. В Windows поддерживается специальная система нумерацииклавиш, которая представлена их виртуальными номерами.
Параметр dwKeyData присутствует длявсех сообщений клавиатуры и содержит информацию о текущем событии.
Для большинства клавиш их виртуальный код соответствует тойзаглавной букве, которая на них нанесена (для английской клавиатуры). Например,виртуальный код клавиши A равен ASCII коду символа ‘A’. Для тех клавиш, которыене соответствуют буквам и символам предусмотрены специальные номера, напримерVK_F6 для клавиши F6, VK_MENU для клавиши Alt, VK_RETURN для клавиши Enter.
Если посмотреть на список виртуальных кодов (это можносделать в WINDOWS.H), то мы увидим несколько странных клавиш:
VK_LBUTTON,VK_RBUTTON, VK_MBUTTON
соответствующих кнопкам мыши. Однако эти виртуальные кодыиспользуются несколько иначе, и приложение не получает сообщений WM_KEYDOWN принажатии кнопок мыши.
Параметр dwKeyData присутствует длявсех сообщений клавиатуры и содержит следующую информацию:
/>
WM_KEYUP         VkCode                    dwKeyData
Кроме сообщения WM_KEYDOWN Windowsпосылает сообщения WM_KEYUP при отпускании клавиши. Параметры этого сообщениятакие же, как и у сообщения WM_KEYDOWN.
Когда Ваше приложение извлекает из очереди сообщение WM_KEYDOWN,то обычно оно транслируется с помощью функции TranslateMessage (это происходитв главном цикле обработки сообщений). Эта функция осуществляет трансляциюсообщений клавиатуры и в результате посылает сообщения WM_CHAR, соответствующиенажатому символу или WM_DEADCHAR.
WM_CHAR           nCharacter               dwKeyData
Сообщает приложению о том, чтонажатая клавиша соответствует данному (nCharacter) символу. Если Выразрабатываете, например, собственный редактор, то Вы должны обрабатыватьсообщения WM_CHAR для формирования текста, а не сообщения WM_KEYDOWN.
WM_DEADCHAR nDeadChar               dwKeyData
Это сообщение информирует приложениео нажатии так называемой Dead-Key. Dead-Key клавиши обычно соответствуютакцентным символам. Так, например, немецкая клавиатура имеет несколько Dead-Key,скажем ‘. Если нажать эту клавишу, а, затем, букву A, то результат долженсоответствовать A с ударением. При этом нажатый ‘ сам по себе не соответствуетникакому символу (это Dead-Key), а служит модификатором для следующей клавиши.Таким образом на последовательность сообщений WM_KEYDOWN для клавиш ‘ и A будутгенерироваться сообщения WM_DEADCHAR для ‘ и WM_CHAR для A с ударением. Окно,имеющее фокус ввода, и активное окно
Помимо рассмотренных четырех сообщений Windows использует еще4 сообщения, содержащих такую же информацию, как и уже рассмотренные сообщенияклавиатуры:
WM_SYSKEYDOWN                             VkCode dwKeyData
WM_SYSKEYUP VkCode                    dwKeyData
WM_SYSCHAR    nCharacter               dwKeyData
WM_SYSDEADCHAR                           nDeadChar      dwKeyData
Обычно эти сообщения посылаются принажатии клавиш совместно с клавишей Alt. Вы обязательно должны предусмотретьобработку этих сообщений по умолчанию, так как, если этого не делать, тобудет нарушен стандартный интерфейс Windows – перестануть работать такиеклавиши как Alt–Tab, Ctrl–Esc и пр.
Сейчас мы должны будем разобраться в различиях понятий“активное окно” и “окно, имеющее фокус ввода”. Сформулируем несколько правил,позволяющих различать эти понятия.
·   окно, имеющее фокус ввода, всегдаактивно.
·   в любой момент времени существуетактивное окно.
·   минимизированное окно не может иметьфокуса ввода, если активное окно минимизировано, то фокус ввода не принадлежитникакому окну.
·   если активное окно не минимизировано,то оно имеет фокус ввода.
Все, что мы сейчас выяснили о сообщениях клавиатуры относитсяк окну, имеющему фокус ввода. Если наше окно активно и не имеет фокуса ввода,то вместо сообщений WM_KEYDOWN, WM_KEYUP, WM_CHAR и WM_DEADCHAR оно будетполучать сообщения WM_SYSKEYDOWN, WM_SYSKEYUP, WM_SYSCHAR и WM_SYSDEADCHAR.
Для чего в Windows используются эти два понятия? Представимсебе, что мы разрабатываем какой-либо редактор. Для управления им мы используемобычные (не системные) сообщения клавиатуры. Теперь мы минимизировали нашредактор и сделали его активным. Если бы при этом он по-прежнему получалобычные сообщения клавиатуры, то пришлось бы специально предусматриватьблокировку ввода данных в минимизированном состоянии — так как работа “вслепую” вряд-ли будет удобна. А, так как в минимизированном состоянии он теряетфокус ввода, то вместо обычных сообщений он будет получать системные, чтоисключит нежелательный эффект.
Однако, обрабатывая системные сообщения, нельзя предполагать,что клавиша Alt была нажата заранее — минимизированное активное окно будетполучать эти сообщения даже для обычных клавиш. Надо обязательно проверять битс номером 1D (Context code) в dwKeyData, что бы убедиться в активностиAlt-статуса.
Здесь же надо обратить внимание на то, что в документации оWindows встречается две трактовки понятия “активное окно”
·   с одной стороны это может быть окно,получающее сообщения от клавиатуры; Такое окно может быть только одно.
·   с другой стороны активном считаетсявсякое окно, чье дочернее имеет фокус ввода. Активное окно выделяется цветомрамки и заголовка. В этом случае активных окон может быть много.Определение состояния отдельных клавиш
Работая с клавиатурой иногда приходится проверять состояниетой или иной конкретной клавиши. Для этого Windows содержит две функции
int         GetKeyState(nVkCode );
void      GetKeyboardState(lpbKeyStates );
Функция GetKeyState() возвращает слово, характризующеесостояние заданной клавиши. Если старший бит (маска 0x8000) равен 1, клавишанажата, если 0, то отпущена. Младший бит (маска 1) указывает состояние“переключаемой” клавиши (например, CapsLock).
Функция GetKeyboardState() заполняет массив из 256 байтсостояниями всех клавиш. В качестве индекса массива используется виртуальныйкод клавиш. Каждый байт массива описывает одну клавишу, его страший бит (маска0x80) описывает состояние клавиши, младший (маска 1) — состояние переключаемойклавиши.
В дополнение к этим функциям Windows содержит еще однуфункцию
void      SetKeyboardState(lpKeyStates );
которая позволяет задать состояние конкретных клавиш. Эта функциятолько корректирует соответствующий массив, с которым работает сама система, ноне посылает никаких сообщений, симулирующих работу с клавиатурой. Применять этуфункцию надо очень осторожно, так как клавиатура является разделяемым ресурсом. Каретка
Говоря о клавиатуре мы должны ввести еще одно понятие — каретка (caret). Дело в том, что Windows использует два указующих элемента — курсор (cursor), который показывает положение мыши, и каретка, котораяпоказывает место, в которое будет вводиться текст. Каретка управляетсяклавиатурой.
При работе с кареткой надо учитывать некоторые особенности.Практически все они связаны с тем, что каретка является разделяемым ресурсом,поэтому Вы должны внимательно следить за корректным использованием каретки.Так, например, Вы можете создавать собственную каретку; однако Вы должныпредусмотреть средства для ее “скрывания” и уничтожения в тот момент, когдаВаше приложение теряет фокус ввода, и создавать или показывать ее, только еслиВаше окно имеет фокус ввода.
Для работы с кареткой предназначены следующие функции:
void ShowCaret(hWnd );
void HideCaret( hWnd );
С их помощью Вы можете показать каретку или сделать ееневидимой. Параметр hWnd может быть NULL, если используется текущее окно. Видимаякаретка автоматически начинает мигать.
voidSetCaretPos( nX, nY );
void GetCaretPos( lpPoint );
void SetCaretBlinkTime( mMSec );
UINT GetCaretBlinkTime( void );
Эти функции позволяют задать положение каретки в координатахокна и период мигания каретки, в миллисекундах. Кроме того Вы можете создаватьсобственную каретку с помощью функции
voidCreateCaret( hWnd, hBmp, nWidth, nHeight );
Параметр ‘hBmp’ может быть хендлом битмапа, при этомпараметры ‘nWidth’ и ‘nHeight’ игнорируются, или одним из двух значений: 0 — сплошная каретка, или 1 — “серая” каретка; в этом случае параметры ‘nWidth’ и‘nHeight’ задают размеры каретки.
void DestroyCaret( void);
Эта функция уничтожает текущую каретку (если кареткаиспользует битмап, то битмап сохраняется).


Не сдавайте скачаную работу преподавателю!
Данный реферат Вы можете использовать для подготовки курсовых проектов.

Поделись с друзьями, за репост + 100 мильонов к студенческой карме :

Пишем реферат самостоятельно:
! Как писать рефераты
Практические рекомендации по написанию студенческих рефератов.
! План реферата Краткий список разделов, отражающий структура и порядок работы над будующим рефератом.
! Введение реферата Вводная часть работы, в которой отражается цель и обозначается список задач.
! Заключение реферата В заключении подводятся итоги, описывается была ли достигнута поставленная цель, каковы результаты.
! Оформление рефератов Методические рекомендации по грамотному оформлению работы по ГОСТ.

Читайте также:
Виды рефератов Какими бывают рефераты по своему назначению и структуре.

Сейчас смотрят :

Реферат Рынок кофе
Реферат Лексическое и грамматическое значение слова
Реферат «Проблема формирования нравственных ценностей школьников в современных условиях»
Реферат Организация кредитования физических лиц в коммерческом банке
Реферат Платежный баланс страны (на примере Казахстана)
Реферат Aging And Marriage Essay Research Paper Reaction
Реферат Производные имена в информативных жанрах
Реферат Формирование управленческой компетентности будущего учителя начальных классов
Реферат Управление конфликтами на примере Алтайского краевого центра по борьбе со СПИДом и инфекционными заболеваниями
Реферат Розвязок інтеграла метоном Нютона Котеса та Сімсона
Реферат Международные валютно-финансовые системы
Реферат Древняя Русь - здоровый образ жизни
Реферат Юридическая сила инструкций Центральной избирательной комиссии РФ и их место в правовой системе
Реферат Ii. История южных и западных славян в Новое время (конец XVIII в. 1914 г.)
Реферат История становления и развития семейного права