Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
GDI App.docx
Скачиваний:
3
Добавлен:
01.04.2025
Размер:
56 Кб
Скачать
☆
    1. Соглашение об использовании имен

Во многих текстах программ вы можете встретить, на первый взгляд, странные имена переменных. Дело в том, что эти имена переменных записаны с соблюдением так называемой венгерской нотации (введенной сотрудником Microsoft венгерского происхождения Ч.Шимони). При использовании этой нотации имена переменных предваряются префиксом, идентифицирующим их тип. Используемые префиксы типов приведены в табл. 2.2. |

Таблица 2.2.

Префиксы типов данных, используемые в венгерской нотации

Префикс

Тип данных

b

ВООL (иногда BYTE)

by

ВУТЕ

c

char

cb

int (счетчик байтов)

c

класс

w

WORD

dw

DWORD

n

short int (или int)

i

int

f

флажок

p

указатель

lp

дальний указатель

sz

указатель на строку заканчивающуюся нулем

lpsz

дальний указатель на строку, заканчивающую­ся нулем

fn

Функция

lpfn

дальний указатель на функцию

pt

Координаты точки, хранимые в виде длинного целого

rgb

Значение цвета, хранимое в виде длинного целого

H

дескриптор

Использовать эти префиксы в программах или нет - дело про­граммиста, но при чтении описаний функций Windows API вы их обязательно встретите, так как сама Microsoft их придерживается.

    1. Структура приложения Windows

Простейшее GUI-приложение Windows, написанное на уров­не Windows API, состоит из двух частей: функции WinMain(), которая является главной функцией, с которой начинается вы­полнение приложения, и оконной процедуры (или оконной функции), которая обрабатывает все сообщения, направляемые окну (которое в случае простейшего приложения является един­ственным).

Функция WinMain() обычно выполняет следующие задачи:

  • определяет класс окна;

  • регистрирует класс окна;

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

  • отображает это окно;

  • запускает цикл обработки сообщений. Она имеет следующий прототип:

int WINAPI WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

Параметры имеют такой смысл:

hInstance -. дескриптор текущего экземпляра приложения;

hPrevInstance - дескриптор предыдущего экземпляра приложения (запущенного на выполнение ранее); lpCmdLine -указатель на командную строку; nCmdShow - задает как окно должно быть отображено. Этот параметр может принимать одно из приведенных ниже значений:

SW_HIDE- скрывает это окно и актин

SW_MINIMIZE - минимизирует данное окно и активизи­рует окно верхнего уровня в системном списке;

SW_RESTORE - активизирует и отображает окно. Если ок­но минимизировано или максимизировано, система восстанавли­вает исходное состояние и позицию окна на экране (это значение эквивалентно значению SW_SHOWNORMAL);

SW_SHOW - активизирует окно и отображает его в текущем положении и размере;

SW_SHOWMAXIMIZED- активизирует окно и отображает его как максимальное окно;

SW_SHOWMINIMIZED - активизирует окно и отображает его в виде иконки;

SW_SHOWMINNOACTIVE - отображает окно в виде иконки. Активное окно остается активным;

SW_SHOWNA- отображает окно в его текущем состоянии. Активное окно остается активным;

SW_SHOWNOACTIVATE - отображает окно в его последних размерах и положении. Активное окно остается активным;

SW_SHOWNORMAL- активизирует и отображает окно. Если окно минимизировало или максимизировано, система восстанав­ливает его в исходных разме рах и позиции (эквивалентно значе­нию SW_RESTORE).

Если функция завершилась успешно, она должна возвращать значение, которое имел параметр wParam последнего принятого сообщения (это – сообщение WM_QUIT). Если функция заверша­ется до входа в цикл обработки сообщений, она должна возвра­щать ноль.

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

LRESULT CALLBACK wINDOWfUNC(HWND hWnd, UINT I Msg, WPARAM

wParam LPARAM lParam);

Ее параметры имеют следующий смысл: hWnd- дескриптор окна, которому направлено сообщение; iMsg- номер сообщения;

wParam- параметр сообщения;

lParam - параметр сооб­щения. Таким образом, с каждым сообщением функции передаются два параметра.

Мы не будем здесь вдаваться в подробности написания GUI-приложений на уровне Win32 API. Это довольно обширная тема, которая может увести нас в сторону от основной темы этой книги. Заинтересованный читатель может обратиться к ставшей классической книге Ч.Петзолда «Программирование для Windows 95», BHV – Санкт-Петербург, 1997. Вместо этого мы рассмотрим здесь пример простейшего GUI-приложения

#include <windows.h>

LRESULT CALLBACK

WindowFunc (HWND, UINT, WPARAM, LPARAM);

char *szWinName = "Простое okho";

int WINAPI WinMain(HINSTANCE hlnstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

HWND hWnd;

MSG msg;

WNDCLASS wcl;

//Заполняем структуру WNDCLASS

wcl.hlnstance = hlnstance;

wcl.lpszClassName = szWinName;

wcl.IpfnWndProc = WindowFunc;

wcl.style » 0;

wcl.hlcon = 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,

"Win32 API приложение",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFADLt,

HWND_DESKTOP, NULL,

hlnstance, NULL);

//отобразить окно и перерисовать его содержимое

ShowWindow(hWnd, nCmdShow) ;

UpdateWindow (hWnd) ;

//создать цикл обработки сообщений

while (GetMessage(&msg, NULL, 0,0))

{

//Разрешить обработку нажатий клавиш

TranslateMessage(&msg);

//Отправить сообщение нужному окну

DispatchMessage(&msg) ;

}

return msg.wParam; >

//Оконная функция

}

LRESULT CALLBACK WindowFunc(HWND hWnd, UINT iMsg,

WPARAM wParam, LP ARAM lParam)

{

switch (iMsg)

{

case WMJDESTROY: //Завершение работы программы

PostQuitMessage(0); break;

default: //Обработка всех остальных сообщений

return DeЈWindowProc(hWnd, iMsg, wParam, lParam);

}

return 0;

}

Прежде всего отметим, что все программы для Windows должны включать в себя файл <windows.h>. Этот файл содержит прототипы всех функций API, а также объявление типов данных, структур и макросов. Некоторые из объявленных в нем типов данных приведены в табл. 2.1. Упоминаемая в тексте при­мера структура WNDCLASS также объявлена в этом файле. Вы­полнение программы начинается с функции WinMain(), кото­рой передается четыре параметра. Назначение этих параметров описано выше. Заметим здесь, что параметр hPrevInstance в Windows 95 и Windows NTвсегда равен NULL (В Windows 3.1 он мог принимать отличные от нуля значения, если ранее был запу­щен другой экземпляр данного приложения. Этот параметр со­хранен только с целью совместимости). В рассматриваемом при­мере создается одно окно. С этой целью в функции WinMain() определяется и регистрируется класс окна. Имя класса окна опре­деляется значением поля lpszClassName структуры WNDCLASS. В данном случае - это szWinName. Термин "класс окна" не следует путать с понятием "класс" языка С++. Класс окна характреризуется структурой WNDCLASS и не имеет ничего общего с объектно-ориентированным программированием. Ввиду особой важности этой структуры в программировании для Windows приведем здесь ее объявление:

Typedef struct_WNDCLASS

{

UINT style;

WNDPROC lpfnWndProc;

Int cbClsExtra;

Int cbWndExtra;

HANDLE hinstance;

HICON hIcon;

HCURSOR hCursor;

HBRUSH hbrBackground;

LPCTSTR lpszMenuName;

LPCSTR lpszClassName;

} WNDCLASS;

Поля структуры имеют следующее назначение:

style - задает стиль (или стили) класса. Стили можно комбинировать с помощью побитовой операции "ИЛИ";

lpfnWndProc - указатель на оконную функцию, т.е.на функцию, которая будет обрабатывать сообщения, направляемые окну создаваемого класса;

cbClsExtra- задает число дополнительных байтов для класса, которые нужно распределить вслед за данной структурой.

Операционная система инициализирует эти байты значением 0;

cbWndExtra - задает число дополнительных байтов, кото­рые дополнительно резервируются вслед за структурой окна и инициализируются операционной системой значением 0;

hInstance - дескриптор данного экземпляра приложения;

hIcon - дескриптор иконки, которая отображается при-ми­нимизации окна данного класса;

hCursor - дескриптор курсора для окна данного класса;

hbrBackground - дескриптор кисти или значение цвета для закрашивания фона окна;

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

lpszClassName - указатель на заканчивающуюся нулем строку, которая задает имя класса окна.

В нашем примере многие поля этой структуры проинициализированы значением 0. В качестве иконки окна задана стан­дартная иконка приложения Windows. Курсор окна имеет вид стрелки, а фон - закрашивается кистью белого цвета. Поле lpfnWndProc содержит указатель на функцию окна с именем WindowProc. Фактическую регистрацию класса окна в опе­рационной системе выполняет функция RegisterClass(), которая возвращает ненулевое значение в случае успеха. По­сле регистрации окна его можно создать. Эту задачу выполняет вызов функции CreateWindow(). Эта функция имеет сле­дующий прототип:

HWND CreateWindow(LPCSTR lpClassName,

LPCSTR lpWindowName

DWORD dwStyle,

Int x,

Int y,

Int nWidth,

Int nHeight,

HWND hWndParent,

HMENU hMenu,

HANDLE hInstance,

LPVOID lpParam);

Назначение параметров:

lpClassName - указатель на заканчивающуюся нулем стро­ку, задающую имя класса окна;

lpWindowName - указатель на заканчивающуюся нулем строку, задающую имя окна, появляющееся в его заголовке;

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

х - задает начальную позицию окна по горизонтали. Если этот параметр равен CW_USEDEFAULT, операционная система сама выбирает позицию по умолчанию и игнорирует значение параметра у;

y - задает начальную позицию окна по вертикали.

nWidth - задает ширину окна. Если этот параметр равен CW_USEDEFAULT, операционная система сама выбирает ширину окна по умолчанию. В этом случае значение параметра nHeight игнорируется;

nHeight - задает высоту окна;

hWndParent - задает дескриптор родительского окна или окна-владельца для создаваемого окна. Если этот параметр равен HWND_DESKTOP, создаваемое окно не имеет родительского;

hMenu - дескриптор меню или дочернего окна в зависимости от стиля окна. Если он равен ДОЬЬ, должно использоваться ме­ню, заданное для всех окон данного класса;

hInstance - дескриптор приложения;

lpParam - указатель на структуру CREATESTRUCT; для кли­ентских окон многодокументного интерфейса этот параметр должен указывать на структуру CLIENTCREATESTRUCT.

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

В рассматриваемом примере создается окно класса szWinName с заголовком, содержащим строку "Заголовок окна". Координаты и размер окна определяются операцион­ной системой. После создания окна оно, как правило, еще не отображается на экране. Для того, чтобы отобразить окно, сле­дует вызвать функцию ShowWindow():

BOOL ShowWindow(HWND hWnd, int nCmdShow);

Параметр hWnd задает дескриптор окна, которое должно быть отображено, а параметр nCmdShow- способ отображения окна; он передается из функции WinMain(). Функция возвращает ненуле­вое значение, если до ее вызова окно отображалось на экране, иначе - ноль. Хотя это и не всегда нужно, тем не менее, мы включи­ли в рассматриваемый пример вызов функции UpdateWindow(). Эта функция вызывает немедленную перерисовку окна.

Последней частью функции WinMain() является цикл обработки сообщений. Он реализован следующими строками про­граммы:

//Создать цикл обработки сообщений

While(GetMessage(&msg, Null, 0, 0))

{

//Разрешить обработку нажатий клавиш

TranslateMessage(&msg);

//Отправить сообщение нужному окну

DispatchMessage(&msg)

}

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

BOOL

GetMessage(LPMSG msg, HWND hWnd, UINT min, UINT max);

Передаваемые этой функций сообщения сохраняются в пере­менной msg. Параметр hWnd задает дескриптор окна, которому направляются выбираемые сообщения. Если этот параметр равен NULL, функция выбирает из очереди все сообщения, адресован­ные приложению. Следующие два параметра определяют диапа­зон номеров получаемых сообщений. В примере эти параметры равны нулю. Это означает, что выбираются все сообщения. Если функция GetMessage() возвращает ноль, обработка сообще­ний прекращается. Это происходит при выходе из приложения. Внутри цикла сообщений вызываются две функции: функция DispatchMessage() направляет очередное сообщение окон­ной функции приложения, а функция TranslateMessage() транслирует виртуальные коды клавиш в клавиатурные сообще­ния. Вызов этой функции в цикле обработки сообщений не обяза­телен. Он нужен только в том случае, если в программе преду­сматривается ввод с клавиатуры. Как мы увидим впоследствии, для, ввода символьной информации Windows предоставляет спе­циальные элементы интерфейса.

Рассмотрим теперь оконную функцию из этого примера. В нашем примере эта функция имеет имя WindowFunc(). В каче­стве параметров функции передаются первые четыре поля струк­туры MSG, которая хранит всю информацию о сообщении в сис­теме. Эту структуру мы рассмотрим в следующем разделе, а здесь отметим, что наша оконная функция самостоятельно обра­батывает только одно сообщение –WM_DESTROY. Это сообщение посылается, когда нужно завершить работу программы. В ответ на это сообщение вызывается функция PostQuitMessage(). Параметр, передаваемый этой функции, определяет код возврата приложения.

Функция PostQuitMessage(), в свою очередь, посылает сообщение WM_QUIT в очередь сообщений приложе­ния. Это сообщение будет выбрано из очереди в цикле обработки сообщений. При поступлении сообщения WM_QUIT функция GetMessage() возвратит ноль и произойдет выход из цикла обработки сообщений и завершение работы программы. Все дру­гие сообщения в оконной функции обрабатываются стандартным образом путем передачи их функции обработки сообщений по умолчанию DefWindowProc(). Если оконная функция возвра­щает нулевое значение, это означает, что обработка сообщения завершена в ней самой, в противном случае возвращаемое значе­ние зависит от обрабатываемого сообщения и определяется функцией DefWindowProc().

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]