Автор работы: Пользователь скрыл имя, 25 Марта 2014 в 14:49, лекция
Конспект лекций содержит описание технологии системного программирования под Windows с использованием функций Win32 API. В первой части конспекта лекций рассмотрены особенности архитектуры ОС Windows, специфика интерфейса прикладного программирования Win32, структура приложений для Windows. Подробно рассмотрены API функции и основные структуры данных для работы с дисками, каталогами, файлами. Отдельная глава посвящена структурной обработке исключений SEH.
WM_CREATE.
Это сообщение окно получает после создания, но до отображения , точнее, до прорисовки рабочей области на экране.
При завершении программы поступают сообщения
WM_DESTROY и WM_QUIT.
При необходимости закрыть окно, Windows дает окну возможность «осмотреться» и провести процедуру деинициализации. В ходе закрытия окна (а окно – это не только прямоугольная область, видимая на экране, это – еще и совокупность структур данных в глубине системы) сразу после снятия его с отображения оконная функция получает сообщение WM_DESTROY, которое является сигналом произвести процедуру деинициализации. Получив это сообщение и произведя все необходимые действия, функция окна, как правило, вызывает функцию PostQuitMessage(), которая посылает окну сообщение WM_QUIT. Это сообщение, в свою очередь, попав в цикл обработки сообщений, вызывает его прекращение.
#include <windows.h>
LRESULT CALLBACK HelloWorldWndProc (HWND, UINT, UINT, LONG);
//прототип оконной функции
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,
int nCmdShow)
{
HWND hWnd; //дескриптор окна
WNDCLASS WndClass; //структура, содержащая набор
//ресурсов класса
MSG Msg; //структура, в которую помещается сообщение
//из очереди
char szClassName[]="HelloWorld";
// создадим и зарегистрируем класс окна
// Заполняем структуру типа WNDCLASS
WndClass.style=CS_HREDRAW|CS_
WndClass.lpfnWndProc=
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
WndClass.hInstance=hInstance;
WndClass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor=LoadCursor(
WndClass.hbrBackground=(
WndClass.lpszMenuName=NULL;
WndClass.lpszClassName=
//Регистрируем создаваемый
if (!RegisterClass(&WndClass))
{
MessageBox(NULL,"Невозможно
"Ошибка!!", MB_OK);
return 0;
}
//Создаем окно
hWnd=CreateWindow(szClassName, "Прог1",
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 HelloWorldWndProc (HWND hWnd,
UINT Message, UINT wParam, LONG lParam)
{
HDC hDC;
PAINTSTRUCT PaintStruct;
RECT Rect;
switch (Message)
{
case WM_PAINT:
hDC=BeginPaint (hWnd, &PaintStruct);
GetClientRect(hWnd,&Rect);
DrawText(hDC,"Hello!", -1, &Rect,
DT_SINGLELINE|DT_CENTER|DT_
EndPaint(hWnd, &PaintStruct);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, Message, wParam, lParam);
}
Примечание. Особенности реализации этой программы в разных средах:
При работе в Borland C++ Builder: следует выбрать в меню File команду New, в открывшемся диалоговом окне New Items на вкладке New выбрать пиктограмму Console Wizard. Появится диалоговое окно Console Wizard. В этом окне следует активизировать кнопку С++ в группе Source Type, остальные флажки не активизировать.
Появится заготовка:
#include <windows.h>
#pragma hdrstop
//----------------------------
#pragma argsused
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
return 0;
}
//----------------------------
При работе в Visual C++: следует выбрать в меню File команду New, в открывшемся диалоговом окне New на вкладке Projects выбрать в списке Win32 Application, в поле ввода Project Name задать имя приложения, выбрать папку для сохранения (Location), нажать кнопку ОК. В появившемся далее диалоговом окне Win32 Application активизировать кнопку Simple Win32 Application.
Появится заготовка:
#include "stdafx.h"
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
return 0;
}
Рассмотрим детально эту программу.
Сразу после входа в WinMain() необходимо создать класс окна и сообщить о нем системе. Класс создается и регистрируется функцией
RegisterClass(&WndClass)
Аргументом этой функции является указатель на структуру типа WndClass, в которой хранятся характеристики создаваемого класса. Поэтому перед регистрацией класса необходимо заполнить эту структуру. Для того чтобы заполнить эту структуру, необходимо знать тип и назначение каждого ее поля.
Структура WndClass описана в заголовочном файле winuser.h. Вот так выглядит описание этой структуры :
typedef struct {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HANDLE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS;
Назначение полей этой структуры и их значения в описанном нами классе:
1) UINT style - стиль класса окна. Стили окна описаны в winuser.h , наименования их начинаются с CS (Class Style). Для стиля окна отводится 16 бит, и только в одном из них 1. Т.е. эти стили используются как битовые флаги, поэтому с ними можно производить операции логического сложения и логического умножения для получения комбинированных стилей, возможные значения приведены в табл. П.2. В нашем примере определяется как
WndClass.style=CS_HREDRAW|CS_
Это значит, что рабочая область окна будет перерисовываться при изменении размеров окна (CS_HREDRAW – при изменении ширины; CS_VREDRAW – при изменении высоты)
2)WNDPROC lpfnWndProc; поле, хранящее указатель на оконную функцию. Имя функции окна – это обычное имя, определяемое разработчиком. В нашем примере – HelloWorldWndProc.
WndClass.lpfnWndProc=
3) - 4) int cbClsExtra; - количество дополнительных байт класса;
int cbWndExtra; - количество дополнительных байт окна.
Для каждого класса Windows создает в памяти структуру с характеристиками класса, другая структура создается для каждого окна. При создании этих структур может быть зарезервировано некоторое количество памяти для нужд программиста. Поля cbClsExtra и cbWndExtra указывают размер резервируемой памяти в структурах класса и окна соответственно (эти параметры используются редко).
В нашем примере эти параметры оставлены нулевыми
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
5) HANDLE hInstance; - дескриптор (хэндл) текущего приложения, т.е. классу окна сообщается хэндл программы.
WndClass.hInstance=hInstance;
6) HICON hIcon; указывает на имя пиктограммы (иконки), в которую превращается окно при минимизации. Ресурс иконки загружается функцией LoadIcon:
HICON LoadIcon(hInstance hInst, ILPCTSTR lpIconName)
Параметр lpIconName указывает на строку с именем загружаемой иконки, а hInst - дескриптор приложения, чей исполняемый код содержит загружаемый ресурс. Программист может использовать собственную иконку, которую сам разработал, а может применить одну из стандартных (предопределенных) иконок. В случае использования собственной иконки параметр hInst должен быть равным хэндлу программы (hInstance). Если используется предопределенная иконка, то параметр hInst равен NULL. Все идентификаторы предопределенных иконок начинаются с букв IDI (IDentificator Icon).
WndClass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
( в данном случае , другие возможные значения предопределенных иконок приведены в табл. П.3).
7) HCURSOR hCursor; задает вид курсора мыши при его прохождении над окном. Ресурс курсора загружается функцией LoadCursor:
HCURSOR LoadCursor(hInstance hInst, ILPCTSTR lpCursorName)
Параметры и действие этой функции аналогичны функции загрузки иконки (см. пункт 6).
WndClass.hCursor=LoadCursor(
Задан курсор в виде стандартной стрелки. Другие возможные значения предопределенных курсоров приведены в табл.П.4.
Функции загрузки иконки и курсора загружают ресурс, только если он не был загружен; иначе выбирают дескриптор загруженного ресурса.
8) HBRUSH hbrBackground; Определяет хэндл кисти, которой будет закрашен фон окна. Чаще всего используют значение системного цвета (см. табл. П.5). При использовании константы к ее значению нужно обязательно добавить 1, т.к. первое значение для них равно нулю, а ноль является недействительным значением для логического номера кисти. Кроме того, цвета необходимо привести к типу HBRUSH, иначе компилятор выдаст ошибку. Например,
WndClass.hbrBackground=(
В нашем примере:
WndClass.hbrBackground=(
GetStockObject - тип функции – HGDIOBJ
9) LPCTSTR lpszMenuName; хранит указатель на строку, содержащую имя меню окна, определенное в файле ресурсов. Если задать NULL (как в нашем примере), окна этого класса не имеют заданного по умолчанию меню.
WndClass.lpszMenuName=NULL;
10) LPCTSTR lpszClassName; хранит указатель на строку, содержащую имя создаваемого класса.
WndClass.lpszClassName=
Имя созданного нами в примере класса – HelloWorld. Переменная szClassName инициализируется при описании:
char szClassName[]="HelloWorld";
Итак, структура WndClass заполнена. Указатель на эту созданную структуру передается функции RegisterClass(). С вызовом этой функции данные о создаваемом нами классе становятся известны Windows (класс регистрируется), и с этого момента мы можем создавать окна (объекты этого класса).
Если зарегистрировать класс не удается, то выводится окно с сообщением об ошибке и программа завершается.
if (!RegisterClass(&WndClass))
{MessageBox(NULL,"Невозможно
"Ошибка!!", MB_OK);
return 0;}
В Win32 API существует множество предопределенных классов окон. При необходимости создания окна предопределенного класса регистрировать класс окна уже не нужно.
Следующий шаг – создание экземпляра окна с помощью функции CreateWindow.
Для создания окна вызывают функцию CreateWindow. Она создает окно и устанавливает начальные значения некоторых его параметров. Эта функция объявлена следующим образом:
HWND CreateWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HANDLE hInstance,
LPVOID lpParam);
Назначение аргументов вызова этой функции:
1) lpClassName указатель на строку с именем класса, к которому будет принадлежать окно. Этот класс может быть либо зарегистрированным функцией RegisterClass, либо определенным операционной системой.
2) lpWindowName – указатель на строку, содержащую имя окна, т.е. текст, который появится на строке заголовка окна. В нашем примере - "Прог1".
3) dwStyle - определяет стиль окна (не общие характеристики класса, а индивидуальные особенности данного окна). Для описания стиля окна используются символистические константы с префиксом WS_. Стиль включает в себя кнопки управления размером окна, наличие строки заголовка и иконки, характер границы. Под это поле отводится 32 бита. в файле winuser.h определены несколько десятков стилей окон. Эти значения используются как битовые флаги (табл. П.6).
Различают окна перекрывающиеся (overlapped), временные (pop-up) и дочерние (child). Перекрывающиеся окна чаще используются в качестве окон приложения. Они всегда имеют заголовок (title bar), рамку и рабочую область (client region), могут иметь меню, панель инструментов (tool bar), строку состояния (ststus bar), полосы прокрутки (scroll bar).
Временные окна используются для вывода сообщений пользователю и остаются на экране непродолжительное время.
Дочерние окна используются для создания органов управления. Базовый стиль этих окон описан константой WS_CHILD. Дочерние окна не имеют кнопок минимизации и максимизации окна, но всегда имеют окно- родителя. Они «прилипают» к поверхности родителя, перемещаются с ним и не могут выйти за пределы родительского окна.
Используемый стиль WS_OVERLAPPEDWINDOW является комбинацией стилей: заголовок, иконка системного меню, граница, кнопки закрытия, сворачивания и максимизации окна.
4)-7) CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
определяют положение окна на экране. Это отступы (в пикселях) левого верхнего угла окна от левого края экрана, от верхней границы экрана, высота и ширина окна.
8) Хэндл окна-родителя или окна-
9) Хэндл меню или идентификатор создаваемого дочернего окна. Меню перекрывающегося или временного окна можно задать тремя способами:
а) в классе окон указывают имя меню, и все окна этого класса могут пользоваться этим меню;
б) имя меню указывают как аргумент функции CreateWindow, и создаваемое окно будет пользоваться этим меню, игнорируя меню класса;
в) меню создают в процессе или после создания окна.
В первом и третьем случаях аргумент hMenu равен NULL.
10) Хэндл экземпляра программы, который мы запускаем, hInstance.
11) Данные, которые используются в некоторых случаях для создания окна. Как правило, в это поле записывается указатель на структуры с дополнительной информацией. В нашем случае - NULL. Используется редко.
Перед созданием окна функция CreateWindow посылает код сообщения WM_CREATE функции создаваемого окна. Затем она обрабатывает возвращаемое функцией окна значение. Если это значение равно 0, то функция CreateWindow создает окно и возвращает его дескриптор. Если значение равно –1, то окно не создается и функция CreateWindow возвращает NULL.
Итак, окно создано, т.е. созданы структуры, которые будут использоваться в течение всего периода существования окна. Но пока окна нет на экране. Для отображения окна используется функция ShowWindow( ).
Для отображения окна на экране необходимо вызвать функцию ShowWindow. Прототип этой функции:
BOOL ShowWindow(HWND hWnd, int nCmdShow);
Эта функция переводит окно hWnd в состояние, определяемое вторым параметром. При первом после запуска приложения вызове этой функции вторым аргументом можно передать значение формального параметра nCmdShow функции WinMain(). Лучше так всегда и делать. Иначе ограничатся некоторые возможности по управлению окном Win32. В последующих вызовах вторым аргументом нужно указать одну из констант, приведенных в табл. П.1.
Информация о работе Системное программирование в среде Win32