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

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

Жанры

Применение 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 кб).

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

Заставь меня остановиться 2

Юнина Наталья
2. Заставь меня остановиться
Любовные романы:
современные любовные романы
6.29
рейтинг книги
Заставь меня остановиться 2

Усадьба леди Анны

Ром Полина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Усадьба леди Анны

Мимик нового Мира 10

Северный Лис
9. Мимик!
Фантастика:
юмористическое фэнтези
альтернативная история
постапокалипсис
рпг
5.00
рейтинг книги
Мимик нового Мира 10

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

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

Игрок, забравшийся на вершину. Том 8

Михалек Дмитрий Владимирович
8. Игрок, забравшийся на вершину
Фантастика:
фэнтези
рпг
5.00
рейтинг книги
Игрок, забравшийся на вершину. Том 8

Физрук: назад в СССР

Гуров Валерий Александрович
1. Физрук
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Физрук: назад в СССР

Темный Патриарх Светлого Рода 6

Лисицин Евгений
6. Темный Патриарх Светлого Рода
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Темный Патриарх Светлого Рода 6

Энфис 5

Кронос Александр
5. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 5

Хочу тебя навсегда

Джокер Ольга
2. Люби меня
Любовные романы:
современные любовные романы
5.25
рейтинг книги
Хочу тебя навсегда

Я все еще не князь. Книга XV

Дрейк Сириус
15. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я все еще не князь. Книга XV

Волк 5: Лихие 90-е

Киров Никита
5. Волков
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Волк 5: Лихие 90-е

Разбуди меня

Рам Янка
7. Серьёзные мальчики в форме
Любовные романы:
современные любовные романы
остросюжетные любовные романы
5.00
рейтинг книги
Разбуди меня

Ученик

Первухин Андрей Евгеньевич
1. Ученик
Фантастика:
фэнтези
6.20
рейтинг книги
Ученик

Не грози Дубровскому! Том IX

Панарин Антон
9. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том IX