Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Технологии программирования. Программирование графических интерфейс

.pdf
Скачиваний:
3
Добавлен:
15.11.2022
Размер:
2.24 Mб
Скачать

Рассмотрим прототип функции более подробно.

Слово CALLBACKв объявлении функции говорит компилятору о необходимости генерации специального кода для входа и выхода из функции обратного вызова. Если этого слова не будет, то функция обратного вызова не будет вызвана правильно.

Тип значения, возвращаемый функции класса окна LRESULT, определен как 32-битное значащее целое, но в зависимости от сообщения в uMsg его, возможно, потребуется преобразовать к указателю на некоторое значение или к другому целому типу, смотрите описание соответствующего сообщения в документации. Это значение определяет результат обработки сообщения, поэтому оно всегда должно передаваться OC при завершении работы функции.

Рассмотрим параметры функции.

HWND hwnd – handle (хэндл) объекта окна, для которого предназначено сообщение, если создано несколько объектов данного оконного класса, то по этому handle функции обработчик выбирает нужный; для главного окна приложения, которое существует в одном экземпляре, его можно проигнорировать.

UINT uMsg – код сообщения, беззнаковое целое.

WPARAMwParamи LPARAM lParam – 32-битные целые,

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

Всего в Windows есть более 900 сообщений, которые может получить любая функция класса окна, и все они должны быть обработаны. Однако вряд ли приложению понадобится обрабатывать их все; те сообщения, обрабатывать которые внутри функции класса окна нет необходимости, могут быть переданы OС для их обработки по умолчанию.

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

ваемую DefWindowProc.

21

LRESULT DefWindowProc(

 

HWND hWnd,

handle (хэндл) окна

UINT Msg,

сообщение

WPARAM wParam, первыйпараметрсообщения

LPARAM lParam

второй параметр сообщения

);

Эта функция принимает и обрабатывает по умолчанию любое сообщение, обрабатывать которое ваша функция класса окна не будет; сами действия по умолчанию практически не зависят от класса окна и в любом приложении для любого класса окна, все сообщения, переданные этой функции, будут обрабатываться одинаково. Если вы использовали эту функцию, то необходимо при выходе из функции вернуть OС значение, полученное от нее.

Теперь можем написать простейшую функцию обработки сообщений.

LRESULT CALLBACK WndProc(

HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

return DefWindowProc(hwnd,message,wParam,lParam)

}

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

22

1.8. Создание главного окна приложения

После регистрации класса окна приложение должно создать вначале главное окно приложения, затем, возможно, и еще несколько окон, связанных с главным окном.

Создание любого объекта оконного типа выполняется функцией CreateWindow.

HWND CreateWindow(

LPCTSTR lpClassName, указатель на строку с именем классаокна

LPCTSTR lpWindowName, указатель на строку с заголовком

окна

стильокна

DWORD dwStyle,

int x,

x – координаталевоговерхнегоуглаокна

int y,

y – координаталевоговерхнегоуглаокна

int nWidth,

ширинаокна

int nHeight,

высотаокна

HWND hWndParent, handle родительскогоокна

HMENU hMenu,

handle меню

HANDLE hInstance, handle того программного модуля, кото-

рыйсоздаетокно

указательнадополнительные параметры

LPVOID lpParam

);

Рассмотрим параметры окна более подробно. lpClassName – указатель на имя класса окна, объект

которого необходимо создать, он должен быть зарегистрирован к моменту вызова этой функции.

lpWindowName – указатель на заголовок данного окна, если заголовок данного окна не нужет, то пусть этот параметр будет NULL.

x,y, nWidth, nHeight – координаты окна и его размеры. Для главного окна приложения и всплывающих окон ко-

ординаты начала окна отсчитываются от левого верхнего угла экрана, а для дочерних окон – от левого верхнего угла родительского окна.

23

hWndParent – handle родительского окна, для главного окна приложения, созданного со стилем WS_OVERLAPPED, должен быть равен NULL, для дочернего окна – handle какогонибудь из окон, уже созданных данным приложением, для всплывающих окон – это или NULL, или handle одного из уже определенных окон.

hMenu – handle объекта класса «оконное меню» или числовой идентификатор окна, который вы задали для дочернего окна. Если ваше главное окно не имеет меню, то укажите этот параметр как NULL .

dwStyle cтили для объекта, созданного для данного класса окна. Младшее слово в данном параметре специфицирует те необходимые свойства в поведении создаваемого объекта для окон данного класса, которые нужно знать операционной системе, а старшее слово в этом двойном слове специфицирует те свойства в поведении оконного объекта, которые необходимо знать функции обработчику сообщений для окон заданного класса. Для главного окна приложения старшее слово обычно не используется, поэтому рассмотрим те стили окна, которые есть в младшем слове.

WS_OVERLAPPED – создает перекрывающееся окно, имеющее рамку и заголовок, любое главное окно приложения должно иметь этот стиль.

WS_POPUP – создает всплывающее окно, то есть способное появляться в любой части экрана при нажатии правой кнопки меню.

WS_CHILD – создает дочернее окно, это окно имеет следующие особенности:

1)при задании своего положения использует координаты, отсчитываемые от левого верхнего угла клиентской части окна родителя (то есть той части прямоугольника, занимаемого окном, которая не занята заголовком и рамкой);

2)если изменяется положение родительского окна, то дочерние окна также перемещаются вместе с ним, при этом их

24

координаты относительно клиентской части главного окна сохраняются;

3) при уничтожении родительского окна все дочерние окна уничтожаются вместе с ним.

WS_CAPTION – создает окно, которое имеет заголовок, любое перекрывающееся окно создается с таким стилем автоматически.

WS_BORDER – создает окно, которое имеет толстую рамку вокруг окна, любое перекрывающееся окно создается с таким стилем автоматически.

WS_SIZEBOX – окно может изменять размер, если пользователь будет двигать рамку окна.

WS_SYSMENU – окно имеет системное меню.

WS_MAXIMIZEBOX и WS_MINIMIZEBOX – окно имеет кнопки увеличения размера до максимального и уменьшения размерадоминимального соответственно.

WS_VISIBLE – после создания окно сразу появляется на экране и окну приходит сообщение на перерисовку, лучше его использовать для дочерних и всплывающих окон, для главного окна приложения стоит использовать другой метод появления на экране.

WS_OVERLAPPEDWINDOW – рекомендуемый стиль перекрывающегося окна для главного окна приложения, определен как битовая комбинация следующих стилей:

WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU,WS_THIC KFRAME,WS_MINIMIZEBO, WS_MAXIMIZEBOX

Пример 1.2. Создание главного окна.

Для создания главного окна приложения можно использовать следующую функцию:

BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)

{

HWND hWnd; hWnd=CreateWindow(szWindowClass,

25

szTitle,WS_OVERLAPPENWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

NULL,NULL,hInstance,NULL); if(!hWnd)return FALSE; ShowWindow(hWnd,nCmdShow) ; UpdateWindow(hWnd); returnTRUE;

}

Функция ShowWindow() отображает окно на экране. Окно отображается как набор атрибутов, таких как заголовок, рамка, кнопки и т.д. Первый аргумент этой функции – handle создаваемого окна, второй определяет, в каком виде окно будет отображаться на экране. В нашем примере просто взяли и подставили значение nCmdShow, указанное при вызове функции WinMain(). Как правило, функции WinMain() передается зна-

чение SW_SHOWDEFAULT.

Функция UpdateWindow() посылает функции окна сообщение WM_PAINT, которое заставляет окно перерисовываться, т.е. прорисовывать не набор атрибутов, за прорисовку которых отвечает Windows, а изображение в рабочей области окна, за что должна отвечать непосредственно программа.

1.9. Цикл обработки сообщений

Простейший цикл обработки сообщений выглядит следующим образом:

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

{

TranslateMessage(&msg);

DispatchMessage(&msg)

}

Из очереди приложения сообщение выбирается функцией

GetMessage().

26

Первый ее параметр(&msg) – указатель на структуру типа MSG, т.е. на сообщение.

Второй параметр – handle окна, созданного программой. Сообщение, адресованное только этому окну, будет выбираться функцией GetMessage и передаваться оконной функции. Если вы хотите, чтобы обрабатывались сообщения для всех созданных программой окон, установите этот параметр в NULL.

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

Функция TranslateMessage() преобразует некоторые сообщения в более удобный для обработки вид.

Функция DispatchMessage() передает сообщение оконной функции.

Завершение цикла обработки сообщений происходит при выборке из очереди сообщения WM_DESTROY, в ответ на которое функция GetMessage() возвращает нулевое значение.

Пример 1.3. Функции WinMain()

 

int WINAPI WinMain(HINSTANCE

hInstance,

HINSTANCE

hPrevInstance,

LPSTR

lpCmdLine,

int

nCmdShow)

{

 

MSG msg;

 

MyRegisterClass(hInstanse);

 

if(!InitInstance(hInstance,nCmdShow)) return FALSE; while(GetMessage(&msg,NULL,0,0))

{

TranslateMessage(&msg);

DispatchMessage(&msg)

}

return msg.wParam;

}

27

Общая структура оконной функции следующая: /*заголовок*/

LRESULT CALLBACK WndProc(

HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

/* переключатель switch для обработки различных сообщений */

/* необработанные ранее сообщения обрабатываются системой по умолчанию*/

return DefWindowProc(hwnd,message,wParam,lParam)

}

1.10.Пример создания простого Win32 приложения

всреде Microsoft Visual Studio

1. Создаем новый пустой проект Win32 Application (тип

«Anemptyproject»).

2.Добавляем в него файл исходного кода (C++ Source File).

Вэтом файле:

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

записываем оконную функцию.

3. В оконной функции обрабатываем событие WM_DESTROY, реакцией на которое будет вызов API

функции PostQuitMessage(0).

Функция PostQuitMessage( ) помещает в очередь сообщение WM_QUIT. После получения этого сообщения приложение заканчивает работу.

4. Заставим программу обращать внимание на какие-нибудь наши действия. Например, на щелчок левой кнопки мыши.

Для этого в нашу оконную процедуру вставим обработчик для сообщения WM_LBUTTONUP. Например:

SetWindowText(hwnd, "Newtitle");

28

Здесь вызываем API-функцию SetWindowText. Она меняет заголовок окна. У этой функции два параметра. Первый указывает, для какого окна мы будем это делать. Второй – новый заголовок, который устанавливаем. После запуска программы результат будет таким (рис. 1.4).

Рис. 1.4

5. Развиваем наше приложение дальше. Сделаем так, чтобы при закрытии приложения появлялся MessageBox с двумя кнопками: OK и Cancel. Если пользователь выберет OK, то наше окно закрывается, а если Cancel, то не закрывается.

ДляэтогодобавимобработчикдлясообщенияWM_CLOSE. Функция MessageBox возвращает значение, соответствующее нажатой пользователем кнопки. Проверяем, не нажал ли пользователь кнопку OK (IDOK==MessageBox(...)), и если это

так, то посылаем сами себе сообщение для уничтожения окна:

SendMessage(hwnd, WM_DESTROY, NULL, NULL);

Здесь IDOK – идентификатор кнопки ОК, возвращаемый функцией MessageBox, если пользователь нажал эту кнопку.

6. Запускаем приложение. При его закрытии должен появиться следующий MessageBox (рис. 1.5).

Рис. 1.5

API-функция MessageBox имеет несколько параметров. Первый – handle окна, которому принадлежит MessageBox. Вто-

29

рой – это надпись в MessageBox, третий – заголовок. Последний параметр определяет внешний вид MessageBox. Так, константа MB_OKCANCEL указывает на то, что у него будут две кнопки:

OK и Cancel.

7. Изменим MessageBox так, чтобы появился предупреждающий значок и была активна вторая кнопка. Для этого изменим последний параметр функции.

Теперь наш MessageBox будет выглядеть так (рис. 1.6).

Рис. 1.6

Вопросы для самоконтроля

1.Для чего предназначен мастер AppWizard?

2.Что такое Workspace\Viewer? Для чего он предназначен? Какие он содержит вкладки?

3.Что позволяет вкладка Classes на Workspace\Viewer?

4.В чем особенности программирования для Windows?

5.Чем отличаются классы Windows от классов в объект- но-ориентированных языках программирования?

6.Как определяется объект Windows?

7.Что такое API? Что в него входит?

8.Какова минимальная Windows-программа?

9.Что необходимо иметь в программе, чтобы приложение могло взаимодействовать с пользователем?

10.Что такое окно программы?

11.Что такое вход в программу?

12.Что делает функция WinMain()?

13.Что делает оконная функция?

30