Четыре составные части программы под WINDOWS
Любое оконное приложение, написанное под Windows должно содержать в себе следующие элементы:
·Функцию регистрации класса окна.
·Функцию создания окна.
·Оконную процедуру.
·Цикл обработки сообщений.
Ранее уже говорилось, что большинство программ под WINDOWS должны иметь хотя бы одно окно. Для его создания необходимо выполнить два шага: регистрацию класса окна и вызвать функцию создания окна. Оба этих действия определяют основные свойства (видимые и невидимые характеристики) окна. Основное отличие первого шага от второго заключается в том, что на основе зарегистрированного класса окна можно создавать бесконечное число окон. Таким образом, при регистрации класса окна задаются свойства, общие (одинаковые) для всех последующих окон свойства. Функция создания окна создает очередной экземпляр окна, добавляя уже конкретные свойства окна, такие как положение на экране, размеры, содержание текста и т.п.
Регистрация окна проводится в два этапа. Во-первых, заполняется структура WNDCLASSEX (поля которой как раз и содержат общую информацию), после чего выполняется функция RegisterClassEx , в которую передается указатель на заполненную структуру. Ниже приведен фрагмент программы с комментариями к полям заполняемой структуры:
WNDCLASSEX wcex; // объявление переменной типа структура оконного класса
wcex.cbSize = sizeof(WNDCLASSEX); // размер структуры в байтах
wcex.style = CS_HREDRAW | CS_VREDRAW; // стиль окна
wcex.lpfnWndProc = (WNDPROC)WndProc; //адрес оконной процедуры
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
– 9 –
wcex.hInstance = hInstance; // описатель приложения
wcex.hIcon = MyIcon1; // определение иконки
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // определение курсора
wcex.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); // установка фона
wcex.lpszMenuName = NULL; // определение меню
wcex.lpszClassName = "MyWindow"; // имя класса
wcex.hIconSm = NULL; // определение маленькой иконки
RegisterClassEx(&wcex); // регистрация класса окна
В дальнейшем, мы вернемся к рассмотрению отдельных полей структуры.
После того, как класс окна зарегистрирован, можно создавать окна, что выполняется следующим образом:
hWnd=CreateWindow( "MyWindow", // имя класса окна
"Строка заголовка", // имя приложения
WS_OVERLAPPEDWINDOW, // стиль окна
CW_USEDEFAULT, // положение по Х
CW_USEDEFAULT, // положение по Y
CW_USEDEFAULT, // размер по Х
CW_USEDEFAULT, // размер по Y
NULL, // описатель родительского окна
NULL, // описатель меню окна
hInstance, // указатель приложения
NULL,// параметры создания.
Функция CreateWindow возвращает описатель вновь созданного окна. Если возвращаемое значение равно NULL , это значит, что окно не было создано по какой-либо причине.
Чтобы созданное окно появилось на экране, необходимо выполнить последовательно две функции:
ShowWindow(hWnd, nCmdShow); // Показать окно
UpdateWindow(hWnd); // Обновить окно
Следующие важные элементы программы – это оконная процедура и цикл обработки сообщений. Адрес оконной процедуры использовался при регистрации класса окна (WndProc). Для их рассмотрения
сделаем небольшое отступление. В первой лекции обсуждался вопрос о событиях и сообщениях. Настало время более подробно рассмотреть этот вопрос.
Порядок обработки сообщений, цикл обработки сообщений
Когда в системе происходит какое-либо событие, на которое должна отреагировать исполняемая программа (например, нажата клавиша на клавиатуре, перемещена мышь или истекло время ожидания), операционная система посылает программе сообщение об этом событии. Программа получает сообщение и выполняет код (часть программы), реагирующий на это событие. На рис. 2.1. отображен этот процесс.
Рис. 2.1. Порядок прохождения сообщения
Сформированное операционной системой сообщение помещается в системную очередь сообщений. Каждое сообщение предназначено конкретному окну. ОС определяет, какому приложению предназначено сообщение и помещает его в очередь сообщений программы. Далее программа сама должна заботиться об обработке сообщения.
Цикл обработки сообщения выбирает очередное сообщение из программной очереди и вызывает оконную процедуру (ОП) того окна, которому оно предназначено. Если программа в это время занята обработкой другого сообщения, вновь прибывшее сообщение ожидает в очереди завершения обработки предыдущего сообщения (это особенно заметно на медленных машинах, когда например, набранное слово на клавиатуре появляется на экране спустя некоторое время).
Стандартный цикл обработки сообщений имеет вид:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
– 11 –
DispatchMessage(&msg);
}
Функция GetMessage выбирает очередное сообщение из программной очереди . Результатом выполнения функции является заполнение структуры msg , которая содержит всю необходимую информацию о полученном сообщении: описатель окна, которому предназначено сообщение, тип сообщения, параметры сообщения (зависящие от типа сообщения) и время возникновения сообщения. Функция также возвращает некоторое число, которое отлично от нуля для всех сообщений кроме сообщения о закрытии программы. В последнем случае цикл обработки сообщений прерывается и программа завершается.
Функция TranslateMessage преобразует сообщение в соответствии с системными настройками (например, преобразовывает код нажатой клавиши клавиатуры согласно выбранного в настоящее время языка).
Функция DispatchMessage определяет, какому окну приложения послано сообщение и вызывает соответствующую оконную процедуру.
Оконная процедура
Оконная процедура является центральной частью программы. Не будет большим преувеличением сказать, что более девяноста процентов алгоритма программы заключено в оконной процедуре. Оконная процедура соответствует одному (или более) окну программы и содержит в себе программную реализацию поведения окна. Подпрограммы рисования элементов окна, реакция на действия мыши, клавиатуры, закрытия окна – все это заключено внутри оконной процедуры.
Оконная процедура имеет стандартный вид:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
. . . . .
switch (message)
{
case WM_CREATE: // Сообщение приходит при создании окна
. . . . . . .
break;
case WM_PAINT: // Перерисовать окно
. . . . . . .
break;
case WM_DESTROY: // Завершение работы
. . . . . . .
break;
default:
// Обработка сообщений, которые не обработаны пользователем
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Оконная процедура вызывается только тогда, когда пришло какое-либо сообщение, предназначенное соответствующему окну. Обратите внимание, что оконная процедура задается в классе регистрации окна, то есть для нескольких окон существует только один экземпляр оконной процедуры. Какому именно окну послано сообщение определят первый параметр функции WndProc – описатель окна hWnd .
Второй параметр функции - message -определяет тип сообщения и принимает одно значение из множества WM _<сообщение>. Например, когда message равно WM_CREATE , это означает, что пришло сообщение о создании окна (данное сообщение является первым сообщением, приходящим в оконную процедуру после создания окна и приходит только один раз).
Третий и четвертый параметры - wParam и lParam сопутствуют сообщению и зависит от его типа. Например, если приходит сообщение о нажатии мыши, в этих параметрах содержится информация о координатах мыши в момент нажатия и состоянии управляющих клавиш.
Программист сам выбирает, какие сообщения обрабатывать, а какие нет. Всего существует несколько сотен сообщений, поэтому обработка всех из них вызвало бы затруднение. Для ликвидации этого неудобства существует функция DefWindowProc , которая по умолчанию обрабатывает все возможные сообщения.
В заключение лекции приведем полностью текст программы, которая является полноправным оконным приложением. В результате выполнения программы на экране появляется окно, содержащее стандартные элементы (заголовок, рамку, кнопки управления) и надпись "Первая программа для WINDOWS ". Окно можно перемещать, минимизировать, максимизировать, свертывать. Можно также изменять его размеры с помощью мыши и наблюдать программу на панели задач.
#include <windows.h> // подключение библиотеки с функциями API
// Глобальные переменные:
HINSTANCE hInst; // Указатель приложения
– 13 –
// Предварительное описание функций
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// Основная программа
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
// Регистрация класса окна
MyRegisterClass(hInstance);
// Создание окна приложения
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// Цикл обработки сообщений
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
// FUNCTION: MyRegisterClass()
// Регистрирует класс окна
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW; // стиль окна
wcex.lpfnWndProc = (WNDPROC)WndProc; // оконная процедура
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // указатель приложения
wcex.hIcon = MyIcon1; // определение иконки
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // определение курсора
wcex.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); // установка фона
wcex.lpszMenuName = NULL; // определение меню
wcex.lpszClassName = "MyClass" ; // имя класса
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex); // регистрация класса окна
}
// FUNCTION: InitInstance(HANDLE, int)
// Создает окно приложения и сохраняет указатель приложения в переменной hInst
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
– 15 –
HWND hWnd;
hInst = hInstance; // сохраняет указатель приложения в переменной hInst
hWnd=CreateWindow( "MyClass" , // имя класса окна
"My first program" // имя приложения
WS_OVERLAPPEDWINDOW, // стиль окна
CW_USEDEFAULT, // положение по Х
CW_USEDEFAULT, // положение по Y
CW_USEDEFAULT, // размер по Х
CW_USEDEFAULT, // размер по Y
NULL, // описатель родительского окна
NULL, // описатель меню окна
hInstance, // указатель приложения
NULL); // параметры создания.
if (!hWnd) // Если окно не создалось, функция возвращает FALSE
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow); // Показать окно
UpdateWindow(hWnd); // Обновить окно
return TRUE; //Успешное завершение функции
}
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
// Оконная процедура. Принимает и обрабатывает все сообщения, приходящие в приложение
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rt;
switch (message)
{
case WM_CREATE: // Сообщение приходит при создании окна
break;
case WM_PAINT: // Перерисовать окно
hdc = BeginPaint(hWnd, &ps); // Начать графический вывод
GetClientRect(hWnd, &rt); // Область окна для рисования
DrawText(hdc, " Первая программа для WINDOWS ", -1, &rt,
DT_SINGLELINE|DT_CENTER | DT_VCENTER);
EndPaint(hWnd, &ps); // Закончить графический вывод
break;
case WM_DESTROY: // Завершение работы
PostQuitMessage(0);
break;
default:
// Обработка сообщений, которые не обработаны пользователем
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
– 17 –
ЛЕКЦИЯ 3. КОНТЕКСТ УСТРОЙСТВА
Дата добавления: 2016-11-22; просмотров: 837;