
- •Введение
- •1. Общие принципы создания интерфейса
- •1.1. Эргономические характеристики интерфейса
- •1.2. Составные части интерфейса
- •1.3. Виды диалога
- •1.4. Процессы ввода – вывода
- •1.5. Методы разработки подпрограмм нижнего уровня
- •Int int86(int num, union regs *inregs, union regs *outregs);
- •Void pokeb(unsigned seg, unsigned off, char value);
- •Int getch();
- •2. Исчезающее меню
- •2.1. Алгоритм создания исчезающего меню
- •2.2. Сохранение и восстановление экрана
- •2.3. Вывод меню и рамки
- •2.4. Определение выбора пользователя
- •2.5. Подпрограмма исчезающего меню
- •3. Иерархическое меню
- •3.1. Фреймы меню
- •3.2. Подпрограмма активизации меню
- •3.3. Организация иерархического меню
- •3.4. Всплывающие окна
- •Void window(int num);
- •Void deactivate(int num);
- •4. Графический интерфейс
- •4.1. Организация меню в графическом режиме
- •Void outtextxy ( int X, int y, char *s);
- •4.2. Организация графического диалога
- •4.3. Особенности графического режима
- •Void putpixel (int color, int X, int y)
- •4.4. Форматы хранения графических файлов
- •5. Прикладной интерфейс для windows
- •5.1. Приложения Windows
- •5.2. Каркас приложения
- •5.3. Обработка сообщений в системе Windows
- •Int ReleaseDc(hwnd hwnd, hdc hdc);
- •Int MessageBox(hwnd hwnd, lpcstr lpText, lpcstr lpCaption, uint wMbType);
- •Int response;
- •5.4. Меню в системе Windows
- •5.5. Диалоги в системе Windows
- •Int DialogBox(hinstance hThisInst,
- •5.6. Пример программы, использующей список и окно ввода
- •6. Лабораторная 1
- •Варианты заданий
- •Пример выполнения задания
- •7 Лабораторная 2
- •Варианты заданий
- •Пример выполнения задания
5. Прикладной интерфейс для windows
Данная глава посвящена программированию на языке С++ в операционной системе Windows. Операционная система Windows (NT/95/98/2000) ориентирована на многооконный интерфейс. После загрузки в память программа пользователя ожидает сообщения, посылаемого ей операционной системой Windows. Для приема сообщения программа запускает цикл обработки сообщений. В этом цикле сообщения выбираются из очереди сообщений для данной программы и направляются обратно к операционной системе Windows, которая вызывает оконную функцию, передавая ей эти сообщения в качестве параметров.
Программа получает доступ к ресурсам Windows, используя множество функций API (Application Program Interface – Программный Интерфейс Приложений). Поддержку независимого от графического оборудования обмена обеспечивает GDI (Graphics Device Interface – Интерфейс Графических Устройств), который является подмножеством API.
5.1. Приложения Windows
Поскольку Windows поддерживает 32 – разрядную адресацию, некоторые типы данных изменили свою размерность: типы int и unsigned стали 32 – битными, при объявлении указателей не требуется их определение как near или far (если такие определения встречаются, то они игнорируются).
Компоненты окна. Каждое окно имеет рамку, определяющую его границы. В верхнем левом углу находится иконка (пиктограмма) системного меню. Щелчок мыши на этой пиктограмме открывает системное меню. Справа от иконки находится заголовок окна. В правом верхнем углу – кнопки минимизации, полноэкранной развертки и закрытия окна. Действие программы отображается в рабочей области. Многие окна имеют горизонтальные и вертикальные линейки прокрутки.
Главная подпрограмма и оконные функции. Приложения, использующие API, начинают свое выполнение с вызова WinMain() вместо вызова main(). Подпрограмма WinMain() является главной и должна быть описана как WINAPI. Когда операционная система Windows посылает сообщения приложению, она вызывает оконные функции и сообщения передает через параметры этих функций. Все оконные функции должны объявляться как LRESULT CALLBACK.
5.2. Каркас приложения
Главная подпрограмма WinMain() должна выполнять следующие действия:
-
определить класс окна (заполнить поля фрейма);
зарегистрировать окно в системе Windows;
-
создать окно данного класса;
-
вывести окно на экран;
-
запустить цикл обработки сообщений.
Оконная функция WindowFunc() должна обрабатывать все сообщения, относящиеся к данному окну. В приведенном ниже примере обрабатывается лишь сообщение WM_DESTROY о закрытии окна. Фрейм окна определен структурой WNDCLASS wcl. Окно создается с помощью функции CreateWindow().
Добавлены типы данных:
HANDLE – число, идентифицирующее некоторый ресурс (32 бита),
HWND – 32 – разрядное целое число, используемое как дескриптор окна,
WORD – 16 – разрядное короткое целое без знака,
DWORD – длинное целое без знака,
UINT – 32 – разрядное беззнаковое целое,
BOOL – принимает значения 0 или 1, так называемый булевый тип,
BYTE – 8 – разрядное целое без знака,
LPSTR – указатель на строку,
LPCSTR – постояный указатель на строку.
Ниже приведём текст программы, реализующей каркас приложения:
#include <windows.h>
#include <string.h>
// 1. Набрать данный текст, вызвав bcw
// 2. Создать проект: File -> New -> Project
// (ввести имя, например karkas.ide вместо proj0001.ide)
// 3. Удалить *.def
// 4. Нажать [Ctrl]+ F9
#include<stdio.h>
LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);
char szwinname[] = "May Window";
int WINAPI WinMain(HINSTANCE hthisinst,
HINSTANCE hprevinst,
LPSTR lpszargs,
int nwinmode)
{
HWND hwnd; // дескриптор (заголовок) окна, т.е. номер,
// единственным образом идентифицирующий окно
MSG msg; // сообщение состоит из HWND окна,
// получающего сообщение, UINT (номер) сообщения
// LPARAM, WPARAM, DWORD time, POINT pt -позиция курсора
WNDCLASS wcl;
wcl.hInstance = hthisinst; // дескриптор данного приложения
wcl.lpszClassName = szwinname; // имя класса окна
wcl.lpfnWndProc= WindowFunc; // оконная функция
wcl.style = 0; // стиль по умолчанию
wcl.hIcon = LoadIcon (NULL, IDI_APPLICATION);//как exe - MSDOS
// IDI_ASTERISK - перевернутый воскл знак (информация)
// IDI_EXCLAMATION - внимание (воскл знак в желтом тр-ке)
// ID_HAND - знак стоп (два скрещенных отрезка в красном круге)
// IDI_QUESTION - вопрос в белом круге
wcl.hCursor = LoadCursor(NULL,IDC_ARROW); // курсор выводится как стрелка
// CROSS (+), IBEAM (верт черта), (WAIT) пес часы
wcl.lpszMenuName = NULL;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
// цвет окна белый
wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
if(!RegisterClass(&wcl)) // регистрация окна
return 0;
hwnd = CreateWindow(szwinname,
"KARKAS",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
HWND_DESKTOP,
NULL,hthisinst,
NULL);
ShowWindow(hwnd,nwinmode); // показать окно
UpdateWindow(hwnd); // перерисовать содержимое
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);// транслировать клавиши
// если убрать, то не будет реагировать на клавиши
DispatchMessage(&msg);// вернуть управление Windows
}
return msg.wParam;
}
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}
Обсудим приведённый выше текст программы.
Выполнение программы начинается с WinMain(), имеющей четыре параметра:
-
hthisinst – дескриптор текущего экземпляра приложения (в системе Windows могут работать несколько экземпляров одной и той же программы);
-
hprevinst – всегда равен NULL, в Windows 3.1 мог принимать ненулевые значения, если ранее были запущены другие экземпляры данного приложения;
-
lpszargs – указатель на строку, содержащую аргументы программы при ее запуске;
-
nwinmode – определяет способ визуализации окна при запуске программы.
Затем определяется и регистрируется класс окна, содержащий поля (классом называют фрейм):
UINT style; // тип окна
WNDPROC lpfnWndProc; // адрес оконной функции
int cbClsExtra; // дополнительные данные для класса
int cbWndExtra; // дополнительные данные для окна
HINSTANCE hInstance; // дескриптор экземпляра приложения
HICON hIcon; // дескриптор иконки
HCURSOR hCursor; // дескриптор курсора мыши
HBRUSH hbrBackground; // цвет заполнения окна
LPCSTR lpszMenuName; // имя главного меню
LPCSTR lpszClassName; // имя класса окна
В данном случае меню не требуется, и имя главного меню будет равно NULL.
Создание окна осуществляется с помощью функции
HWND CreateWindow(
LPCSTR lpClassName, // имя класса окна
LPCSTR lpWinName, // заголовок окна
DWORD dwStyle, // стиль окна
int x, int y, // координаты верхнего левого угла
int Width, int Height, // размеры окна
HWND hParent, // дескриптор родительского окна
HMENU hMenu, // дескриптор главного меню
HINSTANCE hThisInst, // дескриптор приложения
LPVOID lpszAdditional); // указатель на доп. информацию
В нашем случае для параметров x, y, Width, Height используется значение, заданное макросом CW_USEDEFAULT, позволяющее системе самостоятельно выбирать координаты и размеры окна. Если окно не имеет родительского окна, то hParent должен быть равен HWND_DESKTOP или NULL. Поскольку главного меню нет, то hMenu = NULL. Аналогично указатель на дополнительную информацию равен NULL.
Для стиля (или типа) создаваемого окна используется макрос WS_OVERLAPPEDWINDOW, определяющий стандартное окно, имеющее системное меню, заголовок, рамку для изменения размеров, а также кнопки минимизации, развертки и закрытия. Используется наиболее общий стиль. Можно создавать окна, имеющие другие стили. Для этого применяют комбинации стилевых макросов. Наиболее широко используются стили:
WS_OVERLAPPED - стандартное окно с рамкой,
WS_MAXIMIZEBOX - наличие кнопки развертки,
WS_MINIMIZEBOX - наличие кнопки минимизации,
WS_SYSMENU - наличие системного меню,
WS_HSCROLL - наличие горизонтальной панели прокрутки,
WS_VSCROLL - наличие вертикальной панели прокрутки.
Для отображения окна на экран используется функция
BOOL ShowWindow(HWND hwnd, int nHow);
параметры которой задают дескриптор окна (hwnd) и способ отображения nHow. Можно использовать следующие способы отображения:
SW_HIDE - скрыть окно,
SW_MAXIMIZE - развернуть окно до полноэкранного,
SW_MINIMIZE - свернуть окно до иконки,
SW_RESTORE - отобразить окно в нормальном представлении.
Вызов функции UpdateWindow() означает немедленную перерисовку окна, и Windows в этом случае направляет программе сообщение, указывающее на необходимость перерисовки.
Последней частью программы WinMain() является цикл обработки сообщений. Целью этого цикла является получение и обработка сообщений, передаваемых операционной системой. Эти сообщения ставятся в очередь сообщений приложения, откуда они потом выбираются функцией
BOOL GetMessage(LPMSG msg, HWND hwnd, UINT min, UINT max);
Выбираемые из очереди сообщения сохраняются по адресу msg, где находится структура:
struct MSG
{
HWND hwnd; // окно, для которого назначено сообщение
UINT message; // само сообщение
WPARAM wParam; // параметры
LPARAM lParam; // сообщения
DWORD time; // время посылки сообщения
POINT pt; // положение курсора мыши
}
Структура, определяющая координаты курсора мыши, описывается следующим образом
struct POINT
{
LONG x,y; // координаты
}
Параметр hwnd функции GetMessage() является дескриптором окна, для которого эта функция получает сообщения. Если требуется получать сообщения, адресованные всем окнам приложения, то hwnd должен быть равен NULL. Остальные два параметра определяют диапазон получаемых сообщений. Если они равны 0, то программа получает все сообщения. Подпрограмма GetMessage() возвращает 0, когда пользователь завершает работу.
Функция TranslateMessage() транслирует виртуальные коды клавиш, генерируемые системой Windows, в клавиатурные сообщения.
Когда сообщение получено и преобразовано, функция DispatchMessage() возвращает его обратно к Windows. Затем это сообщение будет передано системой Windows в оконную функцию приложения. В конце работы программа возвращает значение msg.wParam.
В нашем примере оконная функция имеет имя WindowsFunc(). Ее параметрами являются первые четыре поля структуры MSG. В нашем примере оконная функция обрабатывает единственное сообщение WM_DESTROY – завершить работу программы. Она обрабатывает его с помощью функции PostQuitMessage(), приводящей к передаче сообщения WM_QUIT приложению. Получив это сообщение, GetMessage() возвращает 0 и завершает тем самым цикл обработки сообщений.
Заметим, что при создании проекта приложения с помощью выбора опций File New Project и включения имени, например karkas.ide, требуется создать пустой файл karkas.def, или удалить его из списка файлов, используемых при компиляции.