47816 (597361), страница 10

Файл №597361 47816 (Ознакомление с приложениями Windows) 10 страница47816 (597361) страница 102016-07-30СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 10)

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

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

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

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

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

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

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

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


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

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

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

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

При разработке 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
#include

#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 );

PostQuitMessage( 0 );
}

LRESULT WINAPI _export WinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg ) {
HANDLE_MSG( hWnd, WM_CREATE, Cls_OnCreate );
HANDLE_MSG( hWnd, WM_PAINT, Cls_OnPaint );
HANDLE_MSG( hWnd, WM_DESTROY, Cls_OnDestroy );
default: break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}

static BOOL init_instance( HINSTANCE hInstance )
{
WNDCLASS wc;

wc.style = 0;
wc.lpfnWndProc = WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szWndClass;
return RegisterClass( &wc ) == NULL ? FALSE : TRUE;
}

int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow )
{
UNUSED_ARG( lpszCmdLine );
MSG msg;
HWND hWnd;

if ( !hPrevInst ) {
if ( !init_instance( hInst ) ) return 1;
}

hWnd= CreateWindow(
szWndClass, // class name
"window header", // window name
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT,CW_USEDEFAULT, // window position
CW_USEDEFAULT,CW_USEDEFAULT, // window size
NULL, // parent window
NULL, // menu
hInst, // current instance
NULL // user-defined parameters
);

if ( !hWnd ) return 1;

ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );

while ( GetMessage( &msg, NULL, NULL, NULL ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}

return msg.wParam;
}


Немного об объектах

Здесь мы рассмотрим некоторые основные особенности реализации объектно–ориентированного программирования в Windows. В последнее время получили огромное распространение библиотеки объектов для создания приложений в среде Windows. Особенно широко они стали распространяться с развитием систем визуального программирования. Наибольшее распространение получили библиотеки объектов компаний

  • Borland — Object Windows Library (OWL), поддерживается компиляторами Borland C++ (рассматривается версия v2.5, сопровождающая компилятор Borland C/C++ v4.5).

  • Microsoft — Microsoft Foundation Classes (MFC), поддерживается наибольшим количеством компиляторов, среди которых Microsoft Visual C++, Watcom C++, Symantec C++ и другие (рассматривается версия v4.0, сопровождающая Visual C/C++ v4.0).

Такие библиотеки достаточно многофункциональны и громоздки, размер исполняемого файла, созданного с их помощью редко бывает меньше 300–400K. Конечно, при разработке больших систем, поддерживающих такие инструменты как OLE, DAO или WOSE, регистрирующих свои собственные типы файлов и т.д., использование этих библиотек может существенно сократить время, необходимое для разработки приложения.

Эти библиотеки объектов, хотя и имеют огромное количество различий, неизбежно имеют и много общего, что определяется платформой, на которой они работают — Windows. Для обеспечения эффективной работы приложений эти библиотеки вынуждены предусматривать простой механизм доступа посредством методов объектов к функциям API, что их неизбежно сближает между собой. Кроме того реализация и иерархия объектов в Windows неизбежно приводит к появлению чем–то сходной иерархии классов в библиотеках ООП.

В этом разделе мы рассмотрим простейшее приложение в среде Windows, построенное средствами ООП, причем все классы будут оригинальными — ни MFC, ни OWL не применяется. Это сделано для того, что бы “извлечь” на поверхность некоторые аспекты разработки классов для Windows–приложений. Здесь будут использоваться существенно упрощенные методы реализации объектов, по сравнению с “большими” библиотеками.

Возможно, что в некоторых частных случаях использование такого подхода может оказаться и более продуктивным, чем применение MFC или OWL. Особенно, если ваше приложение похоже на простейшее “Hello, world!” (в этом случае, правда, еще удобнее может быть обойтись совсем без классов).


Особенности ООП в Windows

На самом деле Windows не является настоящей объектно–ориентированной средой. Хотя окно и может быть названо объектом ООП, но лишь с достаточной натяжкой. Самое существенное отличие окна в Windows от объекта ООП заключается в том, что сообщение, обрабатываемое оконной функцией, во многих случаях не выполняет действий, а является “информационным”, указывая на то, что над окном выполняется та или иная операция какой–либо внешней функцией.

Характеристики

Тип файла
Документ
Размер
2,36 Mb
Тип материала
Учебное заведение
Неизвестно

Список файлов книги

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
7029
Авторов
на СтудИзбе
260
Средний доход
с одного платного файла
Обучение Подробнее