на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Ознакомление с приложениями Windows
p align="left">0 -- окно успешно создано; функция CreateWindow или CreateWindowEx вернет хендл окна.

Сообщения WM_DESTROY и WM_QUIT

Еще одно сообщение, интересующее нас -- WM_DESTROY. Это сообщение посылается окну в момент его уничтожения. Это одно из последних сообщений, которое получает окно -- можно считать, что после этого оно уже не существует, причем в момент получения этого сообщения окно уже невидимо. В этот момент вы можете выполнить необходимые операции по освобождению выделенных при создании окна ресурсов. Оба параметра сообщения WM_DESTROY не используются.

Как и WM_CREATE сообщение WM_DESTROY является информационным -- реальное уничтожение окна осуществляется функцией DestroyWindow, а не обработчиком сообщения WM_DESTROY. Независимо от способа обработки этого сообщения окно будет уничтожено.

Если ваша оконная функция обслуживает главное окно приложения, то в момент уничтожения окна вы должны принять меры для завершения работы всего приложения в целом. Для этого вы должны послать сообщение WM_QUIT, при извлечении которого из очереди закончится цикл обработки сообщений. Если этого сообщения не послать, то цикл обработки сообщений продолжит работу дальше после закрытия всех имеющихся окон. На практике это означает что приложение вообще перестанет получать сообщения и “зависнет” на функции GetMessage, которая будет ждать, пока не придет новое сообщение. В случае Windows 3.x есть единственный способ удалить такое приложение -- перезапуск всего Windows (в Windows-95 или Windows NT такое приложение можно снять самому с помощью менеджера задач). Сообщение WM_QUIT посылается с помощью функции:

void PostQuitMessage( nExitCode );

Параметр nExitCode будет передан как wParam сообщения WM_QUIT и позже возвращен функцией WinMain в качестве параметра завершения.

Обработчиков для сообщения WM_QUIT писать не надо, так как:

Во-первых, функция GetMessage, получив это сообщение просто вернет FALSE, так что цикл обработки сообщений будет закончен без трансляции и диспетчеризации этого сообщения.

Во-вторых, это сообщение адресовано не окну, а приложению. То есть, даже если воспользоваться функцией PeekMessage для извлечения сообщения WM_QUIT из очереди (в отличие от GetMessage это получится), оно не будет отправлено никакому окну, так как хендл окна-получателя равен NULL.

Сообщение WM_PAINT

Последнее рассматриваемое нами сообщение -- WM_PAINT. Оба параметра сообщения WM_PAINT не используются. С этим сообщением нам придется разбираться подробнее. Раньше, когда мы обсуждали разделение экрана между разными задачами, говорилось о том, что в Windows невозможно полностью виртуализовать всю работу с экраном -- то есть содержимое невидимой в данной момент части окна для Windows остается неизвестным.

Представим себе, что невидимая часть окна стала видимой (например, вследствие перемещения другого окна) -- тогда возникает необходимость восстановить ее образ. Windows не знает, что там должно быть отображено, следовательно отображением может заниматься только само приложение.

Для этого вводится специальное сообщение WM_PAINT, которое посылается окну тогда, когда часть окна (или все окно) нуждается в перерисовке. Часто перерисовка окна занимает значительное время, а обработку сообщений рекомендуется выполнять как можно быстрее; поэтому Windows особым образом обрабатывает WM_PAINT, что бы задержки в обработке этого сообщения не оказывали такого влияния на работу системы.

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

Приложение должно быть построено таким образом, что бы, получив сообщение WM_PAINT, оно могло перерисовать требуемую часть окна. То есть приложение должно знать, что, где и как должно быть нарисовано в окне, так как в любой момент может потребоваться многократная перерисовка какой-либо части окна.

Основы рисования в окне

Еще раз вспомним, каким образом появляется сообщение WM_PAINT: это происходит когда все окно, или только его часть становятся видимыми. Та часть окна, которая нуждается в перерисовке, является неверной -- ее содержимое не соответствует требуемому. Эта часть получила название неверный прямоугольник (invalid rectangle).

Соответственно, после перерисовки она перестает быть неверной -- то есть становится верным прямоугольником (valid rectangle).

Теперь стоит выяснить при каких условиях возникают неверные прямоугольники и как они используются. Для этого посмотрим на те ситуации, когда неверный прямоугольник может возникнуть, а когда нет:

Неверный прямоугольник возникает, если:

скрытая область окна (например, закрытая другим окном) становиться видимой.

область окна “прокручивается” (с помощью функций ScrollWindow или ScrollDC). В этом случае та часть окна, в которой должен появиться новый, невидимый ранее, текст, объявляется неверным прямоугольником.

окно изменяет размер. Обычно это приводит к появлению неверных прямоугольников только при увеличении размера окна и только на дополнительно появившейся поверхности. Однако, если при регистрации класса окна Вы указали стиль CS_HREDRAW или CS_VREDRAW, то все окно целиком будет рассматриваться как неверное.

Вами вызвана одна из функций:

void InvalidateRect( hWnd, lpRect, fErase );
void InvalidateRgn( hWnd, hRgn, fErase );

Параметры этих функций: hWnd -- хендл окна, содержащего прямоугольник (или регион), нуждающийся в перерисовке. lpRect -- указатель на структуру типа RECT, описывающую прямоугольник, или hRgn -- хендл нужного региона. fErase -- логическая (TRUE,FALSE) величина, указывающая, нужно ли восстанавливать фон неверной области, или нет.

Неверный прямоугольник не появляется при перемещении курсора мыши или пиктограмм через область окна -- Windows самостоятельно сохраняет и восстанавливает окно под курсором (или пиктограммой).

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

Еще о сообщении WM_PAINT

Допустим, что в результате какого-либо события появился неверный прямоугольник. Что с ним происходит дальше?

Windows, обнаружив неверный прямоугольник, принадлежащий какому-либо окну, ставит в очередь приложения сообщение WM_PAINT, адресованное этому окну. Оконная процедура, получив это сообщение, перерисовывает требуемую часть окна (или большую), после чего сообщает Windows о том, что неверный прямоугольник исправлен.

Если этого не сообщить Windows, то будет считаться, что прямоугольник остался неверным, и снова будут генерироваться сообщения WM_PAINT этому окну. Поэтому очень важно не оставлять после WM_PAINT неверных прямоугольников.

Таким образом осуществляется поддержание окна в требуемом состоянии. Однако перерисовка является медленным процессом (к тому же многие приложения перерисовывают большую часть окна, чем надо), а неверные прямоугольники могут появляться в нескольких экземплярах, иногда перекрывающихся, до того, как приложение начнет обрабатывать WM_PAINT.

Поэтому в Windows сообщение WM_PAINT трактуется не как сообщение, а скорее как состояние: если в очереди приложения есть сообщение WM_PAINT, то окно надо перерисовать. А если в это время появляются новые неверные прямоугольники, то новых сообщений WM_PAINT в очередь не попадает, а просто новый неверный прямоугольник объединяется со старым. Обычно в результате объединения возникает некоторая неверная область сложной формы В первых версиях Windows в результате объединения формировался новый неверный прямоугольник. В современных версиях вместо неверного прямоугольника реально формируется неверный регион, который может иметь сложную форму..

Сообщение WM_PAINT является низкоприоритетным. Чем отличается низкоприоритетное сообщение от нормального? Тем, что, если в очереди приложения есть только сообщения с низким приоритетом, то Windows может передать управление другому приложению, имеющему в очереди сообщения нормального приоритета (в Windows только два сообщения являются низкоприоритетными: WM_PAINT и WM_TIMER).

Эти две особенности позволяют Windows сравнительно легко переносить продолжительное рисование окна, хотя при этом перерисовываемая поверхность зачастую приближается к размерам всего экрана. Специфичная обработка сообщения WM_PAINT является причиной того, что в Windows рекомендуется сосредоточивать все операции по выводу в окно в обработчике сообщения WM_PAINT.

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

все операции по выводу сосредотачиваются в обработчике сообщения WM_PAINT.

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

при этом сообщение только лишь оказывается в очереди, но оно не попадает на обработку немедленно, реальный вывод произойдет несколько позже. Если Вам надо именно сейчас осуществить вывод в окно, то добавьте вызов функции UpdateWindow. Эта функция немедленно передаст оконной процедуре сообщение WM_PAINT для его обработки.

Конечно, осуществление вывода при обработке других сообщений не является ошибкой, хотя делать этого не стоит, особенно если рисование сколько-нибудь сложное. К сожалению, всегда следовать этому правилу почти невозможно, однако нужны веские причины для его нарушения.

При обработке сообщения WM_PAINT стоит придерживаться нескольких правил, специфичных для этого сообщения:

Первое: Никогда не передавайте сообщение WM_PAINT непосредственно окну. Для этого существует функция UpdateWindow, которая генерирует это сообщение, если неверный прямоугольник существует.

Второе: Рекомендуется начинать обработку сообщения WM_PAINT с функции:

HDC BeginPaint( hWnd, lpPaintstruct );

и заканчивать функцией

void EndPaint( hWnd, lpPaintstruct );

где lpPaintstruct -- указатель на структуру типа PAINTSTRUCT. Эти функции выполняют несколько нужных дополнительных действий для обработки сообщения WM_PAINT, в том числе объявляют внутреннюю область окна корректной.

Наконец: Если все же Вы не используете BeginPaint...EndPaint, то обязательно объявляйте перерисованную область верной с помощью функции ValidateRect или ValidateRgn.

void ValidateRect( hWnd, lpRect );
void ValidateRgn( hWnd, hRgn );

Параметры этих функций: hWnd -- хендл окна, содержащего прямоугольник (или регион), нуждающийся в перерисовке. lpRect -- указатель на структуру типа RECT, описывающую прямоугольник, или hRgn -- хендл нужного региона.

Контекст устройства

Рассматривая сообщение WM_PAINT и неверные прямоугольники мы обсудили основные правила осуществления вывода в Windows. Теперь обзорно познакомимся с правилами осуществления вывода графической информации в окно.

В первом же написанном приложении 1a.cpp мы увидели, что функция вывода текста TextOut использовала не хендл окна, а так называемый хендл контекста устройства (HDC, device context). Зачем он понадобился? и почему бы не использовать вместо него хендл окна?

Дело в том, что все средства вывода в Windows относятся не к менеджеру окон, а к графическому интерфейсу устройств (GDI). GDI представляет собой библиотеку функций для выполнения графического вывода на различных устройствах, не только на дисплее. При создании GDI стремились сделать работу с устройствами независимой от самих устройств. Так, одни и те же функции, осуществляющие вывод текста, рисование линий и т.д. могут применяться для работы с дисплеем, принтером, плоттером и другими устройствами.

Для этого пришлось ввести дополнительное понятие -- контекст устройства, идентифицируемый его хендлом. Все функции вывода взаимодействуют с этим контекстом. Часто даже говорят, что функции GDI рисуют на контексте, а не непосредственно на устройстве. Контекст устройства описывает так называемые атрибуты контекста и непосредственно характеристики устройства, на котором осуществляется вывод.

Атрибуты контекста устройства независимы от самого устройства. Они характеризуют то изображение, которое будет рисоваться. В число атрибутов входят кисти, перья, цвет текста, цвет фона и многое другое. Так, назначив контексту устройства текущее перо вы определяете толщину, цвет и стиль (сплошная или прерывистая) тех линий, которые будут отображаться последующими вызовами функций, рисующих эти линии. При необходимости нарисовать линию другого стиля вы должны поменять текущее перо. Аналогично определяются кисть, используемая для закраски фона фигур, шрифт, применяемый при выводе текста, и много других атрибутов контекста устройства.

Информация об устройстве описывает непосредственно возможности самого графического устройства. Функции GDI взаимодействуют с устройством опосредованно -- через контекст и через драйвер этого устройства. Благодаря наличию информации об устройстве одна и та же функция GDI способна осуществлять вывод на любое устройство, для которого существует необходимый драйвер. Так, вы можете выбирать перо или кисть любого цвета, а GDI примет меры, что бы необходимое изображение было получено как на цветном дисплее, так и на черно-белом принтере или плоттере.

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13



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