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

Ректор университета

__________А.В. Лагерев

“__”________ 2005 г.

 

ПРОГРАММИРОВАНИЕ ПОД WINDOWS

ОКОННОЕ ПРИЛОЖЕНИЕ

С ИСПОЛЬЗОВАНИЕМ WinAPI 32

 

 

Методические указания к выполнению

Лабораторной работы № 1

для студентов дневной формы обучения
специальности 230105 «Программное обеспечение ВТ и АС»

 

 


Брянск 2005


УДК 004.4

 

 

Программирование под Windows. Оконное приложение с использованием WinAPI 32: методические указания к выполнению лабораторной работы № 1 для студентов дневной формы обучения специальности 230105 «Программное обеспечение ВТ и АС». - Брянск: БГТУ, 2005- 26с.

 

Разработал:

Е.А.Белов

ст. преп.

 

 

Рекомендовано кафедрой «Информатика и программное обеспечение» БГТУ (протокол №4 от 06.12.04)

 


 



ЦЕЛЬ РАБОТЫ

Изучить простейшее оконное приложения Windows, разработанное с использованием WinAPI 32. В результате выполнения работы студент должен знать структуру приложения, конструкции и функции составляющие простейшее оконное приложение, представлять процессы, лежащие в основе его работы.

Продолжительность работы - 2 часа.

ТЕОРЕТИЧЕСКАЯ ЧАСТЬ

Точка входа в программу

При запуске приложения в Windows операционная система вызывает в программе функцию WinMain. В любом приложении обязательно должна присутствовать эта функция, на которую возлагается ряд специфических задач. И самая важная из них – создание основного окна программы, с которым должен быть связан код, способный обрабатывать сообщения, передаваемые операционной системой этому окну.

Существенное различие между консольной и Windows-программами в том, что первая для получения данных, введенных пользователем, вызывает операционную систему, а вторая делает это через сообщения, передаваемые программе операционной системой.

Точкой входа программы для Windows является функция WinMain, которая всегда определяется следующим образом:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

Эта функция использует последовательность вызовов WINAPI (паскалевское соглашение о передаче аргументов при вызове функций) и по завершению, возвращает операционной системе Windows целое число.

Параметры функции WinMain:

  • Параметр hInstance называется дескриптором экземпляра приложения. Дескриптор экземпляра приложения - это уникальное число, идентифицирующее программу, когда она работает под Windows. Каждая копия одной и той же запущенной несколько раз программы называется “экземпляром” и у каждой свое значение hInstance.
  • Параметр hPrevInstance в настоящее время устарел и в Win32 всегда равен NULL.
  • Параметр lpCmdLine является указателем на оканчивающуюся нулем строку, в которой содержатся параметры, переданные программе из командной строки.
  • Параметр nCmdShow определяет, как приложение первоначально отображается на дисплее: пиктограммой (nCmdShow = SW_SHOWMINNOACTIVE) или в виде открытого окна (nCmdShow = SW_SHOWNORMAL).

Действия, обычно выполняемые функцией WinMain:

Если найдена работающая копия приложения, то работа новой копии прекращается.

Иначе:

§ сохранение дескриптора экземпляра приложения в глобальной переменной;

§ регистрация класса окна приложения и другие инициализации;

§ создание главного окна приложения и, возможно, других, подчиненных окон;

§ отображение созданного окна и отрисовка содержимого его внутренней части;

§ запуск цикла обработки сообщений, помещаемых в очередь приложения;

§ завершение работы приложения при извлечении из очереди сообщения WM_QUIT.

 

Поиск работающей копии приложения

Для проверки того, было ли приложение запущено ранее, можно воспользоваться функцией FindWindow, которая позволяет найти окно верхнего уровня по имени класса или по заголовку окна:

       HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName);

Через параметр lpClassName передается указатель на текстовую строку, в которую необходимо записать имя класса искомого окна. На базе одного и того же класса может быть создано несколько окон. Если необходимо найти окно с заданным заголовком, то имя заголовка следует передать через параметр lpWindowName. Если же подойдет любое окно, то параметр lpWindowName может иметь значение NULL.

Фрагмент кода функции WinMain, проверяющий, было ли ранее приложение запущено, и при положительном ответе выдвигающий на передний план главное окно ранее запущенной копии:

      ...

       HWND hWndOld=FindWindow(ClassName, NULL);

       if(hWndOld)

       {

                   if(IsIconic(hWndOld))

                    ShowWindow(hWndOld, SW_RESTORE);

                   SetForegroundWindow(hWndOld);

                   return FALSE;

       }

       // Работающая копия не найдена - функция WinMain приступает

       // к инициализации приложения и запуску цикла обработки сообщений

      ...

Если необходимо, чтобы каждая копия приложения работала как отдельный процесс, то приведенный фрагмент кода следует не включать в функцию WinMain.

 

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

Как уже говорилось, самая важная задача функции WinMain – создание основного окна программы, с которым должен быть связан код, способный обрабатывать сообщения, передаваемые операционной системой этому окну.

Обычно приложение создает окно за два шага. Сначала с помощью функции RegisterClass регистрируется класс окна, а затем создается само окно зарегистрированного класса с помощью функции CreateWindow.

Класс окна определяет общее поведение нового типа окон, включая адрес новой оконной процедуры. Такие второстепенные аспекты как размер, расположение и внешний вид окна определяются при его создании.

Новый класс окна регистрируется при вызове приложением следующей функции:

       ATOM RegisterClass(const WNDCLASS *lpwc);

Единственный параметр этой функции lpwc указывает на структуру типа WNDCLASS, описывающую тип нового окна. Возвращаемое значение является атомом Windows – 16-разрядным значением, идентифицирующим уникальную символьную строку в таблице Windows.

Фрагмент кода функции WinMain, в котором заполняются поля структуры, описывающей класс окна, регистрируется класса окна:

      ...

       // Сохраняем дескриптор экземпляра приложения в

       // глобальной переменной hInst типа HINSTANCE, чтобы

       // при необходимости воспользоваться им в функции окна.

       hInst=hInstance;

// Заполнение структуры WNDCLASS для регистрации класса окна.

       WNDCLASS wc;

       memset(&wc, 0, sizeof(wc));       // Очистка полей структуры

       wc.lpszClassName="MyWindowClassName";

       // Имя класса окон - строка

       wc.lpfnWndProc=(WNDPROC)WndProc;

       // Адрес оконной функции

       wc.style=CS_HREDRAW|CS_VREDRAW;

       // Стиль класса окон

       wc.hInstance=hInst;                      // Экземпляр приложения

       wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);           

       // Пиктограмма для окон

       wc.hCursor=LoadCursor(NULL,IDC_ARROW);              

       // Курсор мыши для окон

       wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);  // Кисть для окон

       wc.lpszMenuName=NULL;                     // Ресурс меню окон

       wc.cbClsExtra=0;                          // Дополнительная память

       wc.cbWndExtra=0;                       // Дополнительная память

 

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

       RegisterClass(&wc);

      ...

 

Поля структуры WNDCLASS

Название нового регистрируемого класса окон задается при помощи параметра-строки lpszClassName.

Наиболее важными параметрами структуры WNDCLASS являются style и lpfnWndProc. Основная часть того, что представляет окно как уникальную и сложную сущность, управляется через стиль класса окна и оконную процедуру.

Параметр lpfnWndProc указывает адрес функции оконной процедуры. Эта функция отвечает за обработку всех сообщений, получаемых окном. Она может обрабатывать эти сообщения сама или вызывать оконную процедуру по умолчанию DefWindowProc.

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

Некоторые глобальные характеристики окна управляются через параметр стиля окна – style. Для этого параметра можно установить комбинацию значений, используя операцию поразрядного ИЛИ. Например, значение CS_DBLCLKS указывает Windows генерировать события о двойном щелчке кнопкой мыши. Значения CS_HREDRAW и CS_VREDRAW указывают, что окно должно перерисовываться полностью каждый раз при изменении горизонтального или вертикального размера.

Менее важные для функционирования окна поля структуры WNDCLASS:

  • поле hIcon – дескриптор пиктограммы, используемой для представления минимизированных окон этого класса;
  • поле hCursor – дескриптор стандартного указателя мыши для окон этого класса;
  • hbrBackground – дескриптор кисти интерфейса GDI, используемой для рисования фона окна;
  • строка lpszMenuName определяет ресурс меню (по имени или с помощью макроса MAKEINTRESOURCE по целому идентификатору), который используется для стандартного меню этого класса;
  • параметры cbClsExtra и cbWndExtra используются, чтобы выделить дополнительную память для класса окна и для отдельных окон, через них задается размер этой дополнительной памяти. Приложения могут использовать эту дополнительную память для хранения специальной информации приложения, относящейся к классу окна или к отдельным окнам.

 

Создание окна

Регистрация нового класса является первым шагом в создании окна. Затем приложение должно создать само окно с помощью функции CreateWindow, которая возвращает дескриптор созданного окна типа HWND:

HWND CreateWindow(LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight,

HWND hWndParent, HMENU hMenu, HANDLE hInstance, LPVOID *lpParam);

У каждого окна в Windows имеется уникальный дескриптор типа HWND. Дескриптор окна – это один из важнейших описателей, которыми оперирует программа для Windows. Для многих функций Windows требуется дескриптор окна, благодаря которому Windows знает, к какому окну применить функцию.

Фрагмент кода функции WinMain, в котором создается окно зарегистрированного ранее класса с именем "MyWindowClassName":

      ...

       // Создаем главное окно приложения.

       HWND hWndMain=CreateWindow(

                   "MyWindowClassName",            // Имя класса окон

                   "MyWindowTitle",                 // Заголовок окна

                   WS_OVERLAPPEDWINDOW, // Стиль окна

                   CW_USEDEFAULT,CW_USEDEFAULT,

                   // X- и Y-координаты

                   CW_USEDEFAULT,CW_USEDEFAULT,           

                   // Ширина и высота окна

                   NULL, // Дескриптор окна-родителя

                   NULL, // Дескриптор меню окна

                   hInst,          // Дескриптор экземпляра приложения

                   NULL);      // Дополнительная информация

                   if(!hWndMain)

                   {

                   // Окно не создано, выдаем предупреждение.

          MessageBox(NULL,

          "Create: error","MyTitle",MB_OK|MB_ICONSTOP);

                   return FALSE;

                   }

      ...

 

Параметры функции CreateWindow

Первый параметр lpClassName указывает имя класса, поведение которого наследует данное окно. Этот класс должен быть зарегистрирован с помощью фунцкии RegisterClass или быть одним из предопределенных классов элементов управления. Эти переопределенные классы включают в себя стандартные классы элементов управления с именами “button”, “combobox”, “listbox”, “edit”, “scrollbar” и “static”.

Параметр lpWindowName определяет строку, которая выводится в заголовке создаваемого окна.

Параметр dwStyle определяет стиль окна. Не следует путать стиль окна со стилем класса, передаваемым в RegisterClass через структуру WNDCLASS.

Хотя стиль класса определяет некоторые постоянные свойства окон, принадлежащих классу, стиль окна, передаваемый CreateWindow, используется для инициализации локальных свойств окна.

Как и в случае стиля класса, стиль окна также обычно является комбинацией значений (объединенных операцией поразрядного ИЛИ).

        Для определения стиля главного окна чаще всего используют стиль перекрывающегося окна, для чего через параметр dwStyle передают символическую константу WS_OVERLAPPEDWINDOW, определенную во включаемых файлах следующим образом:

       #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED| \

                   WS_CAPTION|WS_SYSMENU|WS_THICKFRAME| \

                   WS_MINIMIZEBOX|WS_MAXIMIZEBOX)

После указания типа окна нужно задать начальные геометрические размеры окна. Если при задании параметров x, y, nWidth и nHeight использовать константу CW_USEDEFAULT, то Windows установит расположение и размеры окна самостоятельно.

При создании окна указываются также дескрипторы его окна-родителя и меню. Если окно является главным окном приложения, то параметру hWndParent присваивается значение NULL. Значение NULL на месте дескриптора меню hMenu говорит о том, что у окна будет только меню класса, общее для всех окон этого класса.

При создании окна необходимо указать, какой экземпляр приложения, которое создает окно, что и делается при помощи параметра hInstance.

Последний параметр lpParam используется для передачи окну дополнительных данных (если их нет, то он должен быть равен NULL). При необходимости этот параметр используется в качестве указателя на какие-нибудь данные, на которые программа в дальнейшем могла бы ссылаться.

 

Отображение окна

Хотя функция CreateWindow и создает окно, это не значит, что оно будет автоматически отображаться на экране дисплея. Для отображения окна следует воспользоваться функцией ShowWindow. Первым параметром в эту функцию передается дескриптор окна, вторым параметром обычно (для главного окна приложения) является величина, передаваемая в качестве параметра функции WinMain, она задает начальный вид окна на экране.

       BOOL ShowWindow (HWND hwnd, int nCmdShow);

Функция ShowWindow выводит окно на экран. Если второй параметр этой функции имеет значение SW_SHOWNORMAL, то фон рабочей области окна закрашивается той кистью, которая задана в классе окна.

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

       void UpdateWindow(HWND hwnd);

Функция UpdateWindow передает функции окна сообщение WM_PAINT. Получив это сообщение, функция обновляет содержимое экрана.

Фрагмент кода функции WinMain, в котором отображается созданное окно и рисуется содержимое его внутренней части:

      ...

       ShowWindow(hWnd, nCmdShow);       // Отображаем окно.

       UpdateWindow(hWnd);

       // Обновляем его содержимое клиентской области окна

      ...

Функции отображения и обновления вызываются, как правило, после создания окна, но, порядок и место вызова функций ShowWindow и UpdateWindow не является обязательным. Окно может быть отображено не в момент создания, а позже, по желанию программиста.

Итак, для отображения окна в типичном приложении необходимо:

- зарегистрировать класс окна функцией RegisterClass;

- создать окно функцией CreateWindow;

- отобразить окно функцией ShowWindow;

- обновить рабочую (клиентскую) область окна функцией UpdateWindow.

 

Цикл обработки очереди сообщений

После создания и отображения окна функция WinMain должна подготовить приложение к получению информации от пользователя через клавиатуру и мышь.

Windows поддерживает очередь сообщений (message queue) для каждой программы, работающей в данный момент в системе. Когда происходит ввод информации, Windows преобразовывает ее в сообщение, которое помещается в очередь сообщений приложения.

Программа извлекает сообщения из очереди сообщений, выполняя блок команд, известный как цикл обработки сообщений (message loop). Простейший цикл обработки сообщений имеет следующий вид:

      ...

       MSG msg;

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

       {

              TranslateMessage(&msg);

       //преобразование клавиатурных сообщениий в символьные

                   DispatchMessage(&msg);

                   // отправка сообщения окну-адресату приложения

       }

      ...

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: