
- •Введение
- •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
- •Варианты заданий
- •Пример выполнения задания
Int ReleaseDc(hwnd hwnd, hdc hdc);
Тип HDC означает дескриптор контекста устройства. Функция ReleaseDC() возвращает ненулевое значение, если она завершилась успешно.
Текст на экран выводит функция, имеющая следующий прототип:
BOOL TextOut(HDC hdc, int x, int y, LPSTR lpstr, int nlength);
На экран выводится nlength символов строки, указатель на которую равен lpstr. Координаты задаются относительно начала рабочей области, а не экрана.
Обработка запроса на перерисовку окна. Если нажать кнопку минимизации окна, а затем вновь распахнуть окно, то символы, записанные в окне с помощью TextOut(), будут потеряны. Система Windows, как правило, не запоминает содержимое окна, но каждый раз, когда надо перерисовать окно, она посылает оконной функции сообщение WM_PAINT.
В некоторых случаях при перемещении и при изменении размеров окна система сохраняет и перерисовывает содержимое окна, но это не касается случая, когда окно минимизируется или перекрывается другим окном, а потом делается попытка восстановить его в исходное состояние. Для того чтобы обрабатывать сообщение WM_PAINT, добавим соответствующий этому сообщению случай в оператор switch функции окна:
case WM_PAINT:
hdc = BeginPaint(hwnd, &paintstruct); // получить DC
TextOut(hdc, 1, 1, str, strlen(str));
EndPaint(hwnd, &paintstruct); // освободить DC
break;
В данном случае применяются другие функции получения и освобождения контекста устройства. Они имеют дополнительный параметр, равный адресу структуры.
struct PAINTSTRUCT
{
HDC hdc; // дескриптор DC
BOOL fErase; // true, если перерисовывается заполнение окна
RECT rcPaint; // координаты области перерисовки
BOOL fRestore, fIncUpdate; // резерв
BYTE rgbReserved[32]; // резерв
}
Здесь тип RECT описывает структуру
struct RECT
{
LONG left, top, right, bottom;
}
Для обработки сообщения WM_PAINT добавим определение
PAINTSTRUCT paintstruct;
В результате получаем приведённую ниже оконную функцию:
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HDC hdc; // контекст устройства
PAINTSTRUCT paintstruct;
switch(message)
{
case WM_CHAR:
hdc = GetDC(hwnd); // получить контекст устройства
TextOut(hdc, 1, 1, “ “, 2); // стереть старый символ
sprintf(str, “%c”, (char)wParam); // записать в буфер новый символ
TextOut(hdc, 1, 1, str, strlen(str)); // вывести на экран
ReleaseDC(hwnd, hdc); // освободить контекст устройства
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &paintstruct); //получить DC
TextOut(hdc, 1, 1, str, strlen(str));
EndPaint(hwnd, &paintstruct); //освободить DC
break;
case WM_DESTROY:
PostQuitMessage(0); //сообщение о завершении
break;
default: //обработка остальных сообщений
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
В реальных программах обработка сообщения WM_PAINT может быть намного сложнее. Она выполняется одним из трех способов:
-
программа выводит при перерисовке информацию, полученную в результате некоторых вычислений;
-
последовательность событий запоминается и при необходимости воспроизводится вновь для перерисовки окна;
-
программа поддерживает виртуальный экран, который при перерисовке копируется в окно.
Обработка сообщений мыши. Рассмотрим наиболее часто употребляемые сообщения мыши WM_LBUTTONDOWN и WM_RBUTTONDOWN, которые поступают при нажатии соответственно левой и правой кнопок мыши. Для обработки этих сообщений в оконной функции добавим следующие строки:
case WM_RBUTTONDOWN: // нажата правая кнопка мыши
hdc = GetDC(hwnd); // получить DC
strcpy(str, “Нажата правая кнопка”);
TextOut(hdc, LOWORD(lParam), HIWORD(lParam), str, strlen(str));
ReleaseDC(hwnd, hdc); // освободить DC
break;
case WM_LBUTTONDOWN: // нажата левая кнопка мыши
hdc = GetDC(hwnd); // получить DC
strcpy(str, “Нажата левая кнопка”);
TextOut(hdc, LOWORD(lParam), HIWORD(lParam), str, strlen(str));
ReleaseDC(hwnd, hdc); // освободить DC
break;
При нажатии кнопки мыши координаты курсора x и y передаются в lParam. Поскольку текст в данном случае выводится, начиная с позиции (LOWORD(lParam), HIWORD(lParam)), то при нажатии кнопки мыши сообщение об этом будет выводиться в текущей позиции курсора.
Параметр wParam будет содержать информацию, определенную комбинацией флагов:
MK_CONTROL - в момент нажатия кнопки мыши была нажата клавиша [Ctrl];
MK_SHIFT - то же для клавиши SHIFT;
MK_LBUTTON - была нажата левая кнопка мыши;
MK_RBUTTON - была нажата правая кнопка мыши;
MK_MBUTTON - была нажата средняя кнопка мыши.
Генерация сообщения WM_PAINT. Программа имеет возможность вызвать генерацию и посылку операционной системой сообщения о запросе на перерисовку окна. Операционная система передаст это сообщение в удобное для себя время. Это позволяет эффективно использовать время центрального процессора.
Чтобы заставить Windows послать сообщение WM_PAINT, программа должна вызвать функцию
BOOL InvalidateRect(HWND hwnd, CONST RECT *lpRect, BOOL fErase);
где hwnd – дескриптор окна, которому должно быть адресовано сообщение WM_PAINT, lpRect – указатель на структуру RECT, задающую прямоугольную область в окне, которая должна быть перерисована. Если lpRect = NULL, то окно перерисовывается полностью. Если fErase не равен нулю, то вначале выполняется перерисовка заполнения, т.е. содержимое перерисовываемой области вначале стирается.
Для демонстрации способа генерации запроса о перерисовке модифицируем каркасную программу следующим образом:
добавим внешние переменные
char str[80] = “”;
int X = 1, Y = 1;
главная программа не изменяется;
перепишем оконную функцию таким образом, что вывод на экран производится с помощью обработки сообщения WM_PAINT. Выводится строка из буфера. При обработке других сообщений этот буфер заполняется и вызывается генерация сообщения WM_PAINT.
Ниже приведём текст модифицированной оконной функции.
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT paintstruct;
switch(message)
{
case WM_CHAR:
X = Y = 1; // выводим в левом верхнем углу
sprintf(str, “%c”, (char)wParam); // заполнить буфер
InvalidateRect(hwnd, NULL, 1); // генерация WM_PAINT
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &paintstruct); //получить DC
TextOut(hdc, X, Y, str, strlen(str)); // вывод
EndPaint(hwnd, &paintstruct); //освободить DC
break;
case WM_RBUTTONDOWN: // нажата правая кнопка мыши
hdc = GetDC(hwnd); // получить DC
strcpy(str, “Нажата правая кнопка”);
TextOut(hdc, LOWORD(lParam), HIWORD(lParam), str, strlen(str));
ReleaseDC(hwnd, hdc); // освободить DC
break;
case WM_LBUTTONDOWN: // нажата левая кнопка мыши
hdc = GetDC(hwnd); // получить DC
strcpy(str, “Нажата левая кнопка”);
TextOut(hdc, LOWORD(lParam), HIWORD(lParam), str, strlen(str));
ReleaseDC(hwnd, hdc); // освободить DC
break;
case WM_DESTROY:
PostQuitMessage(0); //сообщение о завершении
break;
default: //обработка остальных сообщений
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
Генерация сообщений таймера. Можно устанавливать таймер, который с заданной периодичностью будет посылать программе сообщение WM_TIMER. Для установки таймера применяется функция
UINT SetTimer(HWND hwnd, UINT nID, UINT wLength, TIMEPROC lpTFunc);
где hwnd – дескриптор окна, nID -идентификатор устанавливаемого таймера (можно использовать несколько таймеров), wLength – временной интервал в миллисекундах, lpTFunc – функция обработки сообщений таймера. Если TFunc = NULL, то для обработки сообщений таймера будет вызываться оконная функция. Для отключения таймера вызывается функция
BOOL KillTimer(HWND hwnd, UINT nID);
где nID – идентификатор таймера, а hwnd – дескриптор окна, использующего таймер.
Например, если в программе, демонстрирующей генерацию WM_PAINT, поставить после вызова функции ShowWindow(hwnd, nWinMode); вызов подпрограммы установки таймера:
SetTimer(hwnd, 1, 1000, NULL);
а после цикла обработки сообщений:
KillTimer(hwnd, 1);
то вывод окна, в котором показывается день недели, месяц, число, время и год, осуществляется с помощью оконной функции:
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT paintstruct;
struct tm *newtime;
time_t t;
switch(message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &paintstruct); //получить DC
TextOut(hdc, X, Y, str, strlen(str)); //вывод буфера
EndPaint(hwnd, &paintstruct); //освободить DC
break;
case WM_TIMER:
t = time(NULL);
newtime = localtime(&t); //получить текущее время
strcpy(str, asctime(newtime)); // запись в буфер
str[strlen(str)-1] = ‘\0’;
InvalidateRect(hwnd, NULL, 1);
break;
case WM_DESTROY:
PostQuitMessage(0); //сообщение о завершении
break;
default: //обработка остальных сообщений
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
Окна сообщений. Возможен вывод информации с ожиданием реакции пользователя. Это средство является самым простым элементом интерфейса и называется окном сообщения. Для создания этого элемента используется функция: