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

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

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

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

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

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

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

WM_CREATE.

Это сообщение окно получает после создания, но до отображения , точнее, до прорисовки рабочей области на экране.

 

При завершении программы поступают сообщения

WM_DESTROY и WM_QUIT.

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

 

Пример 2.1. Программа, формирующая окно и строку сообщения в нем

#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_VREDRAW;

WndClass.lpfnWndProc=HelloWorldWndProc;

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, "Прог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_VCENTER);

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;

}

Рассмотрим детально эту программу.

2.4. Класс окон

Сразу после входа в WinMain() необходимо создать класс окна и сообщить о нем системе. Класс создается и регистрируется функцией

RegisterClass(&WndClass)

Аргументом этой функции является указатель на структуру типа 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_VREDRAW;

Это значит, что рабочая область окна будет перерисовываться при изменении размеров окна (CS_HREDRAW – при изменении ширины; CS_VREDRAW – при изменении высоты)

 

2)WNDPROC lpfnWndProc; поле, хранящее указатель на оконную  функцию. Имя  функции окна –  это обычное имя, определяемое разработчиком. В нашем примере – HelloWorldWndProc.

WndClass.lpfnWndProc=HelloWorldWndProc;

 

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(NULL, IDC_ARROW);

Задан курсор в виде стандартной стрелки. Другие возможные значения предопределенных курсоров приведены в табл.П.4.

Функции загрузки иконки и курсора загружают ресурс, только если он не был загружен; иначе выбирают дескриптор загруженного ресурса.

 

8) HBRUSH hbrBackground; Определяет хэндл кисти, которой будет закрашен фон окна. Чаще всего используют значение системного цвета (см. табл. П.5). При использовании константы к ее значению нужно обязательно добавить 1, т.к. первое значение для них равно нулю, а ноль является недействительным значением для логического номера кисти. Кроме того, цвета необходимо привести к типу HBRUSH, иначе компилятор выдаст ошибку. Например,

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

В нашем примере:

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

GetStockObject - тип функции – HGDIOBJ

 

9) LPCTSTR lpszMenuName; хранит указатель на строку, содержащую имя меню окна, определенное в файле ресурсов. Если задать NULL (как в нашем примере), окна этого класса не имеют заданного по умолчанию меню.

WndClass.lpszMenuName=NULL;

 

10) LPCTSTR lpszClassName; хранит указатель на строку, содержащую имя создаваемого класса.

WndClass.lpszClassName=szClassName;

 

Имя созданного нами в примере класса – HelloWorld. Переменная szClassName инициализируется при описании:

char szClassName[]="HelloWorld";

 

Итак, структура  WndClass заполнена. Указатель на эту созданную структуру передается  функции RegisterClass(). С вызовом этой функции данные о создаваемом нами классе становятся известны Windows (класс регистрируется), и с этого момента мы можем создавать окна (объекты этого класса).

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

if (!RegisterClass(&WndClass))

{MessageBox(NULL,"Невозможно зарегистрировать класс",

"Ошибка!!", MB_OK);

return 0;}

 

В Win32 API существует множество предопределенных классов окон. При необходимости создания окна предопределенного класса регистрировать класс окна уже не нужно.

 

Следующий шаг – создание экземпляра окна с помощью функции CreateWindow.

 

Функция создания окна 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) Хэндл окна-родителя или окна-владельца. Дескриптор окна-родителя обязательно указывают при создании дочернего окна. Дескриптор окна-владельца для временного окна указывать необязательно. Наше окно не является дочерним, поэтому  параметр равен   NULL.

 

9) Хэндл меню или идентификатор  создаваемого дочернего окна.  Меню перекрывающегося или временного окна можно задать тремя способами:

а) в классе окон указывают имя меню, и все окна этого класса могут пользоваться этим меню;

б) имя меню указывают как аргумент функции CreateWindow, и создаваемое окно будет пользоваться этим меню, игнорируя меню класса;

в) меню создают в процессе или после создания окна.

В первом и третьем случаях аргумент hMenu равен NULL.

 

10) Хэндл экземпляра программы, который мы запускаем,  hInstance.

 

11) Данные, которые используются в некоторых случаях для создания окна. Как правило, в это поле записывается указатель на структуры с дополнительной информацией. В нашем случае - NULL. Используется редко.

 

Перед созданием окна функция CreateWindow посылает код сообщения  WM_CREATE функции создаваемого окна. Затем она обрабатывает возвращаемое функцией окна значение. Если это значение равно 0, то функция CreateWindow создает окно и возвращает его дескриптор. Если значение равно –1, то окно не создается и функция CreateWindow  возвращает NULL.

 

Итак, окно создано, т.е. созданы структуры, которые будут использоваться в течение всего периода существования окна. Но пока окна нет на экране. Для отображения окна используется функция ShowWindow( ).

Функции ShowWindow() и UpdateWindow

Для отображения окна на экране необходимо вызвать функцию ShowWindow. Прототип этой функции:

BOOL ShowWindow(HWND hWnd, int nCmdShow);

Эта функция переводит окно hWnd в состояние, определяемое вторым параметром. При первом после запуска приложения вызове этой функции вторым аргументом можно передать значение формального параметра nCmdShow функции WinMain(). Лучше так всегда и делать. Иначе ограничатся некоторые возможности по управлению окном Win32. В последующих вызовах вторым аргументом  нужно указать одну из констант, приведенных в табл. П.1.

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