Чтение онлайн

на главную - закладки

Жанры

Применение Windows API

Легалов А. И.

Шрифт:

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

Каждое сообщение адресовано определенному окну. Когда Вы запрашиваете сообщение у Windows, система выяснит класс вашего окна, найдет связанную с ним оконную процедуру, и вызовет ее. Любое сообщение,

посланное нашему окну может обрабатываться в нашей оконной процедуре. Нам остается только отреагировать на его. И что? Мы должны отвечать соответстветствующим образом на всевозможные сообщения Windows? Там их сотни! К счастью, нет! Мы должны перехватывать только те сообщения, в которых заинтересованы. Все остальные мы возвращаем обратно в Windows для обработки по умолчанию, используя DefWindowProc.

Windows получает различные события от клавиатуры, мыши, портов, и т.д. Каждое событие быстро преобразуется в сообщение. Windows посылает сообщения, соответствующим окнам. Например, все сообщения от клавиатуры идут к окну, которое в настоящее время имеет фокус ввода (активное окно). Сообщения мыши посылаются согласно позиции курсора мыши. Они обычно идут к окну, которое расположено непосредственно под курсором (если какая-нибудь программа не захватила мышь).

Все эти сообщения заканчиваются в очередях сообщений. Windows поддерживает очередь сообщений для каждой выполняющейся прикладной программы (фактически, для каждого потока). Ваша задача состоит в последовательном получении этих сообщений в так называемом цикле сообщений (message loop). Для этого программа должна вызывать GetMessage. Затем вызывается DispatchMessage, чтобы отдать сообщение обратно Windows. Разве сама Windows не может посылать все эти сообщения самостоятельно? В принципе это возможно, но цикл сообщений дает вашей программе возможность посмотреть на них и, если это необходимо, выполнить некоторые дополнительные действия перед возвратом. Или не выполнять…

Давайте рассмотрим WinMain. Выполнение Windows программы не начинается с функции main — оно начинается с WinMain. Сначала, мы создаем winclass и регистрируем его. Затем мы создаем экземпляр окна (на основе только что зарегистрированного класса) и отображаем его. В общем случае WinMain вызывается с соответствующей директивой show. Пользователь может запустить приложение со свернутым или развернутым окном. Так что мы только следуем этой директиве. Затем мы запускаем цикл сообщения, в котором обрабатываем и посылаем сообщения до тех пор, пока GetMessage не возвратит 0. В этот момент параметр wparam сообщения будет содержать код возврата для всей программы.

int WINAPI WinMain(hinstance hinst, hinstance hprevinst, char * cmdParam, int cmdShow) {

 char className [] = "Winnie";

 WinClass winClass(WindowProcedure, className, hInst);

 winClass.Register;

 WinMaker win("Hello Windows!", className, hInst);

 win.Show(cmdShow);

 MSG msg;

 int status;

 while ((status = ::GetMessage(&msg, 0, 0, 0)) != 0) {

if (status == –1) return –1;

::DispatchMessage(&msg);

 }

 return msg.wParam;

}

Функция API GetMessage – интересный пример причудливой troolean (в противоположность традиционной Boolean) логики Microsoft. GetMessage определена таким образом, чтобы возвратить BOOL, но

в документации определяется три варианта возвращаемых значений: ненулевых, нуля и –1. Я это не выдумал! Приведу цитату из справки:

Если функция передает сообщение, иное чем WM_QUIT, возвращаемое значение отлично от нуля.

Если же функция выдает сообщение WM_QUIT, возвращаемое значение — нуль.

При возникновении ошибки возвращаемое значение равно –1.

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

// Window Procedure called by Windows

LRESULT CALLBACK WindowProcedure(HWND hwnd, unsigned int message, WPARAM wParam, LPARAM lParam) {

 switch (message) {

 case WM_DESTROY:

::PostQuitMessage (0);

return 0;

 }

 return ::DefWindowProc(hwnd, message, wparam, lparam);

}

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

Windows и «Модель-Вид-Контроллер»

Обобщенная Windows программа

Перевод А. И. Легалова

Англоязычный оригинал находится на сервере компании Reliable Software

Эта программа использует набор базовых классов, которые инкапсулируют Windows API

• Controller (Контроллер) — Мост между оконной процедурой и объектно-ориентированным миром.

• View (Вид) — Инкапсулирует вывод Windows программы.

• Canvas (Холст) — Инкапсулирует различные контексты устройств и действия, которые Вы можете сделать с их использованием.

• Model (Модель) — Работник и мозг вашей программы. Вообще не имеет дело с Windows.

Обратите внимание: это Win32 программа — она м.б. запущена под Windows 95, 98, NT, 2000, Me.

Обратите внимание: _set_new_handler — это специфика Microsoft. Если вы используете другой компилятор, то скорее удалите эту строку из кода. Согласно текущему стандарту C++, оператор new должен выбрасывать исключения в любом случае (VC++ сейчас тоже поддерживает стандарт. А.Л. ).

Обратите внимание: Старые компиляторы могут иметь проблемы с шаблонами (Вряд ли кто использует такие старые компиляторы для программирования под Windows. А.Л. ). В этом случае вы можете заменить используемые шаблоны типа Win[Get/Set]Long прямыми вызовами Get/SetWindowLong. Например, вместо вызова

Controller * pCtrl = WinGetLong<CONTROLLER *> (hwnd);

вы можете записать

Controller * pCtrl = reinterpret_cast<Controller *> (::GetWindowLong (hwnd, GWL_USERDATA));

Загрузка упакованных исходных текстов Generic (11 кб).

Поделиться:
Популярные книги

Метатель. Книга 7

Тарасов Ник
7. Метатель
Фантастика:
боевая фантастика
попаданцы
постапокалипсис
рпг
фэнтези
фантастика: прочее
5.00
рейтинг книги
Метатель. Книга 7

Вернуть Боярство 3

Мамаев Максим
3. Пепел
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Вернуть Боярство 3

Сумеречный Стрелок 3

Карелин Сергей Витальевич
3. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 3

Студиозус

Шмаков Алексей Семенович
3. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Студиозус

Неправильный лекарь. Том 1

Измайлов Сергей
1. Неправильный лекарь
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Неправильный лекарь. Том 1

Черный дембель. Часть 2

Федин Андрей Анатольевич
2. Черный дембель
Фантастика:
попаданцы
альтернативная история
4.25
рейтинг книги
Черный дембель. Часть 2

Развод с генералом драконов

Солт Елена
Фантастика:
фэнтези
5.00
рейтинг книги
Развод с генералом драконов

Как я строил магическую империю

Зубов Константин
1. Как я строил магическую империю
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Как я строил магическую империю

Око василиска

Кас Маркус
2. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Око василиска

Возвышение Меркурия. Книга 15

Кронос Александр
15. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 15

Кодекс Охотника. Книга XXIII

Винокуров Юрий
23. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXIII

Бастард Императора. Том 4

Орлов Андрей Юрьевич
4. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Бастард Императора. Том 4

Идеальный мир для Лекаря 16

Сапфир Олег
16. Лекарь
Фантастика:
боевая фантастика
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 16

Своя правда

Шебалин Дмитрий Васильевич
2. Чужие интересы
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Своя правда