Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный практикум «Основы разработки приложений Windows» книга 2.DOC
Скачиваний:
91
Добавлен:
10.05.2014
Размер:
827.9 Кб
Скачать

Задание однократного интервала времени

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

timeBeginPeriod(1);//Установим максимальное разрешение

mmr=timeSetEvent(1000,1,TimeProc,0,TIME_ONESHOT);

...//Продолжение программы

void CALLBACK TimeProc(UINT,UINT,DWORD,DWORD,DWORD){

PostMessage(hwnd,WM_USER,(WPARAM)parm1,(LPARAM)parm2);

timeEndPeriod(1);//Отмена установленного ранее разрешения

..timeKillEvent(mmr);//В предположении, что mmr – глобальная

} // переменная

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

4. Дочерние окна Создание и использование дочерних окон

Любое реальное приложение Windows содержит большое количество окон. Хотя все графические элементы, составляющие экранный кадр приложения (текстовые строки, геометрические фигуры, растровые изображения) можно вывести непосредственно в главное окно, такой способ формирования экранного кадра обычно оказывается неудобным, главным образом из-за невозможности раздельного взаимодействия (с помощью мыши или клавиатуры) с этими элементами. Организация же системы вложенных, или порожденных, окон позволяет для каждого такого окна или группы окон иметь, например, свою форму курсора или свой цвет фона; главное же достоинство порожденных окон заключается в возможности придания каждому окну индивидуальной оконной функции. Это позволяет отдельно и по-разному обрабатывать для каждого окна поступающие в него сообщения Windows (или, наоборот, посылать в окна программно сформированные сообщения).

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

Рис. 4.1. Дочернее окно в главном окне приложения

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

Модальные диалоги, широко используемые в приложениях Windows в качестве средства управления работой программы, относятся к числу всплывающих окон, что определяется указанием при описании их стиля константы WS_POPUP. Модальные диалоговые окна могут быть только всплывающими. Вообще же вложенные окна, в частности немодальные диалоги, могут быть как всплывающими, так и дочерними; в последнем случае в описании их стиля присутствует константаWS_CHILD. Всплывающие и дочерние окна характеризуются следующими различиями:

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

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

  • координаты дочерних окон задаются относительно границ рабочей области родительского окна; координаты всплывающих окон задаются относительно границ экрана;

  • всплывающее окно может содержать собственное меню; в дочерних окнах меню не бывает.

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

Диалоговые окна относятся к окнам предопределенных классов, описанных в Windows. Это ограничивает их возможности, но упрощает взаимодействие с элементами управления, входящими в состав диалоговых окон, так как в Windows для этого предусмотрены стандартные средства.

В тех случаях, когда вложенное окно должно обеспечивать более широкие возможности, целесообразно создать в программе не диалоговое, а обычное порожденное окно и наделить его требуемыми характеристиками. При этом, если форма диалоговых окон описывается в файле ресурсов, а создание осуществляется функциями DialogBox()илиCreateDialog(), то порожденные (как дочерние, так и всплывающие) окна описываются непосредственно в программе, а создаются универсальными функциямиCre­ateWindow()илиCreateWindowEx(). Для определенности мы далее будем говорить о дочерних окнах, хотя фактически весь этот материал в равной степени относится и к окнам всплывающим.

Процедура создания и обслуживания дочернего, как и любого другого, окна состоит из трех этапов:

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

  • создания окна функцией Windows CreateWindow()с указанием стиля окна и его местоположения;

  • обработки сообщений, поступающих в дочернее окно.

Классы всех дочерних окон удобно регистрировать в функции WinMain()вслед за регистрацией класса главного окна; создаются же дочерние окна обычно в функцииOnCreate(), вызываемой Windows в процессе создания главного окна.

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

На рис. 4.2 приведен вид главного окна приложения, назначение которого – вывод на экран информации из базы данных пациента.

Рис. 4.2. Главное окно приложения с несколькими дочерними окнами

В главном окне образовано одно большое дочернее окно (с рамкой и полосой заголовка) для вывода данных в графической форме и пять “управляющих” окон меньшего размера с названиями отображаемых данных. Управляющие окна не имеют ни заголовка, ни рамки, и поэтому никак не выделяются на общем фоне главного окна. Их размеры соответствуют размерам выводимых в них строк текста. Все они принадлежат одному классу, для которого задана специфическая форма курсора – изображение кисти руки. В единую оконную функцию этих окон включена обработка сообщения WM_LBUTTONDOWN.При щелчке мышью по той или иной строке с названием данного в большое дочернее окно выводится соответствующая информация в виде графика.

Таким образом, в данном приложении зарегистрированы классы трех окон – главного окна, большого окна для вывода графика и пяти управляющих окон с названиями данных. Соответственно, в приложении имеются и три оконных функции. Легко сообразить, что оконная функция главного окна почти пуста – в ней может обрабатываться одно единственное сообщение WM_DESTROYо завершении приложения. Оконная функция окна графика содержит обработку сообщенийWM_PAINT, а окна с названиями данных, как уже отмечалось, должны обрабатывать сообщенияWM_LBUTTON­DOWN.

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

Рис. 4.3. Главное окно приложения с одним дочерним окном

#include <windows.h>

#include <windowsx.h>

/*Глобальные переменные*/

HINSTANCE hI;

char szClassName[]="MainWindow";

char szDataClassName[]="DataWindow";

char szTitle[]="Дочернее окно в главном";

/*Главная функция приложения*/

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int){

hI=hInst;

MSG msg;

WNDCLASS wc;

ZeroMemory(&wc,sizeof(wc));

/*Регистрируем класс главного окна*/

wc.lpszClassName=szClassName;

wc.hInstance=hInst;

wc.lpfnWndProc=WndProc;

wc.hCursor=LoadCursor(NULL,IDC_ARROW);

wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);

wc.hbrBackground=GetStockBrush(WHITE_BRUSH);

RegisterClass(&wc);

/*Регистрируем класс дочернего окна*/

wc.lpszClassName=szDataClassName;//Другой класс

wc.lpfnWndProc=DataWndProc;//Другая оконная функция

wc.hbrBackground=GetStockBrush(LTGRAY_BRUSH);//Другой цвет

RegisterClass(&wc);//Регистрируем

/*Создаем главное окно обычным образом*/

HWND hwnd = CreateWindow(szClassName,szTitle,

WS_OVERLAPPEDWINDOW,10,10,228,280,HWND_DESKTOP,

NULL,hInst,NULL);

ShowWindow(hwnd,SW_SHOWNORMAL);//Делаем главное окно видимым

while(GetMessage(&msg,NULL,0,0))//Цикл обработки сообщений

DispatchMessage(&msg);

return 0;

}

/*Оконная процедура главного окна*/

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,

WPARAM wParam,LPARAM lParam){

switch(msg){

HANDLE_MSG(hwnd,WM_CREATE,OnCreate);

HANDLE_MSG(hwnd,WM_PAINT,OnPaint);

HANDLE_MSG(hwnd,WM_DESTROY,OnDestroy);

default:

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

}

}

/*Функция обработки сообщения WM_CREATE главного окна*/

BOOL OnCreate(HWND hwnd,LPCREATESTRUCT){

CreateWindow(szDataClassName, NULL,//Создадим дочернее окно

WS_CHILD | WS_DLGFRAME | //Окно дочернее, с толстой рамкой,

WS_VISIBLE,//видимое (не нужна функция ShowWindow())

10,10,200,200,//Положение дочернего окна в главном

hwnd, NULL, hI, NULL);

return TRUE;

}

/*Функция обработки сообщения WM_PAINT главного окна*/

void OnPaint(HWND hwnd){

PAINTSTRUCT ps;

HDC hdc=BeginPaint(hwnd,&ps);

/*Выведем поясняющий текст*/

char str[]="График Декартова листа";

TextOut(hdc,20,220,str,strlen(str));

EndPaint(hwnd,&ps);

}

/*Оконная процедура дочернего окна */

LRESULT CALLBACK DataWndProc(HWND hwnd, UINT msg,

WPARAM wParam,LPARAM lParam){

switch(msg){

HANDLE_MSG(hwnd,WM_PAINT,DataOnPaint);

default:

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

}

}

/*Функция обработки сообщения WM_PAINT дочернего окна*/

void DataOnPaint(HWND hwnd){

PAINTSTRUCT ps;

float x,y,t;

int a=-5;

HDC hdc=BeginPaint(hwnd,&ps);

/*Построим график функции*/

for(t=-50;t<50;t+=0.01){

x=a*t/(1+t*t*t)*30;

y=a*t*t/(1+t*t*t)*30;

Rectangle(hdc,x+100,y+100,x+102,y+102);

}

EndPaint(hwnd,&ps);

}

Как видно из текста программы, оконная функция дочернего окна и объявляется, и выглядит так же, как и для главного окна. В ней удобно использовать макрос HANDLE_MSG; единственным обрабатываемым здесь сообщением являетсяWM_PAINT(поскольку дочернее окно мы отдельно закрывать не намерены, в оконной функции отсутствует обработка сообщенияWM_DESTROY). Разумеется, при необходимости можно было обрабатывать и другие сообщения для этого окна.

Главное окно мы обычно сначала создаемфункциейCreateWindow(), а затемделаем видимымвызовом функцииShowWindow(). Дочернее окно можно сразу вывести на экран, указав в его стиле, среди прочих, константуWS_VISIBLE. В этом случае отпадает необходимость в вызове для него функцииShowWindow()(впрочем, таким же приемом можно было воспользоваться и при создании главного окна). КонстантаWS_DLGFRAMEделает дочернее окно выпуклым, что характерно для диалоговых окон. При использовании, например, константыWS_BORDERмы получили бы менее красивое “плоское” дочернее окно в тонкой черной рамке.