на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Окна приложений в среде Windows
p align="left">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(...) (или эквивалентной) в следующем порядке:

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, если используется текущее окно. Видимая каретка автоматически начинает мигать.

void SetCaretPos( nX, nY );

void GetCaretPos( lpPoint );

void SetCaretBlinkTime( mMSec );

UINT GetCaretBlinkTime( void );

Эти функции позволяют задать положение каретки в координатах окна и период мигания каретки, в миллисекундах. Кроме того Вы можете создавать собственную каретку с помощью функции

void CreateCaret( hWnd, hBmp, nWidth, nHeight );

Параметр `hBmp' может быть хендлом битмапа, при этом параметры `nWidth' и `nHeight' игнорируются, или одним из двух значений: 0 - сплошная каретка, или 1 - “серая” каретка; в этом случае параметры `nWidth' и `nHeight' задают размеры каретки.

void DestroyCaret( void );

Эта функция уничтожает текущую каретку (если каретка использует битмап, то битмап сохраняется).

Страницы: 1, 2, 3



© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.