Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции -Процедурное программирование в Windows.doc
Скачиваний:
12
Добавлен:
13.09.2019
Размер:
742.91 Кб
Скачать

Вывод в рабочую область окна

При выводе текста или графики в рабочую область окна приложения необходимо учитывать следующие правила:

  • Экран - разделяемый ресурс, поэтому приложение «не знает» заранее размер пользовательской области.

  • Размер области не остается неизменным в процессе работы программы, поэтому для вывода в окно, если требуется знать размеры окна , их нужно определять при каждом выводе.

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

  • Если пользователь приложения минимизирует окно, а затем снова сохраняет окно , то приложение должно обновить изображение.

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

  • Если требуется перерисовать (обновить) окно немедленно, например, это требуется самому приложению при создании нового окна или при выводе изображения, то сообщение направляется не в очередь приложения, а непосредственно передается в функцию окна приложения. Для этого используется функция Update Window ().

Контекст устройства и область отрисовки.

«Общение» с устройствами: дисплеем, принтером, плоттером и другими устройствами вывода, осуществляется функциями GDI (Graphics Device Interface).

При работе с этими функциями приложение оперирует не с адресом видеопамяти или порта компьютера, а со стандартизованным описанием характеристик устройства - контекстом устройства (Device Context).

Контекст устройства - это структура данных, описывающая геометрические и др.

Контекст устройства - специальные параметры устройства.

Контекст устройства - создается и поддерживается Windows.

Контекст устройства - это «паспорт» рабочей области (окна, принтера и т.д.).

Контекст устройства - размещается в перемещаемом сегменте памяти, и функции GDI используют не физический адрес памяти, а дескриптор сегмента.

Обновление рабочей области возлагается на само приложение.

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

Сообщение wm_paint

Windows отслеживает координаты той части рабочей области, которая должна быть обновлена.

Для каждого окна Windows поддерживает «структуру отрисовки», в которой хранятся :

  1. внутренние данные;

  2. координаты измененной области.

Структура отрисовки PAINTSTRUCT описана в файле windows.h:

typed struct tag PAINTSTRUCT

{ HDC hDC; // копия контекста устройства;

BOOL fErase; // будет или нет перерисовываться фон;

RECT rcPaint; // область отрисовки - прямоугольник

BOOL fRestore;

BOOL fincUpdate; > резервируется Windows

BYTE rgbReserved [16];

} PAINTSTRUCT;

RECT rcPaint; // структурная переменная, задающая координаты области отрисовки

typedtf struct

{ rcPaint.left; // X - левого верхнего угла

rcPaint.right; // X - правого нижнего угла

rcPaint.top; // Y - верхнего левого угла

rcPaint.bottom // Y - нижнего правого угла

} RECT;

События, которые портят содержимое рабочей области окна, вызывают изменение координат такой области, а не само сообщение WM_PAINT.

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

Это означает, что сообщение от клавиатуры и мыши обладают большим приоритетом, чем сообщение WM_PAINT (перерисовать изображение).

Например, если пользователь мышью выбирает место, то это сообщение сразу помещается в очередь приложения, и отрабатывается, т.е. действия пользователя имеют наивысший приоритет.

Для вывода информации в рабочую область необходимо :

  • Создать запрос о создании контекста устройства;

  • Использовать операции вывода;

  • Освободить контекст устройства.

Получение контекста устройства зависит от того, какое сообщение обрабатывается.

Если обрабатывается сообщение WM_PAINT, то необходим и адрес структуры отрисовки PAINTSTRUCT. Для этого служит функция BeginPaint():

HDC DC = BeginPaint (hWnd, lpPaint);

где DC - адрес контекста устройства;

hWnd - дескриптор окна;

lpPaint - адрес переменной типа PAINTSTRUCT.

По окончании отрисовки от DC необходимо отказаться функцией:

EndPaint (hWnd, lpPaint);

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

Если приложение не отрабатывает сообщение WM_PAINT, то оно передается Windows функцией DefWindowProc() для стандартной обработки.

Если сообщение WM_PAINT для вывода в окно пользователя неудобно, например, необходимо реализовать свой алгоритм отрисовки, то можно создать свое сообщение, например, WM_DRAW. При этом для получения дескриптора устройства и освобождения дескриптора устройства следует использовать функции GetDC() и ReleaseDC();

HDC DC = GetDC (hWnd);

.

.

ReleaseDC (hWnd, DC);

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

О Р Г А Н Ы У П Р А В Л Е Н И Я

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

Взаимодействие между родительским окном (окно диалога) и органами управления осуществляется посредством сообщений. Когда пользователь производит какое-то действие с органом управления (нажимает кнопку «ОК», завершает ввод текста в окно-редактор и т.п.), функции окна-родителя передается сообщение WM_COMMAND. В этом сообщении параметр wParam содержит индекс органа управления как одной из составных частей окна диалога, а параметр lParam - специальную дополнительную информацию.

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

  1. Зарегистрировать класс окна.

  2. Создать дочернее окно функцией CreateWindow, указав зарегистрированный класс окна.

  3. В функцию окна органа управления определить дескриптор дочернего окна при помощи функции GetParent.

  4. По тому или иному действию пользователя «уведомлять» родительское окно соответствующими сообщениями при помощи функции SendMessage.

Для органов управления как дочерних окон не требуется регистрировать класс окна - в Windows определены стандартные классы окон - органов управления: «button», «edit», «scrollbar», «listbox» и пр. Эти классы, наряду с родительскими классами окон, рассмотренными ранее, образуют стандартную иерархию окон-объектов Windows, для стандартных органов управления определены также стандартные функции окон.

При использовании стандартных классов Windows процедура создания органа управления упрощается до одной строки: вызова функции CreateWindow с указанием стандартного класса. Стандартные органы управления посылают функции родительского окна стандартные сообщения Windows, определенные в файле windows.h. Для каждого класса органов управления определены свои сообщения, которыми они обмениваются с функцией родительского окна.

Рассмотрим классы органов управления, определенные в Microsoft Windows.

Кнопки и переключатели

К простейшим органам управления относятся кнопки и переключатели.

Кнопка («Button»)

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

Переключатели «И» («Check box»)

Используются как переключатели опций «Вкл/Выкл». Характерная их особенность состоит в том, что будучи объединенными в группу, они реализуют логику «И», т.е. на нескольких таких переключателях пользователь может установить любую комбинацию соответствующих опций. Переключатели этого типа могут быть также «трехпозиционными», где третьим состоянием является отключение возможности какого-либо выбора в данный момент.

Переключатели «ИЛИ» («Radio button»)

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

Вокруг этих трех основных типов имеется некоторое количество вариаций. Приведем краткое табличное описание стандартных классов кнопок и переключателей, определенных в Microsoft Windows:

BS_DEFPUSHBUTTON

Определяет кнопку с жирной рамкой. Этот класс кнопок обычно используется тогда, когда обозначаемое действие является действием по умолчанию (подразумевается). На кнопке может быть выведен любой текст.

BS_PUSHBUTTON

То же, что и BS_DEFPUSHBUTTON, однако, обозначаемое действие не является действием по умолчанию.

BS_CHECKBOX

Этот стиль определяет маленький квадратик, который может иметь два состояния: отмеченное («checked» - квадратик отмечен крестиком) и неотмеченное («unchecked» - квадратик пуст). В момент отметки рамка квадратика выделяется жирной линией.

BS_AUTOCHECKBOX

То же что и BS_CHECKBOX, однако, состояние кнопки при отметке отслеживается автоматически.

BS_RADIOBUTTON

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

BS_AUTORADIOBUTTON

То же что и BS_RADIOBUTTON, но при отметке кнопки пользователем ранее сделанная отметка автоматически снимается, и приложение получает сообщение BN_CLICKED.

BS_3STATE

То же что и BS_CHECKBOX, однако, орган управления имеет три состояния. Два первых (отмечен/не отмечен) остаются, а третье состояние (обозначаемое штриховкой кнопки) используется обычно для отображения того факта, что в настоящий момент обозначаемое кнопкой действие или свойство не действительно.

BS_AUTO3STATE

То же что и BS_3STATE, однако, смена состояний поддерживается автоматически.

BS_OWNERDRAW

Орган управления, определяемый пользователем. Функция родительского окна получает сообщения о действиях пользователя над органом управления. По этим сообщениям пользователь обязан отображать орган управления (при создании окна диалога), инвертировать его (в момент нажатия) и т.п.

BS_USERBUTTON

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

BS_GROUPBOX

Этот стиль определяет не орган управления, а стилевой элемент - автоматически отображаемую тонкую рамку, охватывающую другие органы управления. Тем самым пользователю дается понять, что объекты, расположенные внутри рамки, тесно связаны между собой (обычно это стили BS_CHECKBOX и BS_RADIOBUTTON). В правом верхнем углу рамки может располагаться поясняющий текст.

BS_LEFTTEXT

Этот флаг используется для выравнивания текста по левой стороне кнопок BS_RADIOBUTTON и BS_CHECKBOX. Используется только с этими стилями. В параметре lParam этого сообщения указывается дескриптор органа управления как дочернего окна и код нотификации, служащий для определения того, какое же собственно действие произвел пользователь с кнопкой, а в параметре wParam-идентификатор органа управления.

Перечислим стандартные коды нотификации Windows, определенные в файле windows.h:

BN_CLICKED 0

BN_PAINT 1

BN_HILITE 2

BN_UNHILITE 3

BN_DISABLE 4

BN_DOUBLECLICKED 5

Коды нотификации могут понадобиться только при работе с кнопками, определяемыми пользователем. При работе со стандартными кнопками используется только код BN_CLICKED и реже BN_DOUBLECLICKED.

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

Статические органы управления

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

Органы управления этого класса могут быть созданы указанием функции CreateWindow имени класса «static». Дочерние окна этого типа являются, наверное, самым простым типом окон Windows. Статические органы управления не обрабатывают ни клавиатуру, ни мышь и не посылают сообщение WM_COMMAND функции родительского окна.

Единственное сообщение, которое обрабатывает статические органы управления - это сообщение WM_HITTEST, возвращаемое обратно Windows с установленным параметром HTTRANSPARENT. Это заставляет Windows посылать то же самое сообщение функции нижнего окна, т.е. функции окна диалога, где оно благополучно перерабатывается в сообщение рабочей области так же, как если бы статического органа управления не было вовсе.

Используя стандартно определенные стили статических примитивов Windows, можно отображать системными цветами прямоугольники и рамки, выводить в окно диалога текст и даже пиктограммы:

Примитив

Определение

SS_BLACKRECT

SS_GRAYRECT

SS_WHITERECT

SS_BLACKFRAME

SS_GRAYFRAME

SS_WHITEFRAME

SS_CENTER

SS_LEFT

SS_RIGHT

SS_ICON

SS_SIMPLE

SS_USERITEM

Прямоугольник цвета рамки окна (COLOR_WINDOWFRAME)

Прямоугольник цвета фона окна (COLOR_BACKGROUND)

Прямоугольник цвета окна (COLOR_WINDOW)

Рамка цвета рамки окна (COLOR_WINDOWFRAME)

Рамка цвета фона окна (COLOR_BACKGROUND)

Рамка цвета окна (COLOR_WINDOW)

Центрированный текст

Текст, выравненный по левому краю

Текст, выравненный по правому краю

Пиктограмма; функции CreateWindow указывается имя загруженной пиктограммы, не имя файла пиктограммы. Установленная ширина и высота органа управления в этом случае игнорируется; пиктограмма автоматически масштабирует себя по осям

То же, что и SS_LEFT, но проще: так, используя этот стиль, нельзя обрабатывать сообщение WM_CTLCOLOR.

Статический орган управления, отрисовываемый пользователем

Редактируемые поля

Стандартный класс «edit» позволяет создать дочернее окно, внутри которого вы можете редактировать какой-либо текст. Когда фокус ввода принадлежит дочернему окну класса «edit» (редактору текста), вы можете набирать в окне текста, перемещать курсор по окну, выделять текст внутри окна при помощи клавиш Shift и клавиш перемещения курсора, перемещать выделенный текст из окна «в почтовый ящик» (clipboard) и обратно.

Используя класс окна «edit», можно создавать как многострочные редакторы текста (оконные редакторы), так и простейшие однострочные органы управления - строки редактирования.

Как и другие органы управления , редактор текста -это дочернее окно , поэтому первый идентификатор, который надо указать в параметре «тип окна » функции CreateWindow, должен быть WS_CHILD.

Текст, отображаемый в окне редактора, может быть выровнен по левой или правой границе окна или же отцентрирован. Для этого существуют следующие флаги типов окон: ES_LEFT,ES_RIGHT, ES_CENTER.

По умолчанию редактор текста может редактировать только одну строку, и если вы хотите создать многострочный редактор, то надо использовать тип ES_MULTILINE. Чтобы иметь возможность горизонтального перемещения текста в окне, добавьте тип ES_AUTOHSCROLL.В многострочном редакторе можно использовать вертикальное перемещение текста.

Для этого существует тип окна ES_AUTOVSCROLL. По умолчанию редактор текста не имеет рамки, и чтобы не отобразить, используют тип окна WS_BORDER.

Перечислим основные типы органов управления - редактора:

ES_AUTOHSCROLL

Этот стиль вызывает автоматически горизонтальный скроллинг вправо на 10 позиций, если курсор находиться в конце строки. По нажатии клавиши ENTER осуществляется обратный скроллинг на позицию 0.

ES_AUTOVSCROLL

При нажатии клавиши ENTER в конце страницы текст автоматически сдвигается вверх на один экран.

ES_CENTER

Текст автоматически центрируется.

ES_LEFT

Выравнивание текста по левому краю (подбор).

ES_LOWERCASE

Все символы автоматически переводятся в нижний регистр (строчные).

ES_MULTILINE

Этот стиль определяет многострочный редактор текста( по умолчанию определяется простейшая строка ввода). Если указан флаг ES_AUTOVSCROLL , то в окне показывается максимально возможное количество символов, и при нажатии клавиши ENTER в конце страницы текст перемещается на один экран вверх. Если флаг ES_AUTOVSCROLL не указан, то осуществляется автоматический горизонтальный скроллинг на 10 позиций, если курсор находиться в конце строки. По нажатии клавиши ENTER осуществляется обратный скроллинг на позиции 0 (начало новой строки). Если флаг ES_AUTOHSCROLL не указан то осуществляется автоматический перенос на новую строку: при нажатии ENTER, однако, так же начинается новая строка . Граница переноса зависти от ширины окна: если окно изменяет свои размеры, текст как бы «переформатируется». Многострочные редакторы могут иметь полосы просмотра; их сообщения обрабатываются автоматически. Если у многострочного редактора нет полос прокрутки, то он обрабатывает все сообщения о прокрутке, поступающие от родительского окна.

ES_NOHIDESEL

По умолчанию окно-редактор убирает выделения при потере фокуса ввода и возвращает его при возврате фокуса ввода. Флаг ES_NOHIDESEL отменяет это свойство.

ES_OEMCONVERT

Вводимый в окно текст сначала преобразуется из таблицы ANSI в таблицу OEM, затем обратно, после чего отображается на экране. Это гарантирует правильный перевод из одной таблицы в другую, например, при указании строки редактирования имени файла DOS.

ES_PASSWORD

Этот стиль предназначен для ввода паролей и кодов: вводимые символы отображаются в виде звездочки (*). Можно отображать и другой символ, для чего следует послать Windows сообщения ЕM_SETPASSWORDCHAR.

ES_RIGHT

Выравнивание текста по правому краю.

ES_UPPERCASE

Все символы автоматически переводятся в верхний регистр(прописные).

Сообщения класса «edit»

Редактор текста передает функции родительского окна сообщение WM_COMMAND. В параметре сообщения описаны ниже:

Параметр

Описание

wParam

LOWORD (lParam)

HIWORD (lParam)

Идентификатор дочернего окна

Индекс дочернего окна

Код сообщения

Различные коды сообщений приведены в следующей таблице:

Код сообщения

Описание

EN_CHANGE

EN_VSCROLL

EN_HSCROLL

EN_SETFOCUS

EN_KILLFOCUS

EN_ERRSPACE

Содержимое редактора текста изменено

Нажата полоса вертикального просмотра

Нажата полоса горизонтального просмотра

Редактору текста передали фокус ввода

Редактор текста потерял фокус ввода

Произошло переполнение буфера редактора текста

Код сообщения EN_ERRSPACE означает, что редактору текста не хватает отведенной для него памяти . Заметим, что содержимое редактора текста ограниченно 32 килобайтами.

Редактор текста - довольно сложный объект; программа общается с ним как и с другими органами управления, посредством сообщения . Если надо удалить , скопировать или переместить в «почтовый ящик» выделенный в настоящий момент времени участок текста, то можно предать окно редактора текста сообщение WM_CLEAR,WM_COPY,WM_CUT соответственно:

Send Message (hEditWnd,WM_CLEAR,0,0L);

Send Message ( hEditWnd, WM_COPY,0,0L);

Send Message (hEditWnd, WM_CUT,0,OL);

Текст из «почтового ящика» можно вставить в текст внутри окна редактора в месте нахождения курсора:

SendMessage (hEditWnd, EM_GETSEL,0,0L);

Выделить текст внутри окна редактора может либо пользователь при помощи клавиши Shift и клавиш перемещения курсора, либо само приложение, передав окну редактора сообщение EM_SETSEL с параметром lParam, содержащим начальную и конечную позицию выделяемого текста:

SendMessage (hEditWid,EM_SETSEL, 0,MAKELONG(wBegin,wEnd));

У многострочного редактора текста можно определить число строк:

nCount=SendMessage(hEditWnd,EM_ GETLINECOUNT,0,0L);

Полосы прокрутки

При создании органа управления - полосы прокрутки вручную как дочернее окно функции CreateWindow следует указать стандартный класс «scrollbar» и один из двух типов SBS_VERT(вертикальная полоса прокрутки) или SBS_HORS (горизонтальная полоса прокрутки).При обработке действий пользователя все полосы прокрутки передают функции родительского окна не сообщение WM_COMMAND, как все другие органы управления, а сообщения WM_VSCROLL или WM_HSCROLL. Сообщения от полосы просмотра в виде дочернего окна отличаются от сообщений, предаваемых полосами просмотра окна значением старшего слова параметра lParam;

Тип полосы просмотра HIWORD (lParam)

Полоса просмотра окна 0

Орган управления- полоса

просмотра в виде дочернего окна Индекс дочернего окна

Параметр wParam, содержит одну из следующих величин, определенных в файле windows.h:

Величина Действие

SB_BOTTOM Прокрутка до нижнего правого угла

SB_ENDSCROLL Прокрутка до конца

SB_LINEDOWN Прокрутка на строку вниз

SB_LINEUP Прокрутка на строку вверх

SB_PAGEDOWN Прокрутка на страницу вниз

SB_PAGEUP Прокрутка на страницу вверх

SB_THUMBPOSITION Прокрутка по абсолютной позиции.

Текущая позиция находится в

младшем байте параметра

Заметим, что полосы просмотра окна имеют постоянную (стандартную) ширину. Узнать ширину полосы просмотра можно при помощи функции GetSystemMetrics:

nWidth=GetSystemMetrics(SM_CYHSCROLL);

Определение ширины горизонтальной полосы просмотра окна:

Width=GetSystemMetrics(SM_CXVSCROLL);

Установить границы перемещения указателя полосы просмотра в виде дочернего окна вам поможет функция SetScrollRange:

SetScrollRange(hWnd,SB_STL,nMin, nMax,bRedraw);

Параметр hWnd содержит индекс дочернего окна , параметры nMin и nMax определяют границы изменения положения указателя полосы просмотра, а bRedraw определяет ,надо ли перерисовывать полосу просмотра. Если параметр bRedraw равен FALSE, то полосам просмотра не перерисовывается.

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

SetScrollPos(hWnd,SB_STL,nPos,bRedraw);

Параметр nPos функции определяет позицию, в которую устанавливается указатель.

Автоматическая обработка клавиатуры

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

Клавиша Значение параметра wParam

сообщения полосы просмотра

Home SB_TOP

End SB_BOTTOM

Page Up SB_PAGEUP

Page Down SB_PAGEDOWN

Left, Up SB_LINEUP

Right, Down SB_LINEDOWN

Если необходимо, чтобы полоса прокрутки автоматически получала фокус ввода при выборе ее мышью, необходимо при создании ее как дочернего окна указать флаг WS_TABSTOP. В этом случае, когда полоса просмотра будет иметь фокус ввода, ее движок будет слегка мигать, обозначая фокус.

В приведенной выше программе фокус ввода устанавливается в нужное место весьма просто, при помощи функции SetFocus:

SetFocus( hChScroll[nFocus]);