Теперь; когда мы обсудили все необходимые основные понятия, можно начать разработку простейшего приложения Windows. Как уже отмечалось, все Windows-программы имеют определенные общие черты. Таким образом, в этом разделе мы разрабатываем программу, которая может быть каркасом или шаблоном для любого другого приложения. Технология написания программ для Windows предполагает широкое использование таких каркасов, поскольку, в отличие от DOS, простейшая программа для которой занимает около 5 строк, простейшая программа для Windows содержит примерно 50 строк.
Простейшая программа для Windows состоит из двух функций – WinMain() и оконной функции. Функция WinMain() обычно должна выполнять следующие действия:
1. Определение класса окна.
2. Регистрация класса окна.
3. Создание окна данного класса.
4. Отображение окна.
5. Запуск цикла обработки сообщений.
Оконная функция должна обрабатывать все сообщения, относящиеся к данному окну. Поскольку наша каркасная программа не выполняет никаких действий, кроме отображения пустого окна, единственное сообщение, обрабатываемое ею, указывает на то, что пользователь завершил работу с программой. Остальные сообщения направляются на обработку по умолчанию.
Пример 2-1. Итак, рассмотрим простейшую программу для Windows. Она создает стандартное окно, которое имеет заголовок, системное меню и кнопки минимизации, полноэкранной развертки и закрытия окна. Это окно можно перемещать по экрану и изменять его размер.
// Каркасное приложение Windows
#include <Windows.h>
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM,
LPARAM);
char szWinName[]="МоеОкно"; // Имя класса окна
int WINAPI WinMain(HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWinMode)
{
HWND hwnd;
MSG msg;
WNDCLASS wcl; // Определить класс окна
wcl.hInstance=hThisInst; // Дескриптор приложения
wcl.lpszClassName=szWinName;// Имя класса окна
wcl.lpfnWndProc=WindowFunc; // Функция окна
wcl.style=0; // Стиль по умолчанию
wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION);// Иконка
wcl.hCursor=LoadCursor(NULL,IDC_ARROW); // Курсор
wcl.lpszMenuName=NULL; // Без меню
wcl.cbClsExtra=0; // Без дополнительной информации
wcl.cbWndExtra=0;
wcl.hbrBackground=
(HBRUSH)GetStockObject(WHITE_BRUSH); //Белый фон
if(!RegisterClass(&wcl)) // Регистрируем класс окна
return 0;
hwnd=CreateWindow(szWinName, // Создать окно
"Каркас программы для Windows",
WS_OVERLAPPEDWINDOW, // Стиль окна
CW_USEDEFAULT, // x-координата
CW_USEDEFAULT, // y-координата
CW_USEDEFAULT, // Ширина
CW_USEDEFAULT, // Высота
HWND_DESKTOP, // Нет родител. окна
NULL, // Нет меню
hThisInst,// Дескриптор приложения
NULL); // Нет дополнит. аргументов
ShowWindow (hwnd, nWinMode); // Показать окно
UpdateWindow (hwnd); // и перерисовать
while(GetMessage(&msg,NULL,0,0)) // Запустить цикл
{ // обработки сообщений
TranslateMessage(&msg); // Разреш. исп. клавиатуры
DispatchMessage (&msg); // Вернуть управл. Windows
}
return msg.wParam;
}
// Следующая функция вызывается операционной
// системой Windows и получает в качестве
// параметров сообщения из очереди сообщений
// данного приложения
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch(message)
{
case WM_DESTROY: // Завершение программы
PostQuitMessage (0);
break;
default:
// Все сообщения, не обрабатываемые в
// данной функции, направляются на обработку
// по умолчанию
return DefWindowProc(hwnd,message,
wParam,lParam);
}
return 0;
}
Теперь подробно, шаг за шагом, рассмотрим эту программу. Прежде всего, все программы для Windows должны включать в себя файл описаний Windows.h. Как уже говорилось, этот файл содержит прототипы функций API, а также определения типов данных и макроопределения, используемые в профаммах для Windows. Например, типы данных HWND и WNDCLASS определены в Windows.h.
Оконная функция, используемая программой, названа WindowsFunc(). Она вызывается операционной системой для взаимодействия с программой.
Выполнение программы начинается с WinMain(), которой передается четыре параметра.
Параметры hThisInst и hPrevInst являются дескрипторами:
hThisInst – это дескриптор текущего экземпляра приложения (поскольку Windows – многозадачная система, в ней может одновременно работать несколько экземпляров одной и той же программы);
hPrevInst – этот дескриптор всегда будет равен NULL.
Параметр lpszArgs является указателем на строку, содержащую аргументы программы при ее запуске. Параметр nWinModeопределяет способ визуализации окна при запуске программы.
В функции WinMain()определяются три переменные. Переменная hwnd будет содержать дескриптор главного окна программы. Структура msg станет буфером для хранения сообщений, а структура wclбудет использоваться для определения класса окна.
Определение класса окна
В первую очередь в WinMain() определяется и регистрируется класс окна. Класс окна определяется путем заполнения полей структуры WNDCLASS. Вот эти поля:
UINT style; // Тип окна
WNDPROC lpfnWndProc; // Адрес оконной функции
int cbClsExtra; // Дополнительные данные для класса
int cbWndExtra; // Дополнительные данные для окна
HINSTANCE hInstance; // Дескриптор данного экз. приложения
HICON hIcon; // Дескриптор иконки для данного окна
HCURSOR hCursor; // Дескриптор курсора для данного окна
HBRUSH hbrBackground;// Цвет заполнения окна
LPCSTR lpszMenuName; // Имя главного меню
LPCSTR lpszClassName; // Имя класса окна
Как видно из программы, поле hInstance принимает значение параметра hThisInst,имя класса окна lpszClassNameполучает адрес строки "МоеОкно", а адрес оконной функции присваивается переменной lpfnWndProc. Тип окна по умолчанию равен 0, и дополнительные данные для класса и окна не требуются.
Все Windows-приложения должны задавать форму курсора мыши и иконку для определяемого класса окна. Для этих целей приложение может использовать как собственные ресурсы, так и встроенные ресурсы Windows, как это делает наша программа. Иконка определяется при помощи функции API LoadIcon(), прототип которой приведен ниже:
HICON LoadIcon (HINSTANCE hInst, LPCSTR lpszName).
Эта функция возвращает дескриптор иконки. Параметр hInst специфицирует дескриптор данного экземпляра приложения, содержащего иконку, а имя иконки задается параметром lpszName. Для того чтобы использовать встроенные типы иконок Windows, первый параметр должен быть равен NULL, а в качестве второго параметра должен использоваться один из макросов таблицы 2.1.
Таблица 2.1