«Hello Windows!» в классовой обертке
«Hello Windows!» в классовой обертке
Простейшая Windows программа
Перевод А. И. Легалова
Англоязычный оригинал находится на сервере компании Reliable Software
Прежде, чем приступить к программированию для Windows, необходимо понять, как выполняется представленная здесь самая простая программа. Обратите внимание: это — Win32-программа. Она будет выполняться под управлением Windows 95 и Windows NT (если кто-то хочет, чтобы Вы программировали для 16-разрядной платформы, то он должен платить Вам вдвое больше!). Windows API вызовы окрашены в синий цвет, а специфические для Windows типы данных окрашены зеленым. Я буду также ставить два двоеточия перед обращениями к функциям API. В C++ это означает вызов глобальной функции и позволяет, в ряде случаев, избавиться от неоднозначности.
Исходные тексты программы расположены на сервере Reliable software (чужого стараюсь не держать [А.Л.]). Не забудьте откомпилировать его как приложение Windows. Например, в Visual C++ выберите File.New.Projects.Win32 Application. Иначе вы получите ошибку: нерешенный внешний _main. (я обеспечил проектным файлом тех, кто используют MS VC++ 6.0)
Сначала Вы должны определить классы окон, которые будут отображаться вашим приложением. В данном случае мы отобразим только одно окно (WinClass), но тем не менее, мы должны дать Windows некоторую минимальную информацию относительно его класса. Наиболее важная часть WinClass — адрес процедуры обратного вызова, или оконной процедуры (WindowProcedure). Windows, в соответствии с внутренней организацией, вызывает нас — он посылает сообщения нашей программе, вызывая оконную процедуру.
Обратите внимание на объявление оконной процедуры. Windows будет вызывать ее, передавая дескриптор текущего окна и два элемента данных, связанных с сообщением (параметры сообщения): WPARAM и LPARAM.
В WinClass мы также должны определить дескриптор экземпляра программы HINSTANCE, курсор мыши (мы лишь загружаем стандартный курсор – стрелку), кисть, чтобы закрасить фон окна (мы выбрали заданный по умолчанию цвет окна) и имя нашего класса.
После заполнения всех полей структуры WNDCLASS мы регистрируем класс окна в Windows.
#include <windows.h>
LRESULT CALLBACK WindowProcedure(HWND hwnd, unsigned int message, WPARAM wParam, LPARAM lParam);
class WinClass {
public:
WinClass (WNDPROC winProc, char const * className, HINSTANCE hInst);
void Register() {
::RegisterClass (&_class);
}
private:
WNDCLASS _class;
};
WinClass::WinClass(WNDPROC winProc, char const * className, HINSTANCE hInst) {
_class.style = 0;
_class.lpfnWndProc = winProc; // оконная процедура: обязательна
_class.cbClsExtra = 0;
_class.cbWndExtra = 0;
_class.hInstance = hInst; // владелец класса: обязательный
_class.hIcon = 0;
_class.hCursor = ::LoadCursor (0, idc_arrow); // optional
_class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // optional
_class.lpszMenuName = 0;
_class.lpszClassName = className; // обязательно
}
Как только Класс Окна зарегистрирован, мы можем продолжить создание окна. Для этого вызываем функцию API CreateWindow. У нее много параметров: имя только что зарегистрированного класса окна, заголовок, появляющийся в названии окна, стиль, положение на экране и размер, а также дескриптор экземпляра приложения. Остальные параметры в данный момент оставлены обнуленными.
Окно не будет появляться на экране до тех пор, пока Вы не скажете, чтобы Windows показал его.
class WinMaker {
public:
WinMaker(): _hwnd (0) {}
WinMaker (char const* caption, char const* className, HINSTANCE hInstance);
void Show (int cmdShow) {
::ShowWindow(_hwnd, cmdshow);
::UpdateWindow(_hwnd);
}
protected:
HWND _hwnd;
};
WinMaker::WinMaker(char const * caption, char const * className, HINSTANCE hInstance) {
_hwnd = :: CreateWindow(
className, // имя регистрируемого оконного класса
caption, // заголовок окна
WS_OVERLAPPEDWINDOW, // стиль окна
CW_USEDEFAULT, // позиция x
CW_USEDEFAULT, // позиция y
CW_USEDEFAULT, // ширина
CW_USEDEFAULT, // высота
0, // handle to parent window
0, // handle to menu
hInstance, // дескриптор экземпляра
0); // дата создания (window creation data)
}
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 программе.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Запуск сценария с помощью Проводника Windows (Windows Explorer)
Запуск сценария с помощью Проводника Windows (Windows Explorer) Самым простым является запуск сценария в окнах Проводника Windows или на рабочем столе — достаточно просто выполнить двойной щелчок мышью на имени файла со сценарием или на его значке (рис. 1.6). Рис. 1.6. Запуск сценария с
Добавляем Windows Media Center в меню автозапуска в Windows 7
Добавляем Windows Media Center в меню автозапуска в Windows 7 В Windows 7 меню автозапуска не предоставляет возможности воспроизведения мультимедиа в Windows Media Center. Вы не найдете такого пункта и в настройках параметров автозапуска в панели
1.17. Чем отличаются Windows XP Professional и Windows XP Home?
1.17. Чем отличаются Windows XP Professional и Windows XP Home? Обе эти системы имеют очень много общего, и XP Pro и XP Home построены на одном и том же ядре, NT 5.1. Разница между ними заключается только в том, что XP Home не поддерживает несколько функций, работающих в XP Pro. В XP Home не поддерживаются
2.4.2. Установка Windows 9x, Windows NT/2000 и Linux.
2.4.2. Установка Windows 9x, Windows NT/2000 и Linux. Первый способВ этом способе используется загрузчик NT Loader. Выполните установку Windows 2000 в раздел NTFS, a Windows 9x — в раздел FAT/FAT32. Не забудьте приготовить четыре системных дискеты для восстановления! Напомню, что если вы хотите установить Windows
5.6 Служба теневого копирования томов в Windows ХР и Windows Server 2003
5.6 Служба теневого копирования томов в Windows ХР и Windows Server 2003 В Windows ХР и Windows Server 2003 компания Microsoft реализовала службу теневого копирования. Таким образом, предоставляется инфраструктура, позволяющая создавать целостные копии дисковых томов в заранее определенный момент
1.1. Гонки на выживание: Windows ХР, Windows Vista и Windows 7
1.1. Гонки на выживание: Windows ХР, Windows Vista и Windows 7 Время не стоит на месте, и уж тем более на месте не стоят новые технологии. Появление многоядерных процессоров, мощных видеокарт и других новых устройств, которые не могут полностью раскрыть свой потенциал в существующих
Быстрое завершение работы Windows (Windows NT/2000/XP)
Быстрое завершение работы Windows (Windows NT/2000/XP) Windows NT версии 3.1 и 3.5 позволяла закрыть все процессы за 20 секунд. В Windows NT 3.51 и выше существует возможность определять величину интервала, в течение которого система должна завершить свою работу. Для этого необходимо исправить ключ
Что век информационных технологий сотворил с теорией нарастания классовой борьбы Сергей Голубицкий
Что век информационных технологий сотворил с теорией нарастания классовой борьбы Сергей Голубицкий Опубликовано 27 февраля 2014 Манипулирование всегда было главным инструментом регулирования общественной и политической жизни. Во все времена. Но
Ein Volk, ein Plattform, ein Windows!, или Когда уничтожат Windows RT? Евгений Золотов
Ein Volk, ein Plattform, ein Windows!, или Когда уничтожат Windows RT? Евгений Золотов Опубликовано 04 декабря 2013 В лагере MS Windows зреют большие перемены: не все варианты самой популярной ОС чувствуют себя одинаково хорошо. Windows Phone набирает пользовательскую массу
6.5. Общие команды меню Windows-программ. Буфер обмена Windows
6.5. Общие команды меню Windows-программ. Буфер обмена Windows Практически все Windows-программы имеют главное меню, которое расположено сразу под заголовком окна. В большинстве случаев некоторые команды главного меню совпадают. Например, многие Windows-программы имеют меню Файл,
О чем нужно позаботиться перед установкой Windows XP в режиме Windows
О чем нужно позаботиться перед установкой Windows XP в режиме Windows Итак, на вашем жестком диске уже установлена одна из версий операционной системы Windows и вы хотите инсталлировать Windows XP. С чего начать? Прежде всего – вспомнить (выяснить), какая важная информация содержится на
6.9. Шифрование файлов в Windows Vista и Windows 7
6.9. Шифрование файлов в Windows Vista и Windows 7 Если за компьютером работает несколько пользователей, вы можете зашифровать свои файлы, чтобы другие пользователи не смогли их открыть. Возможности шифрования уже встроены в Windows, нужно их только активировать. Для этого перейдите в
5.3.2. Настройка модема в Windows Vista и Windows 7
5.3.2. Настройка модема в Windows Vista и Windows 7 В Windows Vista/7 настройка подключения через модем значительно упрощена. Откройте панель управления и в Центре управления сетями и общим доступом выберите ссылку Установка подключения или сети (в Windows 7 — Настройка нового подключения или
5.4.2. Настройка локальной сети в Windows Vista и Windows 7
5.4.2. Настройка локальной сети в Windows Vista и Windows 7 В Windows Vista и Windows 7 настройки, в целом, схожи с Windows XP, однако при щелчке правой кнопкой мыши на значке Сеть и выборе в меню пункта Свойства, открывается окно Центр управления сетями и общим доступом (рис. 5.22) — его также можно
7.2.2. Настройка почтового ящика в программе Почта Windows (Windows Vista)
7.2.2. Настройка почтового ящика в программе Почта Windows (Windows Vista) В программе Почта Windows почтовый ящик настраивается аналогичным образом. Откройте меню опций Сервис и выберите пункт Учетные записи. В открывшемся окне (рис. 7.9) нажмите кнопку Добавить. В открывшемся окне
7.2.3. Настройка почтового ящика в программе Почта Windows Live (Windows 7)
7.2.3. Настройка почтового ящика в программе Почта Windows Live (Windows 7) Чтобы добавить учетную запись почты Windows Live, щелкните на ссылке Добавить учетную запись в рабочем окне программы (см. рис. 7.3). В открывшемся окне (рис. 7.10) введите адрес электронной почты, пароль и отображаемое