Программирование в среде WINDOWS. 1 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Программирование в среде WINDOWS. 1



Программирование в среде WINDOWS. 1

Графические функции GDI и средства GDI. 2

Аппаратная независимость. 3

Схема процесса создания Windows программы. 4

Файл определения модуля. 5

Сообщения. 6

Окна. 8

Меню. 20

Диалоговые панели. 34

Органы управления. 45

Контекст. 67

Логическая и физическая системы координат...................................................................................................84

Рисование…………………………………………………………………………………………….……...………99

Программирование в среде WINDOWS.

Введение.

Вся внутренняя деятельность системы Windows в значительной степени базируется на трех подсистемах:

системе графического приборного интерфейса;

системе обеспечения многозадачного режима;

системе обеспечения аппаратной независимости.

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

Графический Приборный Интерфейс.

Графический приборный интерфейс, или GDI (Graphics Device Interf/асе), является связующим звеном между программой и графическим устройством вывода и служит для представлении программой визуально ориентированной информации пользователю. GDI представляет собой библиотеку процедур, которые обеспечивают создание графического интерфейса и управление им. Эта библиотека доступна как для Windows так и для любой прикладной программы.

Display Context.

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

Использование DC обусловлено следующими причинами. Прежде.всего, в каждый конкретный момент времени используется лишь небольшая часть возможностей, Рассмотрим качестве примера рисование прямоугольника. Для того чтобы полностью контролировать представление прямоугольника на охране, следует определить его положение в окне. Нужно также определить цвет и границы прямоугольника. Далее программист может пожелать переопределить вид границы (например, сделать ее непрерывной или пунктирной линией). Дополнительно следует определить, валяется ли прямоугольник закрашенным и если да, то каким цветом. И, наконец, программа должна управлять взаимодействием прямоугольника с уже существующими ив экране рисунками.

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

Очень важ­ными являются понятия отсекание.

В системе Windows для любого открытого на экране окна существует вероятность соседства (или даже перекрали») с одним или несколькими окнами. GDI управляет своими функциями таким образом, чтобы не допустить графического вывода вне границ окна, которое использует функции GDI. Более того, GDI обеспечивает графический вывод в пределах рабочей области окна, чтобы не нарушить графические объекты нерабочей области. Такой подход и называется отсеканием. Действие функций графического вывода ограничено областью отсекания. Windows устанавливает параметры области отсекания перед передачей его прикладной программе. Как уже отмечалось, в Windows для программы имеются две возможности получения доступа к DC: функции BeginPalnt и GeiDC. При использовании функции BeginPaiot размеры области отсекания устанавливаются так, чтобы содержать именно тот участок рабочей области окна, который должен быть обновлен. В случае использования функции GetDC область отсекания охватывает всю рабочую область окна. Программа может использовать функции GDI для изменения размеров области отсекания, но она не в состоянии сделать область отсекания больше видимой части рабочей области окна. Таким образом, Windows охраняет множественные окна от вмешательства в дела (т.е. рабочие области) друг друга.

Хотя Windows самостоятельно проводит всю работу, связанную с изменением размеров окна, программа может реагировать на увеличение или уменьшение размеров окна по-разному. Эта разница в реакции программы на изменение размеров окна называется, масштабированием.

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

В Window существуют 8 методов (режимов) масштабирования.

Аппаратная независимость

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

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

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

 

 

Файл определения модуля
Исходный текст на языке СИ
Компилятор СИ
Объектный файл
WINDOWS программа без ресурсов
Компоновка
Заголовочный файл
Библиотечные файлы
Компилятор ресурсов
Текстовый файл ресурсов  
Скомпилированный файл ресурсов
Компилятор ресурсов
Бинарный файл ресурсов  
WINDOWS программа

 


Сообщения.

 

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

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

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

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

Сообщение, в основном, состоит из полей wParam и lParam. В сообщении, формируемом при нажатии любой кнопки мыши, младшее слово lParam содержит X – координату курсора, а старшее – Y – координату. Семь младших бит поля wParam содержит состояние кнопок мыши и клавиш Shift и Ctrl. Если кнопка или клавиша нажата, то соответствующий бит находится в состоянии 1.

Создание окна в Windows

Структура программы в Windows:

 

 

GetMessage
SendMessage
Асинхронное событие
TranslateMessage
DispatchMessage
PostMessage
Синхронное событие
WM_QUIT
Цикл сообщений
Выход
Case WM_COMMAND Case WM_DESTROY default
MainWindowProc
WinMain
Начало

 

 


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

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

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

 

 

Окна

 

#include <windows.h>

#include <stdlib.h>

const char szClassName[] = "WinLab_01";

const char szWindowName[] = "Term II. Windows Lab 01.";

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);

#pragma argsused

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{

HWND hWnd;

// Описание класса окна

WNDCLASS wndclass;

wndclass.style = CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc = WndProc;

wndclass.hInstance = hInstance;

wndclass.hIcon = LoadIcon(hInstance, IDI_APPLICATION);

wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground = 5;

wndclass.lpszMenuName = NULL;

wndclass.lpszClassName = szClassName;

if (!RegisterClass(&wndclass)) // Регистрируем класс окна

exit(FALSE);

// Создаем окно

hWnd=CreateWindow(szClassName,szWindowName, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0,CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd) exit(FALSE);

// Показываем окно

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

// Цикл сообщений

MSG msg;

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

{TranslateMessage(&msg);

DispatchMessage(&msg);}

return msg.wParam;}

/* Обработчик сообщений */

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

{switch (iMessage)

{case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, iMessage, wParam, lParam); }

return 0;}

 

Сообщение с кодом WM_CREATE передается функции окна в момент создания окна.

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

При разрушении структуры данных окна (при уничтожении окна) функция окна получает сообщение с кодом WM_DESTROY. Обработчик этого сообщения действует как деструктор.

 

Модификатор Pascal требует компилировать функцию в стиле языка Паскаля – с очисткой стека от параметров функции. Если указать другой модификатор (cdecl, WINAPI) то вызов функции будет компилироваться в стиле С, стек будет очищен вызывающей программой.

Параметр hInstance идентифицирует данное приложение. Он содержит адрес памяти, выделенной для работы. Этот адрес является виртуальным и по умолчанию настроен таким образом, что равен 0x40000.

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

Поле lpszCmdLine позволяет передавать запускаемому приложению командную строку. Если на рабочем столе для запуска создан ярлык, то щелчок правой кнопкой вызывает появление окна свойств. Если программа запускается из среды разработки, то командная строка может быть задана в свойствах проекта Project - Property-Debugging - CommandArguments. В командной строке (в отличие от argc и argv) отсутствует первый параметр, определяющий путь к исполняемому файлу. Получит командную строку с первым параметром можно с помощью функции GetCommandLine(). Порядок записи операндов в стек не зависит от модификатора. Первый параметр передаётся последним и будет в вершине стека.

 

В области стека функции WinMain созданы две переменные с именами msg и hwnd:

MSG msg; // структура для работы с сообщениями

HWND hwnd; // идентификатор главного окна приложения

Переменная msg представляет собой структуру типа MSG, описанную в файле windows.h следующим образом:

typedef struct tagMSG

{

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

} MSG;

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

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

 

Структура WNDCLASS используется для регистрации класса окна. Эта структура определена в файле windows.h:

typedef struct tagWNDCLASS

{

UINT style;

WNDPROC lpfnWndProc;

int cbClsExtra;

int cbWndExtra;

HINSTANCE hInstance;

HICON hIcon;

HCURSOR hCursor;

HBRUSH hbrBackground;

LPCSTR lpszMenuName;

LPCSTR lpszClassName;

} WNDCLASS;

Перед регистрацией вам необходимо заполнить все поля в этой структуре.

Поле style определяет стиль класса и задается в виде констант (описанных, как всегда, в файле windows.h), имя которых начинается с префикса CS_, например CS_HREDRAW, CS_VREDRAW. Стиль задает реакцию окна на изменение его размера, на выполнение в окне операции двойного щелчка мышью (double click), а также позволяет определить другие характеристики окна, создаваемого на базе данного класса. Например, если для стиля задать значение CS_HREDRAW | CS_VREDRAW, при изменении вертикального или горизонтального размера окна приложение должно его перерисовать, то есть нарисовать заново все или часть того, что было изображено в окне до изменения размера.

Если стиль класса не используется, то для него задается нулевое значение:

wc.style = 0;

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

wc.lpfnWndProc = (WNDPROC) WndProc;

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

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

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

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

wc.cbClsExtra = 0;

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

wc.cbWndExtra = 0;

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

wc.hInstance = hInstance;

Следующее поле имеет имя hIcon и тип HICON. Это идентификатор пиктограммы, в которую превращается окно при уменьшении его размеров до предела (при минимизации окна).

Для загрузки пиктограммы в приложении вызывается функция программного интерфейса Windows с именем LoadIcon:

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

Прототип функции LoadIcon:

HICON WINAPI LoadIcon(HINSTANCE hinst, LPCSTR pszicon);

Первый параметр функции (hinst) содержит идентификатор приложения, второй (pszicon) - имя ресурса-пиктограммы.

Позже мы научим вас определять для окон собственные пиктограммы, нарисованные с помощью приложения Resource Workshop, входящего в комплект поставки Borland C++ for Windows.

В поле hCursor (имеющем тип HCURSOR) вы можете задать вид курсора мыши при его прохождении над окном. Вы знаете, что курсор мыши меняет свою форму при перемещении над различными окнами приложений Windows. При регистрации класса окна вы можете указать форму курсора, для чего и используется поле hCursor.

В нашем приложении мы задаем курсор в виде стандартной стрелки, для чего вызываем функцию LoadCursor и указываем в качестве второго параметра константу IDC_ARROW:

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

Прототип функции LoadCursor:

HCURSOR WINAPI LoadCursor(HINSTANCE hinst, LPCSTR pszCursor);

Вы можете определить для окна свой курсор, нарисовав его аналогично пиктограмме при помощи такого приложения, как Resource Workshop или Microsoft SDKPaint. Однако пока для простоты мы будем использовать стандартный курсор.

Далее нам необходимо заполнить поле hbrBackground, имеющее тип HBRUSH. Это поле позволяет определить кисть (brush), которая будет использована для закрашивания фона окна. В качестве кисти можно использовать "чистые" цвета или небольшую пиктограмму размером 8 х 8 точек.

В нашем приложении мы использовали системный цвет, который Windows использует для закрашивания фона окон:

wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

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

Поле lpszMenuName (указатель на строку типа LPCSTR) определяет меню, располагающееся в верхней части окна. Если меню не используется, при заполнении этого поля необходимо использовать значение NULL:

wc.lpszMenuName = (LPSTR)NULL;

Тип LPCSTR определяется как константный дальний указатель на строку символов:

typedef const char FAR* LPCSTR;

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

wc.lpszClassName = (LPSTR)szClassName;

На этом подготовку структуры wc к регистрации класса окна можно считать законченной. Можно вызывать функцию RegisterClass.

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

Далее приложение вызывает функцию CreateWindow для того, чтобы создать главное окно приложения:

hwnd = CreateWindow(

szClassName, // имя класса окна

szWindowTitle, // заголовок окна

WS_OVERLAPPEDWINDOW, // стиль окна

CW_USEDEFAULT, // задаем размеры и расположение

CW_USEDEFAULT, // окна, принятые по умолчанию

CW_USEDEFAULT,

CW_USEDEFAULT,

0, // идентификатор родительского окна

0, // идентификатор меню

hInstance, // идентификатор приложения

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

 

В случае успеха функция CreateWindow возвращает идентификатор окна (типа HWND). Если окно создать не удалось, функция возвращает нулевое значение.

Приведем прототип функции CreateWindow:

HWND CreateWindow(LPCSTR lpszClassName, LPCSTR lpszWindowName, DWORD dwStyle,int x, int y, int nWidth, int nHeight,HWND hwndParent, HMENU hmenu, HINSTANCE hinst,void FAR* lpvParam);

Многочисленные параметры функции CreateWindow дополняют описание окна, сделанное при создании класса окна.

Первый параметр функции (lpszClassName) - указатель на строку, содержащую имя класса, на базе которого создается окно. В процессе инициализации приложения мы зарегистрировали класс с именем "WindowAppClass" (переменная szClassName).

Второй параметр функции (lpszWindowName) - указатель на строку, содержащую заголовок окна (Title Bar). В нашем случае окно будет иметь заголовок "Window Application" (переменная szWindowTitle).

Третий параметр (dwStyle) - стиль создаваемого окна. Этот параметр задается как логическая комбинация отдельных битов. Константа WS_OVERLAPPEDWINDOW соответствует окну, которое может перекрывать другие окна, имеет заголовок, системное меню, кнопки для минимизации и максимизации окна, а также рамку вокруг окна, с помощью которой можно изменять размер окна. Операционная система Windows позволяет задавать различные стили для создаваемых окон. Мы их рассмотрим в дальнейшем.

Четвертый и пятый параметры функции CreateWindow для окна данного стиля определяют горизонтальную (x) и вертикальную (y) координату относительно верхнего левого угла экрана видеомонитора.

Шестой и седьмой параметры определяют ширину (nWidth) и высоту (nHeight) создаваемого окна.

Наше приложение в качестве координат окна и его размеров использует константу CW_USEDEFAULT. При этом операционная система Windows сама определяет положение и размеры создаваемого окна.

Восьмой параметр (hwndParent) определяет индекс родительского окна. Для нашего приложения в качестве значения используется нуль, так как в приложении создается только одно окно.

Девятый параметр (hmenu) - идентификатор меню или идентификатор порожденного (child) окна. В нашем случае никакого меню или порожденного окна нет, поэтому в качестве значения используется нуль.

Десятый параметр (hinst) - идентификатор приложения, которое создает окно. Необходимо использовать значение, передаваемое функции WinMain через параметр hInstance.

Одиннадцатый, последний параметр функции (lpvParam) представляет собой дальний указатель на область данных, определяемых приложением. Этот параметр передается в функцию окна вместе с сообщением WM_CREATE при создании окна. Наше приложение не пользуется этим параметром.

Отображение окна на экране

Окно создано, но на экране оно еще не появилось, в чем вы можете убедиться, запустив приложение под управлением отладчика. Поэтому, проверив, что создание окна выполнено успешно (функция CreateWindow вернула ненулевое значение), необходимо сделать окно видимым (нарисовать его на экране). Это можно сделать с помощью функции ShowWindow:

ShowWindow(hwnd, nCmdShow);

Прототип функции:

BOOL ShowWindow(HWND hwnd, int nCmdShow);

Функция отображает окно, идентификатор которого задан первым параметром (hwnd), в нормальном, максимально увеличенном или уменьшенном до пиктограммы виде, в зависимости от значения второго параметра (nCmdShow). После отображения окна в нормальном или максимально увеличенном виде внутренняя поверхность окна закрашивается кистью, определенной при регистрации класса.

Внешний вид окна, создаваемого нашим приложением, показан на рис.

Сразу после функции ShowWindow в приложении вызывается функция UpdateWindow.

UpdateWindow(hwnd);

Прототип функции:

void UpdateWindow(HWND hwnd);

Функция UpdateWindow вызывает функцию окна, заданного идентификатором, передаваемым в качестве параметра hwnd, и передает ей сообщение WM_PAINT. Получив это сообщение, функция окна должна перерисовать все окно или его часть. Наше приложение не обрабатывает это сообщение, передавая его функции DefWindowProc.

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

После отображения окна функция WinMain запускает цикл обработки сообщений:

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

{

DispatchMessage(&msg);}

Функция GetMessage предназначена для выборки сообщений из очереди приложения и имеет следующий прототип:

BOOL GetMessage(LPMSG lpmsg, HWND hwnd,WORD uMsgFilterMin, WORD uMsgFilterMax);

Первый параметр функции (lpmsg) является дальним указателем на структуру типа MSG, в которую будет записано выбранное из очереди сообщение. Тип LPMSG определен в файле windows.h следующим образом:

typedef MSG FAR* LPMSG;

Второй параметр (hwnd) является идентификатором окна, для которого необходимо выбрать сообщение из очереди приложения.

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

Третий (uMsgFilterMin) и четвертый (uMsgFilterMax) параметры функции GetMessage позволяют определить диапазон сообщений, выбираемых из очереди приложения, задавая соответственно минимальное и максимальное значение кодов выбираемых сообщений. Если для этих параметров указать нулевые значения (как это сделано в нашем приложении), из очереди приложения будут выбираться все сообщения.

Как работает функция GetMessage?

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

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

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

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

DWORD DispatchMessage(LPMSG lpmsg);

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

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

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

Завершение работы приложения

Приложение обычно завершает свою работу, когда вы нажимаете комбинацию клавиш <Alt+F4> или выбираете строку "Close" в системном меню главного окна приложения. При этом в его функцию окна попадает сообщение WM_DESTROY. В ответ на это сообщение функция окна помещает в очередь сообщение WM_QUIT, вызывая для этого функцию PostQuitMessage. Как вы уже знаете, выборка этого сообщения приводит к завершению цикла обработки сообщений и, следовательно, к завершению работы приложения.

Если операционная система Windows завершает свою работу, функциям окна каждого работающего приложения передается сообщение WM_QUERYENDSESSION. Обрабатывая это сообщение соответствующим образом, приложение может завершить свою работу, предварительно сохранив все необходимые данные.

Стиль класса окна

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

wc.style = 0;

Стиль класса окна задается в виде отдельных битов, для которых в файле windows.h определены символические константы с префиксом CS_:

Стиль Описание
CS_BYTEALIGNCLIENT Внутренняя область окна (client area) должна быть выравнена по границе байта видеопамяти. Иногда используется для ускорения процесса вывода изображения
CS_BYTEALIGNWINDOW Все окно (не только внутренняя область окна) должно быть выравнено по границе байта видеопамяти
CS_CLASSDC Необходимо создать единый контекст отображения, который будет использоваться всеми окнами, создаваемыми на базе данного класса
CS_DBLCLKS Функция окна будет получать сообщения при двойном щелчке клавишей мыши (double click)
CS_GLOBALCLASS Данный класс является глобальным и доступным другим приложениям. Другие приложения могут создавать окна на базе этого класса
CS_HREDRAW Внутренняя область окна должна быть перерисована при изменении ширины окна
CS_NOCLOSE В системном меню окна необходимо запретить выбор функции закрытия окна (строка Close будет отображаться серым цветом, и ее нельзя выбрать)
CS_OWNDC Для каждого окна, определяемого на базе данного класса, будет создаваться отдельный контекст отображения
CS_PARENTDC Окно будет пользоваться родительским контекстом отображения, а не своим собственным. Родительский контекст - это контекст окна, создавшего другое окно (см. дальше)
CS_SAVEBITS Для данного окна Windows должна сохранять изображение в виде битового образа (bitmap). Если такое окно будет перекрыто другим окном, то после уничтожения перекрывшего окна изображение первого окна будет восстановлено Windows на основании сохраненного ранее образа
CS_VREDRAW Внутренняя область окна должна быть перерисована при изменении высоты окна

Чаще всего используются стили CS_HREDRAW и CS_VREDRAW:

wc.style = CS_HREDRAW | CS_VREDRAW;

Если для класса заданы стили CS_HREDRAW и CS_VREDRAW, при изменении размеров окна функция окна может получить сообщение WM_PAINT. В этом случае функция окна должна перерисовать часть окна или все окно.

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

Стиль окна

Определенный в классе окна стиль класса окна используется при создании на базе этого класса всех окон. Для дальнейшего уточнения внешнего вида и поведения окна используется другая характеристика - стиль окна. Стиль окна указывается при создании окна функцией CreateWindow. В наших примерах основное окно приложения не имело стиля класса окна, но для него был определен стиль окна WS_OVERLAPPEDWINDOW:

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

Мы рассмотрим три основных стиля окон - перекрывающиеся окна (overlapped window), временные окна (pop-up window) и дочерние окна (child window).

Перекрывающиеся (overlapped) окна

Перекрывающиеся окна обычно используются в качестве главного окна приложения. Такие окна имеют заголовок (title bar), рамку и, разумеется, внутреннюю часть окна (client region). Дополнительно перекрывающиеся окна могут иметь (а могут и не иметь) системное меню, кнопки для максимального увеличения размера окна и для сворачивания окна в пиктограмму, вертикальную и горизонтальную полосу просмотра (scroll bar) и меню.

В первых версиях операционной системы Windows (версии 1.х) окна располагались рядом и назывались tiled window (tile - черепица). Сейчас такие окна не используются, вместо них появились перекрывающиеся окна, способные перекрывать окна других приложений. Перекрывающиеся окна называются также окнами верхнего уровня (top-level window).

Файл windows.h содержит следующее определение стиля перекрывающегося окна:

#define WS_OVERLAPPED 0x00000000L

В нашем приложении для определения стиля перекрывающегося окна мы использовали символическую константу WS_OVERLAPPEDWINDOW, определенную как логическое ИЛИ нескольких констант:

#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | \

WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | \

WS_MAXIMIZEBOX)

Константа WS_OVERLAPPED определяет базовый стиль окна - перекрывающееся окно. Стиль WS_OVERLAPPEDWINDOW в добавление к базовому указывает, что окно должно иметь заголовок (константа WS_CAPTION), системное меню (WS_SYSMENU), толстую рамку для изменения размера окна (WS_THICKFRAME), кнопку минимизации размера окна (WS_MINIMIZEBOX) и кнопку для максимального увеличения размера окна (WS_MAXIMIZEBOX). Если окно имеет заголовок, вы можете его перемещать по экрану.

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

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

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

Если окно - хозяин сворачивается в пиктограмму, все окна, которыми оно владеет, становятся невидимыми. Если вы сначала свернули в пиктограмму окно, которым владеет другое окно, а затем и окно - хозяин, пиктограмма первого (подчиненного) окна исчезает.

Если вы уничтожили окно, автоматически уничтожаются и все принадлежащие ему окна.

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

Координаты создаваемых функцией CreateWindow перекрывающихся окон указываются по отношению ко всему экрану. Таким образом, если вы создаете перекрывающееся окно с координатами (0, 0), оно будет расположено в верхнем левом углу экрана.

Временные (pop-up) окна

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

Временные окна, в отличие от перекрывающихся, могут не иметь заголовок (title bar). Если для временного окна определен заголовок, оно может иметь и системное меню. Часто для создания временных окон, имеющих рамку, используется стиль WS_POPUPWINDOW, определенный в файле windows.h следующим образом:

#define WS_POPUPWINDOW (WS_POPUP | WS_BORDER | WS_SYSMENU)

Если надо добавить к временному окну системное меню и заголовок, стиль WS_POPUPWINDOW следует использовать в комбинации со стилем WS_CAPTION, добавляющим заголовок.

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



Поделиться:


Последнее изменение этой страницы: 2017-02-07; просмотров: 271; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.17.203.68 (0.154 с.)