Окт 14 2009

Сообщения полос прокрутки

Windows посылает оконной процедуре асинхронные сообщения WM_VSCROLL и WM_HSCROLL, когда пользователь щелкает мышью на различных зонах вертикальной или горизонтальной полосы прокрутки либо перемещает движок.
Когда оконная процедура получает эти сообщения, параметр wParam содержит в своем младшем слове некоторый код, по которому можно узнать, какое событие произошло. Возможным значениям кода соответствуют определенные идентификаторы, начинающиеся с префикса SB_.
С каждым действием мыши связаны как минимум два сообщения. Одно сообщение создается при нажатии кнопки мыши, а второе — когда пользователь отпускает ее. Оконная процедура приложения может получить множество сообщений с кодами SB_LINEUP и SB_PAGEUP, если кнопка мыши остается нажатой в соответствующей позиции полосы прокрутки. Сообщение с кодом SB_ENDSCROLL показывает, что кнопка мыши отпущена. Как правило, сообщения SB_ENDSCROLL можно игнорировать.
При перемещении движка (thumb) мышью система вырабатывает серию сообщений с кодом SB_THUMBTRACK. Если младшее слово параметра wParam имеет значение SBJTHUMBTRACK или SB_THUMBPOSITION, то старшее слово параметра wParam определяет текущее положение полосы прокрутки. Во всех остальных случаях старшее слово параметра wParam можно не учитывать. Также можно игнорировать параметр IParam, который обычно используется для полос прокрутки, создаваемых в окнах диалога.
Напомним, что функция UpdateWindow вызывает передачу сообщения WM_PAINT непосредственно оконной процедуре. Это важно, если вы хотите обеспечить немедленную реакцию приложения на действия пользователя, когда тот быстро перемещает движок полосы прокрутки (сообщение SB_THUMBTRACK). Дело в том, что при обычном порядке обработки функция InvalidateRect вызывает постановку сообщения WM_PAINT в очередь приложения, а там это сообщение обрабатывается с самым низким приоритетом.
Наконец, в блоке обработки сообщения WM_PAINT вы должны предусмотреть код для вывода той части текстового документа, которая определяется текущим положением вертикального и горизонтального движков.


Окт 14 2009

Параметры полосы прокрутки

Каждая полоса прокрутки характеризуется несколькими параметрами: Диапазон (range), задаваемый двумя целыми числами, отражающими минимальное (nMin) и максимальное (пМах) значения в «единицах данных» проблемной области. При выводе текста «единицами данных» для вертикального измерения обычно считают строки текста, а в горизонтальном измерении1 — отдельные символы. Величина range определяется по формуле range = пМах - nMin + 1.
Положение (position) — целое число внутри диапазона, отражающее положение движка. Когда движок находится в крайней верхней или крайней левой позиции на полосе прокрутки, то его положение соответствует минимальному значению диапазона. Крайнее нижнее или крайнее правое положение движка соответствует максимальному значению диапазона.
Размер страницы (page) — целое число, отображающее количество «единиц данных», которые могут разместиться в клиентской области окна при его текущих размерах. Windows использует размер страницы и диапазон полосы прокрутки для управления длиной движка. При этом длина движка выглядит пропорционально той части документа, которую пользователь видит в окне. Кроме того, если указан размер страницы, то система берет на себя управление видимостпью полосы прокрутки при изменении размеров окна. Как только размер страницы становится больше диапазона, полоса прокрутки становится невидимой и недоступной.
По умолчанию для полосы прокрутки установлен диапазон от 0 до 100. Но вы можете переопределить этот диапазон. Так, если отображаемый документ содержит nLine строк, то можно использовать два варианта определения диапазона. В первом случае для границ диапазона задаются значения nMin = 0 и пМах = = nLine - 1. Во втором случае задаются nMin = 1 и пМах = nLine. Первый вариант считается более предпочтительным, так как он согласуется с индексацией элементов в массиве, а отображаемый текст часто хранится в виде массива строк. Для установки диапазона полосы прокрутки, размера страницы и текущего положения движка предназначена функция SetScrollInfo:
int SetScrollInfcKHWND hwnd, int fnBar, LPCSCROLLINFO Ipsi, BOOL fRedraw); Параметр hwnd содержит либо дескриптор окна, если функция применяется для стандартных полос прокрутки, либо дескриптор элемента управления Scroll Bar. Интерпретация зависит от значения второго параметра — fnBar.
Параметр fnBar определяет тип полосы прокрутки. Он может принимать значения SB_VERT (стандартная вертикальная полоса), SB_H0RZ (стандартная горизонтальная полоса) и SB_CTL (элемент управления Scroll Bar). Параметр Ipsi содержит указатель на структуру SCR0LLINF0, которая будет рассматриваться ниже.
Параметр b Redraw определяет, должна ли система перерисовать полосу прокрутки сразу после выполнения функции SetScrollInfo.
Поле fMask задает параметры, которые будут устанавливаться функцией SetScrollInfo или возвращаться функцией GetScrollInfo. Значением этого поля может быть комбинация флагов, перечисленных в табл. 2.33.
Для получения информации о текущих значениях параметров полосы прокрутки приложение может воспользоваться функцией GetScrollInfo.
Важно понимать, что если в программе используются полосы прокрутки, то вместе с Windows вы берете на себя ответственность за их поддержку и обновление положения движка. Так, Windows отвечает за следующие аспекты:
управление логикой работы мыши с полосой прокрутки;
обеспечение временной инверсии цвета при щелчке кнопкой мыши в зоне прокрутки на одну страницу;
перемещение движка, когда пользователь захватывает его мышью и передвигает по полосе;
отправка сообщений полосы прокрутки в оконную процедуру;


Окт 14 2009

Полосы прокрутки и вывод текста

При выводе текста может возникнуть ситуация, когда в клиентской области окна недостаточно места для его размещения. Например, длина строк может оказаться больше ширины окна, а количество строк слишком большим, чтобы поместиться в окне с данной высотой. Полосы прокрутки {scroll bars) являются самым удобным решением этой проблемы. Они просты в использовании и обеспечивают удобный просмотр информации.
Следует различать два вида полос прокрутки: полоса прокрутки окна; полоса прокрутки — элемент управления типа Scroll bar.
Второй вид полос прокрутки рассматривается в главе 7.
Полосы прокрутки окна, называемые также стандартными полосами прокрутки, размещаются вдоль правой и нижней рамок окна, как показано на рис. 2.35. Чтобы они появились, достаточно при вызове функции CreateWindow указать флаги WS_VSCROLL (вертикальная прокрутка) и WS_HSCROLL (горизонтальная прокрутка) в параметре dwStyle. Вертикальная полоса прокрутки позволяет пользователю просматривать информацию в окне, прокручивая ее вниз или вверх. Горизонтальная полоса прокрутки позволяет перемещать информацию вправо или влево. Терминология полос прокрутки, связанная с направлениями прокрутки, ориентирована на пользователя. Фактически программа перемещает документ в окне в противоположном направлении.
На рисунке поясняется также рекомендуемое использование вертикальной полосы прокрутки для просмотра текста. Текущее положение информации в окне относительно документа в целом отображается положением движка (thumb). Кроме щелчков мышью в указанных местах пользователь может также при помощи мыши переместить движок в любое необходимое положение. Использование горизонтальной полосы прокрутки осуществляется аналогичным образом.
Следует помнить, что, когда у окна появляются полосы прокрутки, клиентская область окна не включает в себя пространство, занятое полосами прокрутки.
Windows обеспечивает всю логику работы мыши с полосами прокрутки. Однако у полос прокрутки нет интерфейса клавиатуры. Если необходимо дублировать некоторые функции полос прокрутки клавишами управления курсором, то следует реализовать эту логику самостоятельно.


Окт 14 2009

Нетривиальный вывод текста

В современных текстовых редакторах и других графических пакетах решаются
различные нетривиальные задачи вывода текста. Неполный перечень таких задач
приведен в следующем списке:
Управление кернингом (контекстная регулировка межсимвольных расстояний).
Закраска текста кистью.
Работа с текстом в растровом формате.
Применение траекторий GDI при выводе текста.
Эти вопросы не рассматриваются в книге, так как это привело бы к неоправданному увеличению объема издания. Достаточно подробно они освещаются в книге.


Окт 14 2009

Абзацное форматирование в прямоугольнике

В пользовательском интерфейсе Windows часто требуется вывести длинный текст в прямоугольнике, способном вместить несколько строк. Или, напротив, короткий текст поместить в прямоугольнике с учетом заданного позиционирования. Для решения подобных проблем Win32 GDI предоставляет функции DrawText и DrawTextEx.
Так же как и другие функции вывода текста, функция DrawText принимает в качестве параметров указатель на символьную строку и длину строки. Однако функция ведет себя более интеллектуально по отношению к строкам с завершающим нулевым символом. Вы можете передать значение -1 на месте параметра nCount, и функция сама определит длину строки. Если же строка не имеет завершающего нулевого символа, то благоразумнее будет указать ее длину в аргументе nCount.
Функция DrawText выводит текстовую строку в прямоугольной области, заданной параметром IpRect. Последний параметр, uFormat, определяет метод форматирования текста. Его значение представляет собой битовую маску, образованную объединением флагов форматирования.


Окт 14 2009

Выравнивание по ширине (выключка)

Функция TextOut обеспечивает выравнивание текста по левому или правому краю, а также по центру. Вид выравнивания зависит от текущего режима выравнивания. Но при этом функция не поддерживает выравнивание по ширине (выключку). Выравнивание по ширине означает, что левый край текста должен быть выровнен по левой границе области, а правый край — по правой границе. Это достигается равномерным увеличением протяженности пробелов, разделяющих слова в строке.
Для решения указанной проблемы GDI позволяет использовать функции GetTextExtentPoint32 и SetTextJustification.
Допустим, что надо реализовать выключку при выводе строк текста в область с левой границей х и правой границей х + width. Предполагается, что протяженность строк не превышает width логических единиц. План решения обычно содержит следующие шаги:
1. С помощью инструкций
SIZE size;
GetTextExtentPoint32(hDC, IpString. nCount. Ssize):
получить размеры обрамляющего прямоугольника для строки IpString, содержащей nCount символов. Эти размеры возвращаются в виде значений полей параметра size. Поле size.cx будет содержать ширину обрамляющего прямоугольника, а поле size.су — высоту обрамляющего прямоугольника.
2. Подсчитать количество разделительных символов nBreak в строке IpString. Разделительным символом обычно является пробел, но он может быть переопределен в каком-либо шрифте на другой символ. Если нужно уточнить, какой символ на самом деле является разделительным, используйте функцию GetTextMetrics с последующим анализом поля tmBreakChar структуры TEXTMETRIC.
3. Вычислить размер пространства, которое необходимо распределить между nBreak разделительными символами:
int breakExtra = width - size.cx;
4. Вызвать функцию
SetTextJustification(hdc, breakExtra. nBreak);
передав ей определенные выше величины breakExtra и nBreak. Функция SetText-Justification присвоит атрибуту контекста устройства, отвечающему за выключку текста, величину дополнительного интервала, используемую после этого функциями TextOut и ExtTextOut.
5. Позаботиться о том, чтобы текущий режим выравнивания текста содержал флаг TA_LEFT (значение по умолчанию). После этого уже можно вызвать функцию TextOut для отображения строки текста.
Следует отметить, что при каждом вызове функции SetTextJustification накапливается погрешность, если величина breakExtra не делится нацело на nBreak. Чтобы эта погрешность не повлияла на последующую работу функции GetTextExtent-Point32 при выводе многострочного текста, рекомендуется перед обращением к GetTextExtentPoint32 сбросить накопленную погрешность вызовом функции
SetTextJustification(hdc. 0. 0);
В листинге 2.1 приводится программа, в которой демонстрируется описанная технология выравнивания текста по ширине.


Окт 14 2009

Межсимвольные интервалы

В контексте устройства имеется специальный атрибут, управляющий расстоянием между символами, — межсимвольный интервал {extra space). Межсимвольный интервал добавляется к каждому символу, включая символы пробела, когда GDI выводит строку текста. По умолчанию этот атрибут равен нулю. Функция SetTextCharacterExtra присваивает ему новое целочисленное значение в логических единицах, возвращая предыдущее значение. Функция GetTextCharacterExtra возвращает текущее значение межсимвольного интервала.


Окт 14 2009

Вывод текста с табуляцией

К сожалению, функция TextOut не обрабатывает управляющие символы, в том числе символы перевода строки \п и табуляции \t. Встретив любой такой символ, она просто выведет глиф (для системного шрифта SYSTEM_FONT) или глиф для несистемного шрифта.
В то же время табуляция широко используется в простейших текстовых редакторах для выравнивания текста по столбцам, облегчающего восприятие информации. Для обеспечения работы с табулированным текстом Windows содержит функции TabbedTextOut и GetTabbedTextExtent.
Функция TabbedTextOut имеет следующий прототип:
LONG TabbedTextOut(HDC hOC. int X. int Y. LPCTSTR IpString, int nCount. int iNumTabs. CONST LPINT IpnTabStops, int xTabOrigin);
Первые пять параметров имеют то же значение, что и у функции TextOut. Шестой параметр, iNumTabs, определяет количество позиций табуляции. Седьмой параметр, IpnTabStops, содержит указатель на массив позиций табуляции, заданных в логических единицах. Позиции табуляции должны быть отсортированы в возрастающем порядке.
Если шестой параметр равен нулю и одновременно седьмой параметр равен NULL, то позиции табуляции устанавливаются через одинаковые промежутки, равные восьмикратной средней ширине символов. Если шестой параметр равен единице, то первый элемент массива IpnTabStops содержит число символьных позиций, которое каждый раз прибавляется для определения следующей позиции табуляции.
Последний параметр, xTabOrigin, задает логическую координату по горизонтали точки отсчета позиций табуляции. Часто бывает удобно определить эту точку так, чтобы она совпадала с начальной позицией вывода строки, поскольку в этом случае массив IpnTabStops перестает быть зависимым от конкретной позиции вывода.
Если выводимая строка содержит символы табуляции \t, то GDI отображает начало строки, пока не обнаружит символ табуляции. После этого GDI просматривает массив позиций табуляций, и если первая позиция подходит для продолжения вывода (то есть она находится правее границы последнего выведенного символа строки), то вывод продолжается с этой позиции. В противном случае GDI берет следующую позицию из массива и проверяет ее и т. д. То же самое происходит при обнаружении следующего символа табуляции. Таким образом, функция не гарантирует, что символы после я-го символа табуляции будут выводиться в п-й позиции табуляции.
Позиции табуляции в массиве IpnTabStops могут быть отрицательными. В этом случае GDI использует абсолютное значение указанной величины, но выравнивает текст по правому краю перед заданной позицией, вместо выравнивания по левому краю после нее.
В случае успешного завершения функция TabbedTextOut возвращает 32-разрядное число, старшее слово которого содержит высоту, а младшее — ширину выведенной строки. В случае неудачного завершения работы возвращается нулевое значение.
Функция GetTabbedTextExtent возвращает размеры табулированного текста, не выводя его.


Окт 14 2009

Простой вывод текста

Функция обеспечивает вывод строки с адресом IpString, размещая текст в заданной позиции с учетом текущего режима выравнивания. При выводе используются текущие значения атрибутов контекста устройства — шрифт, цвет текста и цвет фона графических элементов, режим смешивания фона и многие другие. Функция не распознает конец строки IpString по завершающему нулевому символу, поэтому количество выводимых символов задается параметром cbString. Символы строки должны входить в набор символов текущего шрифта. Позиционирование текста зависит от текущего режима выравнивания.
Текущий режим выравнивания текста реализован как атрибут контекста устройства, определяющий правила позиционирования текста. Он указывает, что считать опорной точкой {referencepoint): точку (nXStart, nYStart) или текущую позицию пера в контексте устройства. Также режим выравнивания определяет, как позиционировать строку текста (обрамляющий прямоугольник) относительно опорной точки и как выводить текст: слева направо или справа налево.


Окт 14 2009

Вывод текста

Win32 GDI обеспечивает полный набор функций для форматирования и рисования текста в клиентской области окна или на бумажной странице принтера. Эти функции могут быть разделены на те, которые форматируют текст, подготавливая его для вывода, и те, которые действительно отображают текст. Форматирующие функции выравнивают текст, устанавливают межсимвольные промежутки, изменяют протяженность разделительных символов, устанавливают цвет текста и цвет фона графических элементов. Рисующие функции выводят отдельные символы или целые строки текста.


Следующая страница »