Главная » Win32 API » Структура главной функции в минимальном приложении

0

Минимальное приложение Windows состоит из 2 частей:

1.                главной функции с именем WinMain, включающей цикл обра­ботки сообщений;

2.                оконной функции WndProc.

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

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

Рассмотрим структуру главной функции более подробно. На С ми­нимальная главная функция с одним окном имеет вид:

int    WINAPI    WinMain(HINSTANCE    hlnst,     HINSTANCE,     LPSTR, int)

{   char  szClassName[]="Class32";

// Произвольное имя класса главного окна char szTitleName[]="Пример приложения";

// Произвольный  заголовок окна

MSG mess; // Структура для получения сообщений

WNDCLASS wc; //Структура для задания характеристик //окна // Регистрация класса главного окна

memset(&wc,0,sizeof(wc) ); // Обнуление и формирование необходимых элементов // структуры wc

wc.lpfnWndProc=WndProc; // указатель на оконную

//функцию wc.hlnstance=hlnst; // Дескриптор приложения wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);

//вызов функции загрузки стандартной пиктограммы

wc.hCursor=LoadCursor(NULL,IDC_ARROW); // вызов функции загрузки курсора мыши -// однонаправленной стрелки

wc. hbrBackground=GetStockBrush (LTGRAY_BRUSH) ; // запрос для закрашивания фона окна // светло-серой кистью из ресурсов Windows

wc.lpszClassName=szClassName; // имя класса окна

RegisterClass(&wc); // Вызов функции регистрации //класса окна // Создадим главное окно

HWND hwnd=CreateWindow(szClassName,szTitleName, // Класс и заголовок окна

WS_OVERLAPPEDWINDOW,20,20,300,200, // Стиль, х и у координаты левого верхнего угла, // ширина и высота окна HWND_DESKTOP,NULL,hlnst,NULL);

// Дескриптор родительского окна, ссылка на меню, // Дескриптор экземпляра приложения,  адрес дополни­тельных данных

// Покажем окно на экране

ShowWindow(hwnd,SW_SHOWNORMAL); // Организуем цикл обработки сообщений

while(GetMessage(&mess,NULL,0,0)) // получить сообщение

DispatchMessage(&mess) ; //и передать оконной функции для обработки

return 0; // после выхода из цикла вернуться в Windows }

При запуске приложения управление передается программам ОС, которые загружают код приложения в память и вызывают главную функцию, которая должна иметь имя WinMain и дескриптор WINAPI. При вызове WinMain ОС передает ей 4 параметра. Первый параметр типа HINSTANCE должен быть дескриптором данного экземпляра приложения, необходимым для его идентификации. Этот дескриптор используется различными API-функциями, поэтому он должен хра­ниться в глобальной переменной. В минимальном приложении таких функций нет, поэтому hlnst не сохраняется нигде. Второй параметр для 16-разрядных приложений представляет собой дескриптор преды­дущего экземпляра приложения, а для 32-разрядных приложений не

имеет смысла и принимает нулевое значение. Третий параметр являет­ся указателем на строку, содержащую параметры командной строки при запуске приложения. Четвертый параметр WinMain служит для определения режима запуска приложения. Так, приложение можно сразу после запуска свертывать в пиктограмму, что осуществляется при равенстве 4 параметра 7. Если 4 параметр равен 1, то окно прило­жения принимает размеры, указанные при создании дескриптора окна. Этот 4 параметр обычно передается вторым параметром функции по­каза окна ShowWindow. В нашем примере мы сразу передали функции ShowWindow нужную константу SWSHOWNORMAL, равную 1.

В приложении главная функция должна сначала зарегистрировать в ОС класс главного окна. Если кроме одного главного окна планируется вывод на экран дочерних окон, то их классы также необходимо зареги­стрировать. ОС выводит на экран и обслуживает только окна заре­гистрированных классов! Класс окна задает характеристики, общие для всех подобных окон. Действия программиста по регистрации клас­са заключаются в заполнении структуры типа WNDCLASS, в которой хранятся характеристики класса окна. Данные из этой структуры необ­ходимы функции RegisterClass, которая и выполняет собственно реги­страцию. Рассмотрим структуру WNDCLASS.

{

UINT style; // стиль класса окна

WNDPROC lpfnWndProc;

// указатель на имя оконной функции int cbClsExtra;

// количество байтов дополнительной информации // о классе int cbWndExtra;

// количество байтов дополнительной информации // об окне

HINSTANCE hlnstance; // дескриптор приложения HICON hicon; // дескриптор пиктограммы приложения HCURSOR hCursor; // дескриптор курсора приложения HBRUSH hbrBackground; // дескриптор кисти для фона ок­на

LPCSTR IpszMenuName;

// указатель на строку с именем меню окна

LPCSTR lpszClassName;

// указатель на строку с именем класса окна

} WNDCLASS;

Не все поля структуры необходимо заполнять, поэтому структура сначала обнуляется, а затем заполняются только нужные поля. Нулевое значение элемента структуры, описывающей объект Windows (на­пример, структуры типа WNDCLASS), означает, что реальное значе­ние элемента будет установлено по умолчанию. Через структуру WNDCLASS ОС определяет адрес оконной функции, которая вызыва­ется для обработки сообщений.

Стиль класса окна представляет собой целое 32-битовое число, каждый бит которого разрешает или запрещает возможность опреде­ленных действий с окном. Так, 0 и 1 биты разрешают/запрещают пере­рисовку окна при изменении его размеров, бит 3 отвечает за реакцию приложения на двойные щелчки мышью в области окна, бит 9 запре­щает закрытие окна пользователем. За каждый бит или их комбинацию отвечает предопределенная константа, имя которой может быть ис­пользовано для формирования стиля класса окна с операцией побито­вого ИЛИ. Примерами констант, определяющих стиль класса окна, яв­ляются CSHREDRAW (перерисовка окна при изменении его шири­ны), CSVREDRAW (перерисовка окна при изменении высоты), CSNOCLOSE (запрещение команды закрытия окна в системном ме­ню). В нашем минимальном приложении создание своего стиля окна не требуется.

Курсор и пиктограмма являются ресурсами Windows. Ресурсы обычно загружаются из файла ресурсов с помощью специальных функций загрузки ресурсов, например, для загрузки курсора использу­ется LoadCursor. В качестве первого аргумента функции загрузки ре­сурсов указывается дескриптор приложения, в котором хранится тре­буемый ресурс, а в качестве второго имя ресурса. При этом необяза­тельно пользоваться ресурсами приложений, можно использовать ре­сурсы Windows. Для этого первым параметром функции LoadCursor указывается NULL, что означает саму Windows, а второй параметр вы­бирается из списка встроенных ресурсов. Так, для курсора-однонаправленной стрелки имя ресурса IDCARROW, для курсора вертикальной двунаправленной стрелки IDCSIZENC. С помощью функции Load Icon загружается пиктограмма приложения, также вы­бираемая из стандартных ресурсов Windows. Для формирования кисти, определяющей закраску фона окна, используется одна из предопреде­ленных кистей Windows. Можно установить свою кисть, использовав вызов вида:

wc.hbrBackground=CreateSolidBrush(RGB(100,70,150));

где аргументом CreateSolidBrush является цвет кисти, упаковы­ваемый в 4 байта с помощью макроса RGB, аргументами которой слу­жат интенсивности трех составляющих цвета.

После регистрации класса окна необходимо создать главное окно и показать его на экране. Порожденные окна тоже необходимо перед по­казом создать, причем необязательно в WinMain. Создание окна осу­ществляется с помощью функции CreateWindow, имеющей следую­щие параметры:

-  адрес строки с именем регистрируемого класса. Отметим, что имя класса может быть предопределенным для окон, реализующих элемен­ты управления. Класс BUTTON служит для формирования кнопок, групп, флажков и переключателей, класс LISTBOX служит формиро­вания списка строк, класс EDIT для формирования поля редактиро­вания при вводе текста, класс STATIC для размещения в окне текста, класс SCROLLBAR для формирования полосы прокрутки;

-  адрес строки с заголовком окна;

-  стиль окна, определяющий вид окна при показе, например, вид рамки, наличие заголовка, кнопок, рамки и т.п. Стиль это 32-битное число, биты которого несут смысловую нагрузку по определению кон­кретных свойств окна при отображении. Для того чтобы указать для окна набор свойств, используют побитовое ИЛИ для констант, опреде­ляющих то или иное свойство. Обычно главное окно описывается с помощью константы WSOVERLAPPEDWINDOW (OxOOCFOOOOh), ко­торая одновременно указывает на возможность перекрытия окна, на­личие строки заголовка, системного меню, рамки, кнопки свертывания и кнопки развертывания окна, что обеспечивается операцией побито­вого ИЛИ между константами WSOVERLAPPED, WSCAPTION, WS_SYSMENU,     WS_THICKFRAME,       WS_MINIMIZEBOX, WS_MAXIMIZEBOX;

-  x и у координаты левого верхнего угла окна относительно начала экрана;

-  размеры окна в пикселах по горизонтали и вертикали;

-  дескриптор родительского окна. Для главного окна будем считать, что его родителем является рабочий стол, имеющий дескриптор HWNDDESKTOP;

-  дескриптор меню окна. Если его нет или используется меню клас­са, указывается NULL;

-   Дескриптор приложения, полученный через первый аргумент
функции WinMain;

- адрес дополнительных данных, необходимых для создания окна.
Если создание окна прошло успешно, то функция CreateWindow

возвращает дескриптор созданного окна, который передается в функ­цию ShowWindow, выводящую окна на экран.

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

В простейшем случае цикл обработки сообщений состоит из вызова функции GetMessage, и, если она возвращает ненулевое значение, вы­зывается функция DispatchMessage. Если в очереди потока появляется сообщение, то функция GetMessage забирает его из очереди и перено­сит в структуру mess.

В качестве параметров функции GetMessage указываются:

-  адрес структуры mess, в которую поступает взятое из очереди со­общение,

-  дескриптор окна, чьи сообщения будут обработаны GetMessage. Если NULL, то функция работает со всеми сообщениями данного при­ложения;

-  два последних параметра определяют числовой диапазон сообще­ний, которые анализируются GetMessage. Для исключения фильтра­ции сообщений оба параметра должны быть равны нулю.

Особая ситуация возникает, когда GetMessage обнаруживает в оче­реди сообщение WMQUIT с кодом 0x12. В этом случае функция за­вершается с возвратом 0, что завершает цикл обработки сообщений.

Функция DispatchMessage вызывает оконную функцию окна того класса, которому предназначено сообщение и передает ей содержимое сообщения через структуру mess. После обработки сообщения окон­ной функцией управление возвращается в цикл обработки сообщений (рисунок 1.2).

WinMain

цикл обработки

GetMe:


очередь потока

сообщения

Рисунок 1.2 -Логика обработки сообщений в приложении

Источник: Сучкова, Л.И. Win32 API: основы программирования: учебное пособие/ Л.И. Сучкова; АлтГТУ им. ИИ. Ползунова. -Барнаул, АлтГТУ, 2010. 138 с, ил.

По теме:

  • Комментарии