на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Ознакомление с приложениями Windows
p align="left"> IMPORTS
[internalname=] modulename.id
[internalname=] modulename.importname

Раздел IMPORTS задает соответствие внутренних имен импортируемых функций (internalname) функциям, экспортированным другими модулями. Возможно два метода связывания имен -- по идентификатору (первый пример), modulename -- имя экспортирующего модуля, id -- идентификатор; либо по именам (второй пример), importname -- внешнее имя функции, под которым она была экспортирована другим модулем.

Win32 API

Файл описания модуля в Win32 API используется для задания нестандартных характеристик динамически загружаемых библиотек. Полное описание файлов описания модуля для Win32 API надо смотреть в документации, сопровождающей применяемый компилятор.

Так как файл описания модуля используется для создания DLL, то первая директива -- LIBRARY. Часто применяется также директива EXPORTS для задания идентификаторов экспортируемых функций (обе -- см. в описании файла описания модуля для Windows API).

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

SECTIONS
secname [CLASS `classname'] [EXECUTE] [READ] [WRITE] [SHARED]

После указания имени секции (сегмента) следует необязательное указание имени класса и атрибутов этой секции -- разрешение на выполнение (EXECUTE), на чтение (READ), на запись (WRITE) и объявление секции разделяемой (SHARED) между разными копиями модуля (загруженными в разных адресных пространствах разных приложений!).

Дополнительные разделы

В этом разделе будет рассказано о малоизвестном заголовочном файле -- windowsx.h. В некоторых случаях разработчики его, конечно, используют, но редко больше чем на 5% от его возможностей. Этот заголовочный файл был разработан специально для облегчения контроля исходного текста программы. К сожалению, в большей части документации, сопровождающей компиляторы, этот файл вообще не описан, хотя существует уже очень давно. Пожалуй впервые он описан в документации, сопровождающей Microsoft Visual C++ 4.0 (Microsoft Developer Studio, раздел “SDKs|Win32 SDK|Guides|Programming Techniques|Handling Messages with portable macros”). Однако даже там описаны только принципы его применения, но не дано подробное описание всех его макросов. Как результат -- при применении windowsx.h приходится постоянно обращаться к его исходному тексту.

Заголовочный файл WINDOWSX.H

В Windows часто бывает так, что одна и та же функция может работать с объектами разных типов. В таких случаях бывает трудно проследить корректность ее применения. Для этого в windowsx.h включено много макросов, которые переопределяют вызовы таких функций, что бы текст получился более читаемым. Именно эту возможность windowsx.h иногда применяют на практике.

Например функция DeleteObject может применяться для удаления многих объектов GDI (Graphics Devices Interface) -- карандашей, кистей, регионов и пр. По названию функции понять, какой-именно объект она удаляет нельзя, поэтому при чтении исходного кода приходится сосредотачиваться на параметрах этой функции. В windowsx.h определены макросы:

#define DeletePen(hpen) DeleteObject((HGDIOBJ)(HPEN)(hpen))
#define DeleteBrush(hbr) DeleteObject((HGDIOBJ)(HBRUSH)(hbr))
#define DeleteRgn(hrgn) DeleteObject((HGDIOBJ)(HRGN)(hrgn))

при использовании которых текст становится более читаемым и легче находятся ошибки.

При включении файла windowsx.h в ваше приложение это надо делать после включения основного файла windows.h:

#define STRICT
#include <windows.h>
#include <windowsx.h>

Для того, что бы получить представление о возможностях windowsx.h рекомендуется посмотреть его исходный текст. В нем присутствуют следующие разделы:

макросы для работы с функциями ядра (несколько макросов для работы с глобальной памятью)

макросы для работы с объектами GDI

макросы для работы с окнами (вызовы стандартных функций)

распаковщики сообщений (самая большая часть)

макросы для работы с окнами стандартных классов (кнопки, списки и пр.)

некоторые макросы для оптимизации стандартной библиотеки времени выполнения

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

Распаковщики сообщений

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

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

Вполне очевиден выход -- разнести обработку сообщений по отдельным функциям, которые будут вызываться из процедуры обработки сообщений. Однако для каждого сообщения передаются свои данные, упакованные в двух параметрах -- wParam и lParam. Иногда они не используются, иногда содержат какие-либо значения, иногда -- указатели. Естественно, было бы удобным передавать в вызываемую функцию уже распакованные параметры. Затруднение здесь вызывает то, что для Windows API и для Win32 API одни и те же данные одного и того же сообщения могут быть упакованы по разному Это связано с тем, что параметр wParam имеет тип UINT -- то есть он в Windows API представляет собой 16ти разрядное слово, а в Win32 API -- 32х разрядное. Кроме того, в младшем или старшем слове lParam часто размещается хендл, который в Windows API 16ти разрядный. К сожалению в Win32 API хендлы 32х разрядные, так что уместить его на прежнем месте не представляется возможным..

При разработке windowsx.h это все было учтено (для Windows API и для Win32 API распаковщики определяются по разному). Так, для каждого сообщения WM_xxx определен свой макрос с именем HANDLE_WM_xxx. Например, для сообщения WM_CREATE определен макрос:

HANDLE_WM_CREATE(hwnd, wParam, lParam, fn)

Параметры всех макросов одинаковые, что позволяет передавать им непосредственно параметры сообщения (окно-адресат hwnd, параметры wParam и lParam), а также имя функции-обработчика fn. Этот макрос должен использоваться внутри конструкции switch для вызова нужной функции и передачи ей распакованных параметров. Например фрагмент следующего вида:

switch ( uMsg ) {
case WM_CREATE: return HANDLE_WM_CREATE(hWnd,wParam,lParam,fnOnCreate);
// ...
}

будет превращен компилятором в следующий фрагмент (подробнее см. исходный текст windowsx.h):

switch ( uMsg ) {
case WM_CREATE:
return ((fnOnCreate)((hWnd),(LPCREATESTRUCT)(lParam)) ?
0L : (LRESULT)-1L);
// ...
}

То есть при раскрытии макроса HANDLE_WM_xxx осуществляется распаковка параметров, вызов функции и анализ возвращаемого результата. Здесь, кстати, скрыта одна ловушка (по счастью крайне редкая): результат, возвращаемой функцией-обработчиком не всегда будет совпадать с результатом, описанным в справочнике для данного сообщения. Случай с WM_CREATE именно такой -- согласно описанию обработчик WM_CREATE должен вернуть 0L, если все в порядке. А, как мы видим в приведенном фрагменте, функция, вызываемая распаковщиком, должна вернуть TRUE, то есть не 0, если все в порядке (распаковщик сам заменит TRUE на 0L).

При рассмотрении этого примера возникает вопрос -- а как должна быть описана функция-обработчик, что бы распаковщик ее правильно вызывал? Ответ прост -- в самом файле windowsx.h перед определением соответствующего макроса приводится прототип этой функции. То есть нам надо сделать следующее: открыть windowsx.h, найти в нем строку, где определяется распаковщик для WM_CREATE (это легко делается поиском) и посмотреть на приведенный там текст:

/* BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) */
#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn) \
((fn)((hwnd), (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L)
#define FORWARD_WM_CREATE(hwnd, lpCreateStruct, fn) \
(BOOL)(DWORD)(fn) ((hwnd), WM_CREATE, 0L, \
(LPARAM)(LPCREATESTRUCT)(lpCreateStruct))

Описание функции Cls_OnCreate мы и ищем. Далее нам надо его просто скопировать в наше приложение и исправить при желании имя функции. Единственное, что остается не слишком удобным -- так это вызов макроса-распаковщика -- уж очень длинная строка получается. Для этого в windowsx.h содержится отдельный небольшой макрос:

HANDLE_MSG( hWnd, uMsg, fn )

Используется он таким способом:

switch ( uMsg ) {
HANDLE_MSG( hWnd, WM_CREATE, Cls_OnCreate );
// ...
}

При этом он сам вставляет “case WM_xxx: return ...” и прочее. Важно следить, что бы в описании оконной процедуры параметры wParam и lParam назывались именно так и не иначе. Дело в том, что HANDLE_MSG при обращении к макросу HANDLE_WM_xxx указывает ему именно эти имена.

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

Рассмотренные пока макросы-распаковщики позволяли нам вызвать функцию-обработчик сообщения, имея для нее данные, упакованные в wParam и lParam. Однако иногда возникает другая необходимость -- имея параметры функции передать какое-либо сообщение. Для этого предназначены макросы FORWARD_WM_xxx. Для использования этих макросов, необходимо, что-бы функция, получающая параметры сообщения, имела следующий вид:

LRESULT proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

Макросы FORWARD_WM_xxx получают в качестве параметров распакованные данные (как и функция-обработчик), упаковывают их в параметры сообщения и вызывают указанную функцию. По счастью практически все функции, которые придется вызывать с помощью макросов FORWARD_WM_xxx (SendMessage, PostMessage, DefWindowProc и пр.) соответствуют приведенному описанию.

Например, сообщение WM_SETFONT посылается окну (стандартного класса) для того, что бы назначить ему нужный шрифт. Параметры этого сообщения следующие: wParam содержит хендл шрифта, а младшее слово lParam указывает, надо ли перерисовывать окно сразу после смены шрифта. Предположим, что ваше окно имеет дочернее окно, и вам хочется сделать так, чтобы при смене шрифта в вашем окне одновременно менялся шрифт в дочернем. Соответственно вы должны включить в оконную процедуру обработку сообщения WM_SETFONT и в его обработчике передать такое-же сообщение дочернему окну.

void Cls_OnSetFont( HWND hwnd, HFONT hfont, BOOL fRedraw );

LRESULT WINAPI _export proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg ) {
// ...
HANDLE_MSG( hWnd, WM_SETFONT, Cls_OnSetFont );
// ...
}
}

// ...

void Cls_OnSetFont( HWND hwnd, HFONT hfont, BOOL fRedraw )
{
HWND hwndChild = ...; // определение хендла дочернего окна
FORWARD_WM_SETFONT( hwndChild, hfont, fRedraw, SendMessage );
}

Здесь, кстати, можно было бы воспользоваться макросом SetWindowFont из того же windowsx.h. Этот макрос обращается к FORWARD_WM_SETFONT, как в рассмотренном примере, однако текст при этом становится более читаемым:

void Cls_OnSetFont( HWND hwnd, HFONT hfont, BOOL fRedraw )
{
HWND hwndChild = ...; // определение хендла дочернего окна
SetWindowFont( hwndChild, hfont, fRedraw );
}

Добавление собственных распаковщиков не должно вызвать больших затруднений -- достаточно только разработать реализации макросов HANDLE_WM_xxx и FORWARD_WM_xxx аналогично уже сделанному в windowsx.h.

Пример 1B -- использование распаковщиков сообщений

Этот пример иллюстрирует применение распаковщиков сообщений на примере простейшего приложения. Фактически он соответствует слегка измененному примеру 1A, в котором оконная процедура переписана для использования распаковщиков сообщений. Функция WinMain в этом примере осталась без изменений.

#define STRICT
#include <windows.h>
#include <windowsx.h>

#define UNUSED_ARG(arg) (arg)=(arg)

static char szWndClass[] = "test window";

BOOL Cls_OnCreate( HWND hwnd, LPCREATESTRUCT lpCreateStruct )
{
UNUSED_ARG( hwnd );
UNUSED_ARG( lpCreateStruct );
return TRUE;
}

void Cls_OnPaint( HWND hwnd )
{
PAINTSTRUCT ps;

BeginPaint( hwnd, &ps );
TextOut( ps.hdc, 0, 0, "Hello, world!", 13 );
EndPaint( hwnd, &ps );
}

void Cls_OnDestroy( HWND hwnd )
{
UNUSED_ARG( hwnd );

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



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