Системное программирование в среде Win32

Автор работы: Пользователь скрыл имя, 25 Марта 2014 в 14:49, лекция

Краткое описание

Конспект лекций содержит описание технологии системного программирования под Windows с использованием функций Win32 API. В первой части конспекта лекций рассмотрены особенности архитектуры ОС Windows, специфика интерфейса прикладного программирования Win32, структура приложений для Windows. Подробно рассмотрены API функции и основные структуры данных для работы с дисками, каталогами, файлами. Отдельная глава посвящена структурной обработке исключений SEH.

Прикрепленные файлы: 1 файл

Win32_лек_часть1.doc

— 811.00 Кб (Скачать документ)

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

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

 

Запуск и завершение цикла обработки сообщений

Стандартный цикл обработки сообщений имеет следующий вид:

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

{

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

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

Рассмотрим эту структуру сообщения.

 

typedef struct tagMSG { 

    HWND   hwnd; 

    UINT   message;

    WPARAM wParam;

    LPARAM lParam;

    DWORD  time;

    POINT  pt;

} MSG;

 

  1. хэндл окна, которому адресовано сообщение;
  2. номер сообщения. Каждое сообщение имеет свой идентификатор, начинающийся с WM.
  3. – 4) содержат параметры сообщения, для каждого сообщения различны;

5) время посылки сообщения;

6) позиция, на которой находился  курсор в момент выработки  сообщения (в экранных координатах).

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

GetMessage(&Msg, NULL, 0,0)

 

  1. указатель на структуру типа MSG, в которую будет записана информация о сообщении;
  2. хэндл окна, созданного программой. При этом будут выбираться сообщения, адресованные только этому окну. Если мы хотим обрабатывать сообщения для всех созданных программой окон, следует установить NULL.
  3. и 4) позволяют передавать оконной функции не все сообщения, а только те, номера которых попадают в определенный интервал. 3 – нижняя граница интервала, 4 – верхняя.

 

Эта функция всегда возвращает ненулевое значение, за исключением одного случая. Исключение составляет  сообщение WM_QUIT – при получении этого сообщения работа цикла, а следовательно, и программы прекращается.

Выбранное из очереди сообщение передается в функцию TranslateMessage(&Msg), которая преобразует сообщения в более удобный для обработки вид. Эта функция вызывает драйвер клавиатуры Windows  для преобразования  виртуальных кодов клавиш в ASCII – значения, которые ставятся в очередь программных событий в виде сообщения WM_CHAR. Это позволяет программе отличить, например, «А» от «а» без анализа состояния клавиши регистра.

Функция DispatchMessage(&Msg); берет данные о сообщении из структуры  Msg и передает  их в соответствующую оконную процедуру на обработку.

После того как сообщение передано, снова вызывается функция GetMessage, чтобы взять из очереди следующее сообщение. Каждое сообщение заставляет функцию GetMessage возвращать значение  true, за исключением  сообщения WM_QUIT.

 

Теперь пришло время поговорить о «получателе» сообщений – оконной процедуре (или функции окна).

 

Функция окна

В нашем примере функция окна предусматривает обработку только двух сообщений WM_PAINT и WM_DESTROY. Все остальные сообщения «протекают» сквозь функцию и передаются на обработку по умолчанию.

В функции окна описаны следующие переменные:

HDC hDC; - хэндл контекста устройства.

PAINTSTRUCT  PaintStruct;– адрес структуры, определяющей область перерисовки. Не всегда должно перерисовываться все окно полностью. К примеру, только часть окна перекрывается другим окном. Естественно, что и перерисовываться должна только часть окна. Windows «знает» о том, какая часть окна перекрыта. Среди всех полей структуры типа PaintStruct имеется поле, содержащее координаты той области (clipping region), которая должна быть перерисована.

RECT Rect – структура, определяющая прямоугольную область на экране, содержит координаты левого верхнего угла и правого нижнего угла этой области:

typedef struct _RECT {

    LONG left;

    LONG top;

    LONG right;

    LONG bottom;

} RECT;

 

Рассмотрим обработку сообщения WM_PAINT.

Первый шаг  - получение хэндла контекста устройства с помощью функции BeginPaint.

hDC=BeginPaint (hWnd, &PaintStruct);

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

Второй шаг – определение рабочей области окна.

GetClientRect(hWnd,&Rect);

Третий шаг – вывод надписи.

DrawText(hDC,"Hello!", -1, &Rect,

DT_SINGLELINE|DT_CENTER|DT_VCENTER);

Четвертый шаг – освобождение  контекста устройства:

EndPaint(hWnd, &PaintStruct);

 

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

Все остальные сообщения «протекают» сквозь оконную функцию и передаются с помощью функции DefWindowProc() на обработку по умолчанию.

 

Рассмотрим еще один пример, представляющий собой модификацию рассмотренного примера 1. Пусть вместо строки сообщения в окно выводится рисунок.

Пример 2.2.  Вывод в окно рисунка

#include  <windows.h>

 

LRESULT CALLBACK DCDemoWndProc (HWND, UINT, UINT, LONG);

 

int APIENTRY WinMain(HINSTANCE hInstance,

                     HINSTANCE hPrevInstance,

                     LPSTR     lpCmdLine,

                     int       nCmdShow)

{

  HWND hWnd;

WNDCLASS WndClass;

MSG Msg;

 

char szClassName[]="DCDemo";

 

// создадим  и зарегистрируем  класс окна

// Заполняем структуру типа WNDCLASS

WndClass.style=CS_HREDRAW|CS_VREDRAW;

WndClass.lpfnWndProc=DCDemoWndProc;

WndClass.cbClsExtra=0;

WndClass.cbWndExtra=0;

WndClass.hInstance=hInstance;

WndClass.hIcon=LoadIcon(NULL, IDI_APPLICATION);

WndClass.hCursor=LoadCursor(NULL, IDC_ARROW);

WndClass.hbrBackground=(HBRUSH) GetStockObject (WHITE_BRUSH);

WndClass.lpszMenuName=NULL;

WndClass.lpszClassName=szClassName;

 

//Регистрируем создаваемый класс

if (!RegisterClass(&WndClass))

{

MessageBox(NULL,"Невозможно зарегистрировать  класс", "Ошибка!!", MB_OK);

return 0;

}

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

hWnd=CreateWindow(szClassName, "Programm No2",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL);

 

if (!hWnd)

  {MessageBox(NULL,"Невозможно создать окно", "Ошибка!", MB_OK);

    return 0;

    }

// вывод окна

ShowWindow(hWnd, nCmdShow);

UpdateWindow (hWnd);

 

//Запуск цикла сообщений

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

{

     TranslateMessage(&Msg);

      DispatchMessage(&Msg);

   }

 

return Msg.wParam;

}

 

//Реализация оконной функции

LRESULT CALLBACK DCDemoWndProc (HWND hWnd, UINT  Message, UINT  wParam, LONG lParam)

{

HDC hDC, hCompatibleDC;

PAINTSTRUCT  PaintStruct;

HANDLE hBitmap, hOldBitmap;

RECT Rect;

BITMAP Bitmap;

 

switch (Message)

{case WM_PAINT:

//Получаем контекст устройства

hDC=BeginPaint (hWnd, &PaintStruct);

//Загружаем  bitmap, который будет  отображаться в окне, из файла

hBitmap=LoadImage(NULL, "Установка.bmp", IMAGE_BITMAP,

0,0, LR_LOADFROMFILE);

//Получаем размерность загруженного bitmap'a

GetObject(hBitmap, sizeof(BITMAP), &Bitmap);

//Создаем совместимый с контекстом  окна контекст в памяти

hCompatibleDC=CreateCompatibleDC(hDC);

//Делаем загруженный из файла bitmap текущим в совместимом контексте

hOldBitmap=SelectObject(hCompatibleDC, hBitmap);

//определяем размер рабочей  области окна

GetClientRect(hWnd,&Rect);

//Копируем bitmap с совместимого на  основной контекст с масштабированием

StretchBlt(hDC, 0,0, Rect.right, Rect.bottom, hCompatibleDC, 0,0,

Bitmap.bmWidth, Bitmap.bmHeight, SRCCOPY);

//вновь делаем старый bitmap текущим

SelectObject(hCompatibleDC, hBitmap);

 

//Удаляем загруженный с диска bitmap

DeleteObject (hBitmap);

//Удаляем совместимый контекст

DeleteDC(hCompatibleDC);

//Освобождаем основной контекст, завершая перерисовку рабочей области окна

//DrawText(hDC,"Hello, World!", -1,

//&Rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);

EndPaint(hWnd, &PaintStruct);

return 0;

case WM_DESTROY:

PostQuitMessage(0);

return 0;

    }

return DefWindowProc(hWnd, Message, wParam, lParam);

}

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

Рассмотрим обработку сообщения WM_PAINT:

  1. Получение хэндл контекста устройства, вызвав функцию

BeginPaint (hWnd, &PaintStruct);

аргументы: hWnd – хэндл окна, &PaintStruct – адрес структуры, определяющей область перерисовки. Не всегда должно перерисовываться все окно полностью. К примеру, только часть окна перекрывается другим окном. Естественно, что и перерисовываться должна только часть окна. Windows «знает» о том, какая часть окна перекрыта. При необходимости перерисовки (при вызове BeginPaint()) система заполняет структуру типа PaintStruct, адрес которой и передается в качестве второго параметра функции BeginPaint(). Среди всех полей структуры типа PaintStruct имеется поле, содержащее координаты той области (clipping region), которая должна быть перерисована.

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

LoadImage(NULL, "Установка.bmp", IMAGE_BITMAP, 0,0,

LR_LOADFROMFILE);

типы аргументов

HINSTANCE     hInst

LPCSTR        lpszName

UNIT

int

int

UNIT       fuLoad

 

Первый, второй и последний аргументы этой функции работают в связке. Первый - (hInst)- хэндл программы. Если вместо хэндла указать нуль, то объект является предопределенным, т.е. хранится в «глубинах» системы. В противном случае, объект загружается откуда-то снаружи. Второй – определяет загружаемый объект. Последний fuLoad содержит флаги, определяющие режим загрузки объекта. В нашем случае LR_LOADFROMFILE – загрузка из внешнего файла. От значения первого и последнего  аргументов зависит как будет интерпретирован второй аргумент. Взаимодействие этих трех аргументов объясняется в табл. 2.1.

Таблица 2.1

fuLoad (флаг LR_LOADFROMFILE)

hInst

lpszName

Не установлен

NULL

Идентификатор предопределенного объекта

Не установлен

не NULL

Имя ресурса

Установлен

NULL

Имя файла, в котором содержится  bitmap

Установлен

не NULL

Имя файла, в котором содержится  bitmap


 

Третий аргумент – тип образа,  он может принимать значения IMAGE_BITMAP, IMAGE_CURSOR, IMAGE_ICON и IMAGE_ENHMETAFILE.

Четвертый и пятый аргументы указывают ширину и высоту иконки или курсора , в нашем примере не используются.

Последний аргумент – флаги, определяющие параметры загрузки образа в память. Их много (более 10). Все они начинаются с LR. Краткое описание флагов приведено в табл. 2.2.

Таблица 2.2

Флаг

Значение

Эффект

LR_DEFAULTCOLOR

0x0000

загружаемый образ не монохромный

LR_MONOCHROME

0x0001

загружаемый образ черно-белый

LR_COLOR

0x0002

 

LR_COPYRETURNORG

0x0004

 

Окончание табл. 2.2. 

LR_COPYDELETEORG

0x0008

 

LR_LOADFROMFILE

0x0010

загружать образ из файла, а не из ресурсов

LR_LOADTRANSPARENT

0x0020

все пиксели, цвет которых совпадает с цветом пикселя, расположенного в левом верхнем углу bitmap’а, отображаются как прозрачные

LR_DEFAULTSIZE

0x0040

Использовать ширину и высоту образа, определенные в системных метриках для иконки или курсора, если cxDesired или cyDesired равны 0. Если этот флаг не установлен, cxDesired и/или cyDesired равны 0, используются размеры образа, указанные в ресурсе.

LR_LOADMAP3DCOLORS

0x1000

Заменяет оттенки серого в RGB на COLOR_3D

LR_CREATEDIBSECTION

0x2000

При загрузке bitmap’a возвращает оригинальные значения цветов, не преобразуя bitmap в совместимый с данным контекстом

LR_COPYFROMRESOURCE

   

LR_SHARED

0x8000

 

 

  1. Получение совместимого контекста в памяти

CreateCompatibleDC(hDC); hDC – хэндл контекста, для которого создается совместимый контекст.

  1. Вызов функции

SelectObject(hCompatibleDC, hBitmap). Первый аргумент указывает хэндл контекста, в котором замещается текущий элемент, второй аргумент – хэндл элемента, которым замещается текущий элемент. Эта функция возвращает хэндл замещаемого элемента (hOldBitmap), т.е. впоследствии с этим элементом могут также производиться манипуляции.

 

  1. Копирование bitmap’a (с масштабированием) с одного контекста на другой с помощью функции

StrechBlt (HDC, int,int,int,int, HDC, int, int, int, int,  DWORD);

Информация о работе Системное программирование в среде Win32