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

Поcобие_БЕЛОВ_Графический_интерфейс_API

.pdf
Скачиваний:
141
Добавлен:
18.03.2016
Размер:
2.75 Mб
Скачать

31

return FALSE; //До создания окна узнаем габариты экрана в пикселях

int w=GetSystemMetrics(SM_CXSCREEN)-1; //Ширина int h=GetSystemMetrics(SM_CYSCREEN)-1; //Высота hwnd = CreateWindow(szMainClass, szTitle,

WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE, 0, 0, w, h, 0,0, hInstance, NULL);

if (!hwnd) return FALSE; while(GetMessage(&msg, 0, 0, 0))

DispatchMessage(&msg); return msg.wParam;

}

BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground) {

WNDCLASS wc; wc.style=wc.cbClsExtra=wc.cbWndExtra=0; wc.lpfnWndProc=Proc;

wc.hInstance = hInstance; wc.hIcon=LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(brBackground + 1); wc.lpszMenuName = (LPCTSTR)NULL; wc.lpszClassName=szName;

return (RegisterClass(Swc) != 0);

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{ switch (msg) {

case WM_DESTROY:

{ PostQuitMessage(0); return 0;

}

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

32

1.7.2. Расположение окон черепицей

Задача. В правом нижнем углу рабочей области окна приложения при первом нажатии левой клавиши мыши отобразить окно с заголовком «1-е окно», при втором нажатии – окно с заголовком «2-е окно» и так до пяти окон. Начиная со второго, окна располагать под предыдущим, сдвигая вверх и влево так, чтобы был виден заголовок, а левый верхний угол пятого окна должен совпадать с левым верхним углом рабочей области окна приложения. Если какие-либо из этих окон закрыты, то при нажатии левой клавиши мыши должно быть создано первое из закрытых окон.

Анализ задачи. (Полный текст приложения приведен, в листинге

1.3.).

Регистрируем класс окна приложения:

if (!RegClass(WndProc, szMainClass, COLOR_WINDOW)) return FALSE;

Фон окна приложения в задании не указан, поэтому из прил. 1, табл. 1.4 выбираем стандартный цвет COLOR_WINDOW.

Регистрируем класс временных окон:

if (!RegClass(WndPopup, szPopupClass,COLOR_BTNFACE)) return FALSE.

Для разнообразия цветом фона временных окон выбираем цвет трехмерных элементов.

Создаем окно приложения:

hwnd = CreateWindow(szMainClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL).

Для него указываем стиль WS_OVERLAPPEDWINDOW | WS_VISIBLE. Координаты окна задаем по умолчанию. Далее активизируем цикл обработки сообщений:

while(GetMessage(&msg, 0, 0,0)) DispatchMessage(&msg);

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

Все действия по созданию, отображению и расположению временных окон выполняет функция окна приложения при обработке

33

кодов сообщений WM_MOVE, WM_SIZE и WM_LBUTTONDOWN.

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

left=LOWORD(lParam); top=HIWORD(lParam);

// Остается переместить существующие временные окна: for (short j=0;j<5;j++) if (IsWindow( hwnds[j]))

MoveWindow( hwnds[j], left+cxClient-Width-xStep*j, top+cyClient-Height-yStep*j, Width,Height,TRUE);

Координата левого края j-го временного окна отсчитывается от правого края рабочей области (left+cxClient) и равна величине left+cxClient-Width-xStep*j.

Аналогично отсчитывается координата верхнего края j-ro временного окна.

При поступлении кода WM_SIZE требуется пересчитать размеры временных окон. Для этого запоминаем новую ширину и

высоту

рабочей

области

окна

приложения:

cxClient=LOWORD(lParam);

cyClient=HIWORD(lParam). Тогда

ширину и высоту временных окон можно вычислить по выражениям

Width=cxClient/2, Height=cyClient-4*yStep.

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

xStep=(cxClient-Width)/4;

Остается только переместить существующие временные окна. Эта часть обработки кода WM_SIZE полностью совпадает с такой же частью обработки кода WM_MOVE:

for (short j=0;j<5;j++) if (IsWindow( hwnds[j]))

MoveWindow( hwnds[j], left+cxClient-Width-xStep*j, top+cyClient-Height-yStep*j, Width, Height, TRUE).

Здесь перебирают все элементы массива дескрипторов hwnds, и если для j-ro элемента массива (дескриптора hwnds[j]) существует окно, это окно перемещается в новые координаты.

34

При обработке кода WM_LBUTTONDOWN (при нажатии левой клавиши мыши) перебирают элементы массива дескрипторов hwnds до тех пор, пока не обнаруживается, что для j-ro элемента массива (дескриптора hwnds[j]) не существует окна:

for (short j=0; j<5, IsWindow(hwnds[j]); j++).

Если для всех дескрипторов массива существуют окна, обработка сообщения завершается. Иначе для этого дескриптора в определенном условиями задачи месте создается окно:

hwnds[j] = CreateWindow(szPopupClass, str, WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, left+cxClient-Width-xStep*j,top+cyClient-Height-yStep*j, Width, Height, hwnd, 0, hInstance, NULL);

Следующее действие связано с изменением расположения только что созданного окна без перемещения:

if(j>0)

{ SetWindowPos(hwnds[j], hwnds[j-1], 0, 0, Width, Height, SWP_NOMOVE);

SetForegroundWindow(hwnds[0]);

},

т.е. функция SetWindowPos располагает окно hwnds[j] под предыдущим окном hwnds[j-l], а функция SetForegroundWindow

выдвигает на передний план первое окно из массива дескрипторов. Таким образом, при создании нового временного окна на переднем плане всегда окажется первое из них.

Этим завершается обработка кода WM_LBUTTONDOWN. Листинг 1.3. Расположение окон черепицей в обратном порядке.

#include <windows.h>

//Объявление функций

BOOL RegClass(WNDPROC, LPCTSTR, UiNT);

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM, LPARAM);

LRESULT CALLBACK WndPopup(HWND,UINT, WPARAM,LPARAM);

HINSTANCE hInstance; char szMainClass[ ] = "MainClass"; char szPopupClass[ ] = "PopupClass";

char szTitle[]= "Пример 1.3";

intWINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int

35 nCmdShow) {

MSG msg; HWND hwnd; hInstance=hInst;

if (!RegClass(WndProc, szMainClass,COLOR_WINDOW)) return FALSE;

if(!RegClass(WndPopup,szPopupClass,COLOR_BTNFACE)

)

return FALSE;

hwnd = CreateWindow(szMainClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0,0, hInstance, NULL);

if (!hwnd) return FALSE; while(GetMessage(&msg, 0,0,0)) DispatchMessage(&msg);

return msg.wParam;

}

BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)

{

WNDCLASS wc; wc.style=wc.cbClsExtra=wc.cbWndExtra=0; wc.lpfnWndProc=Proc; wc.hInstance = hInstance; wc.hIcon=LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground= (HBRUSH)(brBackground +1); wc.lpszMenuName = (LPCTSTR)NULL; wc.lpszClassName=szName;

return (RegisterClass(&wc) != 0);

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

static short cxClient, cyClient, yStep, xStep; static short left, top, Width, Height;

36

//Описываем массив дескрипторов окон static HWND hwnds[5];

switch (msg)

{case WM_CREATE:

{ //Шаг смещения окон по вертикали yStep=GetSystemMetrics(SM_CYCAPTION); return 0;

}

case WM_MOVE:

{ //Левый верхний угол рабочей области left=LOWORD(lParam); top=HIWORD(lParam); //Перемещаем

существующие временные окна for (short j=0;j<5;j++)

if (IsWindow(hwnds[j])) MoveWindow(hwnds[i], left+cxClient-Width- xStep*j, top+cyClient-Height-yStep*j, Width,Height,TRUE);

return 0;

}

caseWM_SiZE:

{ //Ширина и высота рабочей области cxClient=LOWORD(lParam);

cyClient=HIWORD(lParam); //Ширина и высота временных окон

Width=cxClient/2;

Height=cyClient-4*yStep; //Шаг смещения окон по горизонтали

xStep=(cxClient-Width)/4; //Перемещаем существующие временные окна

for (short j=0;j<5;j++)

if (IsWindow(hwnds[j]))

MoveWindow(hwnds[j], left+cxClient-Width- xStep*j, top+cyClient-Height-yStep*j, Width,Height,TRUE); return 0;

}

caseWM_LBUTTONDOWN: { //Ищем свободное место в массиве дескрипторов

for (short j=0; j<5, IsWindow(hwnds[j]); j++); //Если

37

свободного места нет, возвращаемся if (j>4)

return 0; //Формируем заголовок окна char str[20];

_itoa(j+1, str, 10);

strcat(str/-e окно"); //Создаем j-e временное окно hwnds[0] = CreateWindow(szPopupClass, str,

WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, left+cxClient-Width- xStep*j, top+cyClient-Height-yStep*j, Width, Height, hwnd, 0,

hInstance, NULL);

if(j>0) //Если создано не первое окно, перемещаем его вниз

{ SetWindowPos( hwnds[j], hwnds[j-1], 0,0, Width, Height, SWP_NOMOVE );

//Перемещаем на передний план первое окно

SetForegroundWindow(hwnds[0]);

}

return 0;

}

case WM_DESTROY: { PostQuitMessage(0); return 0; }

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

LRESULT CALLBACK WndPopup(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

return DefWindowProc(hwnd, msg, wParam, lParam);

}

Упражнения

1.После нажатия на левую (правую) клавишу мыши над рабочей областью окна в левом верхнем (правом нижнем) углу области отобразить временное окно размером в четверть области. Временное окно скрыть после отжатия клавиши.

2.В левом верхнем (в правом нижнем) углу рабочей области окна создать временное (дочернее) окно. После нажатия левой клавиши мыши 4 раза «мигает» временное окно, а после нажатия правой – 3 раза «мигает» дочернее окно. При этом окна выдают

38

различные звуковые сигналы.

3.Создать окно приложения размером в одну шестнадцатую площади экрана с заголовком «Форматирование диска» без кнопок изменения размеров, закрытия и сворачивания в пиктограмму и без кнопки системного меню. При перемещении курсора мыши над рабочей областью окно должно «убегать» от курсора мыши в случайным образом выбранном направлении, оставаясь на экране.

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

5.При запуске i-ro экземпляра (i>2) приложения спросить пользователя, необходимо ли его запустить. Если пользователь ответит «Да», то запустить его, иначе на передний план переместить 2-й экземпляр приложения и завершить работу i-ro экземпляра.

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

освоем заголовке.

7.Окно приложения без заголовка занимает весь экран фоном рабочего стола.

8.В центре рабочей области окна располагается невидимое окно без заголовка размером в четверть площади рабочей области. После нажатия левой клавиши мыши над рабочей областью любого из окон окно без заголовка должно стать видимым, а после нажатия правой – невидимым.

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

10.В центре рабочей области окна расположено окно без заголовка с вертикальной и горизонтальной полосами просмотра размером в четверть рабочей области. При нажатии разных клавиш мыши временное окно выдает разный звуковой сигнал.

11.Создать окно размером в четверть площади экрана. После двойного щелчка мыши окно перемещается так, что его центр совпадает с координатами курсора мыши в момент щелчка.

39

12.Дочернее окно размером 100х100 пикселей при перемещении курсора мыши над ним «убегает» от курсора мыши в произвольном направлении, в пределах родительского окна.

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

14.В рабочей области окна приложения рядом друг с другом расположить 3 временных окна, каждое из которых по-своему реагирует на нажатие левой клавиши мыши.

15.Окно первого экземпляра приложения расположить в левом верхнем, второго – в правом верхнем, третьего – в левом нижнем, четвертого – в правом нижнем углу экрана. Причем все окна равных размеров и вместе занимают весь экран. В заголовке окна указать номер экземпляра. Запретить запуск пятого экземпляра.

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

17.Центр рабочей области окна занимает временное окно размером в четверть площади области. Оно перемещается в тот угол рабочей области, где щелкнули левой клавишей мыши. А после щелчка правой клавишей мыши временное окно перемещается в угол, противоположный текущему углу.

18.Окно приложения занимает четверть экрана и расположено

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

19.Окно размером в четверть площади экрана расположено в центре экрана. После нажатия левой клавиши мыши окно несколько раз меняет подсветку и перемещается в угол экрана так, что курсор мыши оказывается за пределами окна.

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

40

21.В рабочей области окна приложения рядом друг с другом расположить 4 временных окна, в заголовках которых указан номер окна. После нажатия левой клавиши мыши временное окно выдает сообщение, содержащее номер окна.

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

23.В углах рабочей области окна приложения созданы невидимые временные окна с заголовком. Каждое окно становится видимым после нажатия левой клавиши мыши над его частью рабочей области и становится невидимым после нажатия левой клавиши мыши над его рабочей областью.

24.Окно приложения размером в четверть площади экрана занимает один из углов экрана. После нажатия левой клавиши мыши окно сворачивается в пиктограмму. После щелчка по пиктограмме оно восстанавливается в другом углу экрана.

25.При запуске приложения показать окна существующих копий этого приложения и спросить пользователя, необходимо ли запустить еще один экземпляр. Если пользователь ответит «Да», то запустить его. Иначе завершить работу приложения.

Контрольные вопросы

1.Чем отличается текст приложения, которое создает окна, от текста приложения, которое не создает окон?

2.Каков алгоритм работы главной функции приложения?

3.Какие действия выполняет приложение для создания окна?

4.Описание каких программных объектов необходимо включить в текст приложения для регистрации класса окон?

5.В каком месте и как происходит вызов функции окна?

6.Каково назначение формальных параметров функции окна?

7.Какие сообщения получает функция окна при создания окна?

8.Что происходит с теми сообщениями, которые функция окна не обрабатывает?

9.Каковы отличительные характеристики перекрывающихся, временных и дочерних окон?

10.Как единственный раз создать окно в теле функции окнавладельца?