Опубликован: 10.03.2009 | Доступ: свободный | Студентов: 2295 / 280 | Оценка: 4.31 / 4.07 | Длительность: 09:23:00
Лекция 1:

Программирование под Windows с использованием Win API

Лекция 1: 123 || Лекция 2 >

Регистрация класса окна

Каждое окно, которое создается в рамках приложения Windows, должно основываться на классе окна – шаблоне, в котором определены выбранные пользователем стили, шрифты, заголовки и т.д. Для всех определений класса окна используется стандартный тип структуры. Таким образом, сначала определяется структура WNDCLASS w, а затем поля структуры заполняются информацией о классе окна. У этой структуры много полей, но большинство из них можно определить нулем. В программе это делается строкой memset(&w,0,sizeof(WNDCLASS)) ;

Рассмотрим следующий фрагмент программы:

w.style = CS_HREDRAW | CS_VREDRAW;
  w.lpfnWndProc = WndProc;
  w.hInstance = hInstance;
  w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  w.lpszClassName = "My Class";
  RegisterClass(&w);

В этом фрагменте определяется стиль класса (все идентификаторы стилей начинаются с префикса CS_ ). В программе значения поля стиля задаются константами. CS_HREDRAW ¬– обеспечивает перерисовку содержимого клиентской области окна при изменении размера окна по горизонтали, CS_VREDRAW – обеспечивает перерисовку содержимого клиентской области окна при изменении размера окна по вертикали.

w.lpfnWndProc = WndProc - значение указателя на функцию окна ( WndProc ), которая выполняет все задачи, связанные с окном.

w.hInstance = hInstance - определяется экземпляр приложения, регистрирующий класс окна.

w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH) - определяется кисть, используемая для закраски фона окна.

w.lpszClassName = "My Class" - указатель на строку символов, заканчивающуюся на 0, которая определяет имя класса. Класс здесь – это не класс в смысле ООП (объектно-ориентированного программирования). Термин один, но смысла два. Исторически классы окон возникли раньше, чем классы ООП.

RegisterClass(&w) - регистрация происходит при помощи вызова функции RegisterClass().

Создание окна на основе класса окна

hwnd = CreateWindow("My Class","Окно пользователя", WS_OVERLAPPEDWINDOW,500,300,500,380,NULL,NULL,hInstance,NULL);

Первый параметр функции служит для задания класса окна. Второй – это заголовок окна. Третий – определяет стиль окна (обычное перекрывающее окно с заголовком, кнопкой вызова системного меню, кнопками минимизации и максимизации и рамкой). Следующие шесть параметров определяют положение окна на экране (по оси X и по оси Y), размеры окна по оси X и по оси Y, идентификатор родительского окна и идентификатор меню окна. Следующее поле ( hInstance ) содержит идентификатор экземпляра программы, далее следует информация об отсутствии дополнительных параметров ( NULL ). Если создание окна прошло успешно, то функция CreateWindow(...) возвращает идентификатор созданного окна, в противном случае – NULL. После того как окно создано, его надо показать и обновить. Для того чтобы вывести главное окно приложения на экран, необходимо вызвать функцию Windows ShowWindow(...).

ShowWindow(hwnd,nCmdShow) выводит окно на экран. Параметр hwnd содержит идентификатор окна, созданного при вызове CreateWindow(...). Второй параметр определяет, как окно выводится в первый момент.

Последний шаг при выводе окна на экран заключается в вызове функции Windows UpdateWindow(hwnd) , которая приводит к перерисовке клиентской области окна.

Создание цикла обработки сообщений

Теперь программа готова выполнять свою главную задачу – обрабатывать сообщения. Используется стандартный цикл С/С++ цикл while:

while(GetMessage(&msg,NULL,0,0))
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

Использование функции GetMessage

Вызов этой функции позволяет получить для обработки следующее сообщение из очереди сообщений приложения. Данная функция копирует сообщение в структуру сообщения, на которую указывает указатель msg, и передает его в основной блок программы. Если значение следующего параметра NULL, то будут поступать сообщения, относящиеся к любому окну приложения. Значения последних параметров (0,0) указывает функции, что не надо применять никаких фильтров сообщений. Фильтры могут применяться для распределения получаемых сообщений по категориям, например, нажатия на клавишу или перемещение мыши. После входа в цикл обработки сообщений, выйти из него можно, получив только одно сообщение: WM_QUIT. Когда обрабатывается сообщение WM_QUIT, то возвращается значение "ложь" и цикл обработки сообщений завершается.

Использование функции TranslateMessage

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

Использование функции DispatchMessage

Функция DispatchMessage(...) используется для распределения текущего сообщения соответствующей функции окна.

Оконная функция WndProc

Вторая часть в любой программе под Windows – это оконная процедура. В рассматриваемом примере она маленькая (так как программа ничего не делает), но, именно эта часть и является самой главной и интересной в приложении.

Рассмотрим функцию WndProc:

LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
  switch (Message)
  {
    case WM_DESTROY: PostQuitMessage(0); break;
    default: return DefWindowProc(hwnd, Message, wparam, lparam);
  }
  return 0;
}

Основное назначение оконной функции – это обработка сообщений Windows. Каждое приложение получает много сообщений. Их источник может быть разным. Например, сообщения от пользователя или от самой Windows. Обработка этих сообщений происходит именно в оконной функции. Это означает, что для каждого сообщения необходимо написать свой обработчик. Если обработчика не будет, то приложение не будет обращать внимание на сообщение. У оконной функции четыре параметра. Первый из них hwnd типа HWND задает окно, которое будет обрабатывать сообщение. Второй UINT Message – это передаваемое сообщение. Два последних WPARAM wparam, LPARAM lparam задают дополнительные параметры для передаваемого сообщения. Они для каждого сообщения свои. Оконная процедура отправляет сообщение в switch, который в примере имеет только один case:

switch (Message)
{
  case WM_DESTROY:
  ...

То есть, пока рассматриваемая программа обращает внимание только на сообщение WM_DESTROY. Это сообщение окно получает только при своем уничтожении. После принятия этого сообщения необходимо вызвать функцию PostQuitMessage(...). В ответ на сообщение WM_DESTROY необходимо поместить в очередь сообщение WM_QUIT. Это и делает функция PostQuitMessage(...), посылая это сообщение в очередь и говоря, что процесс должен быть завершен. Если мы хотим, чтобы наша программа реагировала еще на что-нибудь, то надо написать еще case.

Рассмотрим далее ветку default. В ней идет вызов функции DefWindowProc(hwnd, Message, wparam, lparam) . Основное предназначение этой функции – обработка сообщений Windows, которые не обрабатываются в нашей программе (то есть, для которых нет своего case ). При этом ничего не делается, но очередь из сообщений идет.

Лекция 1: 123 || Лекция 2 >