Сделай Сам Свою Работу на 5

Тема: Общая структура Windows-приложения





Программирование Windows-приложений построено на работе с окнами и обработке сообщений, что накладывает на структуру программы определенные ограничения.

Любая программа под Windows состоит минимум из двух функций - WinMain() и оконной функции.
Функция WinMain() должна выполнять следующие операции:

1. Определять класс окна

2. Регистрировать класс окна

3. Поиск уже запущенной копии приложения

4. Создавать окно данного класса

5. Отображать окно

6. Запускать цикл обработки сообщений

Оконная функция предназначена для обработки сообщений, относящихся к данному окну

Исходный текст приложения, которое создает главное окно. При нажатии левой клавишей мыши в клиентской области окна при помощи стандартной диалоговой панели сообщений выдается информация о приложении.

// --- Обязательный включаемый файл

#include "stdafx.h"

// --- Прототип функции главного окна

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// --- Объявление глобальных переменных

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

char ClassName[]="Window"; // Название класса окна

char AppTitle[]="Application Win32"; // Заголовок главн окна

// --- Главная функция приложения WinMain



int APIENTRY _tWinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

WNDCLASS wc; // Структура для инф-ции о классе окна

HWND hWnd; // Дескриптор главного окна приложения

MSG msg; // Структура для хранения сообщения

// --- Проверяем, было ли приложение запущено ранее.

if((hWnd=FindWindow(ClassName, NULL))!=NULL)

{

// Если прилож. было запущено ранее, активизировать

// и выдвинуть на передний план его главное окно

if(IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE);

SetForegroundWindow(hWnd);

// Работа новой копии прекращается.

return FALSE;

}

// Заполнение полей стр-ры WNDCLASS

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

wc.lpszClassName=ClassName; // Имя класса окон

wc.lpfnWndProc=(WNDPROC)WndProc; //Адр. окон. ф-ции

wc.style=CS_HREDRAW|CS_VREDRAW; // Стиль класса окон

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

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);

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



hWnd=CreateWindow(

ClassName, // Имя класса окон

AppTitle, // Заголовок окна

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

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

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

CW_USEDEFAULT, // Ширина окна

CW_USEDEFAULT, // Высота окна

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

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

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

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

if(!hWnd)

{

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

MessageBox(NULL,"Window create error", AppTitle,

MB_OK|MB_ICONSTOP);

return FALSE;

}

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

ShowWindow(hWnd, nCmdShow);

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

UpdateWindow(hWnd);

// Запуск цикла обработки очереди сообщений.

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

{

// Преобразов. сообщ., получ с помощью клавиатуры

TranslateMessage(&msg);

// Отправление сообщения оконной функции

DispatchMessage(&msg);

}

return TRUE; // Завершение работы приложения

}

 

// --- Функция окна

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

// Нажата левая кнопка мыши в клиентской обл. окна.

case WM_LBUTTONDOWN:

{

// Вывод информации о приложении с помощью

// диалоговой панели сообщений MessageBox()

MessageBox(hWnd, "Win32 aplication", "Window",

MB_OK|MB_ICONINFORMATION);

}; break;

// Пользователь удалил окно.

case WM_DESTROY:

{

// Если это оконная функция главного окна, то следует

// в очередь сообщений послать сообщение WM_QUIT

PostQuitMessage(0);

}; break;

// Необработанные сообщ. передаются в стандартную

// функцию обработки сообщений по умолчанию.

default:

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

}

return 0l;

}

 


Пояснения к тексту программы

Главная функция приложения WinMain

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

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE

hPrevInstance, LPSTR lpCmdLine, int nCmdShow)



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

Назначение параметров функции WinMain:

· hInstance называется дескриптором экземпляра приложения. Это уникальное число, идентифицирующее программу, когда она запущена в Windows. Каждая копия одной и той же запущенной несколько раз программы имеет свое значение hInstance.

· hPrevInstance ранее использовался в Win16 и в Win32 всегда равен NULL.

· lpCmdLine является указателем на оканчивающуюся нулем строку, в которой содержаться параметры, переданные программе из командной строки.

· nCmdShow определяет, как приложение первоначально отображается на дисплее: пиктограммой (SW_SHOWMINNOACTIVE) или в виде открытого окна (SW_SHOWNORMAL).

 

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

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

HWND FindWindow(LPCTSTR lpClassName,

LPCTSTR lpWindowName);

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

· lpClassName – это указатель на текстовую строку, в которой задается имя класса искомого окна. На базе одного и того же класса может быть создано несколько окон.

· lpWindowName – это указатель на текстовую строку, содержащую искомый заголовок окна. Если же подойдет любое окно, то параметр lpWindowName имеет значение NULL.

В приведенном тексте функции WinMain, проверяется, было ли ранее приложение запущено и при положительном ответе выдвигается на передний план главное окно ранее запущенной копии с помощью функции SetForegroundWindow(hWnd);

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

 

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

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

ATOM RegisterClass(const WNDCLASS *lpwc);

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

 

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

Затем приложение должно создать само окно с помощью функции 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 знает, к какому окну применить функцию.

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

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

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

· dwStyle определяет стиль окна. (см. тему «Классы и стили окон»).

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

· hWndParent задает для создаваемого окна дескриптор его окна-родителя. Если окно является главным окном приложения, то этому параметру присваивается значение NULL.

· hMenu определяет для окна дескриптор меню. Значение NULL на месте дескриптора меню говорит о том, что у окна будет только меню класса, общее для всех окон этого класса.

· hInstance задает дескриптор экземпляра приложения, которое создает окно.

· lpParam используется для передачи окну дополнительных данных (если их нет, то он должен быть равен NULL).

 

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

Для отображения окна на экране используется функция:

BOOL ShowWindow(HWND hwnd, int nCmdShow);

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

· hwnd задает дескриптор окна.

· nCmdShow задает начальный вид окна на экране (для главного окна приложения используется величина, передаваемая в качестве параметра функции WinMain). Для всплывающих и дочерних окон nCmdShow задает, как окно первоначально отображается: пиктограммой (SW_SHOWMINNOACTIVE) или в виде открытого окна (SW_SHOWNORMAL)..

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

void UpdateWindow(HWND hwnd);

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

 

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

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

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

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

. . .

MSG msg;

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

{

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

TranslateMessage(&msg);

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

DispatchMessage(&msg);

}

. . .

Извлечение сообщений из очереди производится при помощи функции:

BOOL GetMessage(MSG FAR* lpmsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax);

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

· lpmsg является дальним указателем на структуру сообщения типа MSG (см. тему «Сообщения Windows. Типы сообщений»).

· hwnd определяет дескриптор окна – источника сообщений. Если задать этому аргументу NULL, то программа будет получать сообщения от всех окон, созданных программой.

· uMsgFilterMin и uMsgFilterMax позволяют задать диапазон значений для фильтрации сообщений, получаемых программой. Если на их месте задать 0, то программа будет получать все сообщения.

Если поле message сообщения msg, извлеченного из очереди сообщений, равно любому значению, кроме WM_QUIT, то функция GetMessage возвращает ненулевое значение. Если из очереди извлечено сообщение WM_QUIT, то GetMessage возвращает нуль, что прерывает цикл обработки сообщений.

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

LONG DispatchMessage(const MSG FAR* lpmsg);

Эта функция передает msg обратно в Windows, которая отправляет его для обработки соответствующей оконной процедуре.

Перед вызовом функции DispatchMessage помещена специальная функция, производящая преобразование кодов комбинаций некоторых клавиш в символьные сообщения:

BOOL TranslateMessage(const MSG FAR* lpmsg);

 

Завершение работы приложения

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

Однако после входа в цикл обработки очереди сообщений единственным способом завершить приложение является посылка в очередь приложения сообщения WM_QUIT. Сообщение помещается в очередь сообщений только функцией главного окна данного приложения вызовом функции PostQuitMessage.

 

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

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

Оконная функция всегда связана с определенным классом окна, который регистрируется при помощи функции RegisterClass. На основе одного и того же класса можно создать несколько окон.

Оконная функция определяется следующим образом:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg,

WPARAM wParam, LPARAM lParam);

Все четыре параметра оконной процедуры идентичны первым четырем полям структуры MSG.

Функция окна вызывается непосредственно Windows и не может вызываться приложением напрямую. В функции окна используется соглашение о связях языка Паскаль, поэтому объявление функции CALLBACK обязательно.

 

Обработка сообщений в оконной функции

Функция окна получает сообщение из двух источников: из цикла обработки сообщений и от Windows:

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

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

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

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

 

Удаление окна, сообщение WM_DESTROY

Сообщение WM_DESTROY показывает, что Windows находится в процессе ликвидации окна в ответ на полученную от пользователя команду (пользователь вызывает поступление этого сообщения, если нажмет мышью на пиктограмме “Close”, выберет пункт “Close” из системного меню или нажмет комбинацию клавиш Alt+F4).

Главное окно стандартно реагирует на это сообщение, вызывая функцию:

PostQuitMessage(0);

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

 








Не нашли, что искали? Воспользуйтесь поиском по сайту:



©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.