Окт 16 2009

Логическая палитра

При работе с логической палитрой следует помнить, что все цвета в приложении, которые реализованы как значения типа C0L0RREF, должны быть определены с помощью одного из следующих макросов:
COLORREF PALETTEINDEXtWORD wPalettelndex);
COLORREF PALETTERGB(BYTE bRed, BYTE bGreen, BYTE bBlue);
Макрос PALETTEINDEX получает индекс и возвращает 32-разрядное описание элемента палитры. В контексте устройства оно используется как элемент логической палитры контекста.
Макросу PALETTERGB, как и макросу RGB, передаются значения красной, зеленой и синей составляющих искомого цвета. При использовании этих макросов в контексте устройства без логической палитры их возвращаемые значения интерпретируются одинаково. Но если макрос PALETTERGB используется в контексте устройства с логической палитрой, то для указанных в нем RGB-составляющих система ищет ближайшее совпадение в логической палитре, словно приложение указало индекс в палитре. Этот макрос используется чаще, так как он является очевидной заменой макроса RGB во всех функциях, требующих передачи значения типа COLORREF.


Окт 16 2009

Системная палитра

Системная палитра является графическим объектом уровня операционной системы. Ранее уже говорилось о том, что диапазон цветов, которые одновременно воспроизводятся устройством, зависит как от аппаратной палитры, реализуемой видеоадаптером, так и от настроек экрана.
Чтобы посмотреть или изменить настройки экрана, нужно щелкнуть правой кнопкой мыши на свободной части рабочего стола экрана, после чего появится всплывающее меню. В этом меню следует выполнить команду Свойства, что приведет к отображению диалогового окна Свойства: Экран. В окне нужно выбрать вкладку Настройка и найти на ней групповое поле Цветовая палитра. Элемент управления типа C0MB0B0X внутри этого поля позволяет выбирать количество одновременно отображаемых цветов на экране. Если у вас достаточно современный дисплей, то доступными, скорее всего, окажутся следующие установки:
256 цветов;
Hi Color (16 бит);
True Color (24 или 32 бит).
В 256-цветном режиме каждый пиксел представлен в кадровом буфере видеоадаптера одним байтом. Один байт позволяет закодировать до 256 разных цветов, одновременно отображаемых на экране. Точный состав цветов определяется палитрой видеоадаптера, которая предоставляется пользовательским приложениям в виде системной палитры.
тоит обратить внимание на необычное размещение статических цветов. Так, первая группа из десяти цветов располагается в начале таблицы, а вторая группа из десяти цветов — в конце таблицы. Это связано с тем, что наиболее употребительная растровая операция X0R часто используется для инвертирования цветов и последующего их восстановления. Поэтому важно обеспечить инвертирование цвета при помощи инвертирования значения индекса в цветовой таблице. Например, инверсия нулевого значения индекса дает значение 255 (OxFF), при этом черный цвет трансформируется в белый. Позицию 1 занимает темно-красный цвет R6B(0x80, 0x00, 0x00). Если инвертировать индекс, то он переходит в 254 (OxFE), что соответствует голубому цвету. Он не совсем совпадает с цветом, дополняющим темно-красный цвет в цветовом пространстве RGB (R6B(0x7F, OxFF, OxFF)), но все же достаточно близок к нему.
Первые 8 цветов и последние 8 цветов никогда не изменяются, независимо от цветового режима. Реализация цветов с индексами 8,9, 246, 247 зависит от режима. В таблице указаны RGB-значения этих цветов для режима True Color. В 256-цветном режиме RGB-значения этих цветов будут другими.


Окт 16 2009

Основные принципы управления палитрами

Цветовая палитра представляет собой таблицу (массив) цветов, которые способно воспроизвести устройство. Вход в таблицу для доступа к каждому цвету осуществляется по индексу.
В Win32 GDI используется несколько типов палитр.
Системная палитра {system palette) определяет все цвета, которые могут быть одновременно отображены устройством. Диапазон цветов зависит от аппаратной палитры, реализуемой видеоадаптером, и от настроек экрана. В любом случае системная палитра является неким «программным представителем» аппаратной палитры. Приложение не может непосредственно модифицировать системную палитру. Системная палитра обычно содержит 256 элементов (входов), из которых 20 зарезервировано для так называемых статических цветов, которые никогда не изменяются. Эти цвета используются всеми приложениями для вывода меню, кнопок, фона окна, текстовых надписей и других элементов стандартного интерфейса.
Логическая палитра (logical palette) — это палитра уровня приложения. Она создается приложением и закрепляется за контекстом устройства. Логическая палитра позволяет определять и использовать цвета, которые соответствуют потребностям приложения. После создания логической палитры с помощью функции CreatePalette или CreateHalftonePalette она должна быть реализована вызовом функции ReaHzePalette. В процессе реализации Windows заполняет неиспользуемые элементы в системной палитре цветами из логической палитры. Если неиспользованных элементов меньше, чем нужно, то Windows распределяет оставшиеся цвета из логической палитры, либо подыскивая ближайший цвет в аппаратной палитре, либо определяя подходящее смешение (dithering) цветов, если применяются сплошные кисти.
Для успешного применения логической палитры нужно учесть еще один нюанс, о котором в MSDN практически ничего не говорится. Во всех функциях, требующих передачи аргумента типа COLORREF, соответствующее значение должно быть определено с помощью макроса PALETTERGB, а не при помощи макроса RGB.
Если приложение явно не создает логическую палитру, то используется палитра по умолчанию (default palette), содержащая только те 20 цветов, которые имеются в системной палитре. В этом случае для аппроксимации цвета, отсутствующего в палитре, будут использоваться указанные 20 цветов.
Чтобы обеспечить одновременную работу нескольких приложений, использующих различные логические палитры, Windows предоставляет активному окну1 приоритет в установлении цветов для логической палитры. Неактивным окнам приходится пользоваться оставшимися цветами. Неактивные окна используют все незадействованные элементы в логической палитре и применяют ближайшие согласованные цвета для всех невыполненных запросов к палитре. Однако эта проблема обычно не очень существенна, поскольку в большинстве приложений используются только системные цвета.
Для координации функционирования активных и неактивных окон при работе с палитрами, прежде чем предоставить фокус ввода приложению, которое использует логическую палитру, Windows отправляет ему сообщение WM_QUERYNEWPALETTE. Это сообщение дает возможность приложению еще раз реализовать палитру и восстановить цвета, которые могли быть изменены другими приложениями, пока окно было неактивным.
Сообщение WM_PALETTECHANGED отправляется всем окнам, когда одно из приложений реализует свою логическую палитру. Для неактивных окон это сообщение несет информацию о том, что некоторые цвета в палитре могли быть изменены другим окном, имеющим фокус ввода.


Окт 16 2009

Палитры

Если устройство вывода поддерживает полный диапазон цветов, определенных 24-битным RGB-значением1, то палитра вам не нужна. К сожалению, еще не вышли из употребления старые модели дисплеев, которые поддерживают только 256 цветов. Другие графические устройства, такие как принтеры и плоттеры, тоже имеют ограничения по количеству воспроизводимых цветов.
Графические объекты, именуемые в Windows палитрами, обеспечивают надлежащее согласование цветов при работе приложений на разных аппаратных платформах. Чтобы узнать, поддерживает ли конкретное устройство работу с палитрой, нужно вызвать функцию GetDeviceCaps, передав значение индекса RASTERCAPS, и убедиться, что возвращаемое значение содержит флажок RC_PALETTE.
Для упрощения изложения в следующих разделах, посвященных палитре, под устройством вывода будет подразумеваться дисплей.


Окт 16 2009

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

Приложение U_T_Diagram демонстрирует использование страничной системы координат, создание логических перьев, рисование различных линий, создание логических шрифтов, вывод текста с применением разных шрифтов.
В программе решается задача формирования и вывода на экран временной диаграммы напряжения переменного электрического тока. Действующее значение напряжения — 220 В, частота — 50 Гц. Диаграмма строится для промежутка времени, в котором происходят ровно два периода колебаний.
На рис. 2.37 показано окно приложения Черно-белый рисунок трансформирует различные цвета в оттенки серого и поэтому не передает всей красоты созданной диаграммы. Например, линии координатной сетки на самом деле имеют зеленоватый цвет, а синусоида графика — малиновый цвет. Если вы хотите все-таки насладиться этой красотой, то придется ввести в компьютер прилагаемый ниже текст программы, откомпилировать и запустить ее.
Период синусоидальных колебаний Т связан с их частотой / соотношением Т= \/f, поэтому для частоты 50 Гц период составляет 0,02 с, или 20 мс. Также полезно вспомнить, что действующее значение напряжения переменного тока U связано с его амплитудным значением Um соотношением U = 0,707 х Um. Из этого следует, что амплитудное значение напряжения равно 311,17 В.
Для улучшения внешнего вида графика используются не только разные цвета линий, но и разная толщина. Линии координатной сетки рисуются толщиной 1 пиксел, оси X и У — толщиной 3 пиксела, а сама синусоида — толщиной 5 пикселов.
Прежде чем привести листинг программы, сделаем некоторые пояснения по поводу выбора и настройки координатной системы. Размышления над сутью решаемой задачи приводят нас к убеждению, что здесь можно обойтись без аффинных преобразований и, следовательно, нас вполне устроит страничная система координат.
Физическую область вывода (viewport) стоит привязать к клиентской области окна, размеры которой можно получить при помощи функции GetClientRect. Благодаря этому рисунок будет автоматически масштабироваться при изменении размеров основного окна приложения.
Теперь подумаем, как нам организовать логическую область вывода (window). Казалось бы, здесь удобно использовать логические единицы, присущие данной проблемной области, то есть по оси абсцисс — миллисекунды, а по оси ординат — вольты. Но если выбрать эти логические единицы, то возникнет очень неприятная проблема. Фактически, мы потеряем контроль над толщиной пера, используемого для прорисовки линий. Это раз. Кроме того, толщина пера окажется разной при рисовании по горизонтали и по вертикали, так как она будет определяться масштабными коэффициентами тх и ту1. Это два.
Причиной перечисленных неприятностей являются особенности реализации в Win32 API объекта логического пера. Дело в том, что в вызове функции CreatePen(penStyLe, nWidth, crColor) параметр nWidth задает толщину пера именно в логических единицах. Исключением является нулевое значение nWidth,определяющее перо толщиной 1 пиксел независимо от установленных координатных преобразований.


Окт 16 2009

Просмотрщик текстовых файлов

Приложение TextViewer предназначено для чтения и вывода на экран текстового файла. В приложении демонстрируются: использование полос прокрутки, вывод текста при помощи функций TextOut и TabbedTextOut, а также использование региона отсечения.
В этом примере также показано, что использование идей ООП вряд ли ухудшает качество программного кода, скорее — наоборот. С этой целью разработан класс «Document для решения тех подзадач, которые связаны с загрузкой, хранением и выводом документа в клиентскую область окна с учетом его прокрутки. Интерфейс класса содержится в файле KDocument.h, а его реализация — в файле KDocument.cpp.
Обратите внимание на следующие особенности реализации класса KDocument:
Для хранения текстового документа используется член класса lines, который
объявлен как вектор строк типа string.
В методе Open заданный входной файл читается по строкам. Предполагается, что строки разделяются символом \п. Каждая прочитанная строка добавляется в конец вектора lines. Затем в цикле for вычисляется максимальная длина строки lineLenMax с учетом возможного присутствия символов табуляции. Присутствие символа табуляции в строке lines[i] проверяется методом find класса string, который возвращает позицию обнаруженного символа \t или значение -1, если символ табуляции не обнаружен. В методе ScrollSettings величина lineLenMax используется для установки максимального значения диапазона горизонтальной полосы прокрутки.
В методе Initialize вычисляются размеры «единиц данных» для скроллинга. Величина cxChar задает шаг изменения в горизонтальном измерении, а величина yStep — шаг изменения в вертикальном измерении. Для вычислений используются метрики текста, полученные в параметре tm.
Метод ScrollSettings предназначен для установки параметров вертикальной и горизонтальной полос прокрутки при заданных ширине width и высоте height клиентской области окна.
Метод UpdateVscroll выполняет итоговую обработку всех сообщений от вертикальной полосы прокрутки. В нем же производятся прокрутка содержимого окна при помощи функции ScrollWindow, обновление положения движка с помощью SetScrolUnfo и обновление клиентской области при помощи функции UpdateWindow. Более подробные комментарии по этому этапу можно найти в разделе «Полосы прокрутки и вывод текста».
Обратите особое внимание на первые две инструкции в теле функции. Они предваряются комментариями «ограничение на положительное приращение» и «ограничение на отрицательное приращение». Первая инструкция обеспечивает прекращение прокрутки при продвижении документа к его концу, как только позиция движка достигнет значения vertRange - (int)vsi.nPage. В этом положении движка последняя страница документа полностью видна в окне и дальнейшая прокрутка теряет смысл. Заметим, что преобразование к типу int для поля vsi.nPage необходимо для корректного выполнения макроса min.
Вторая инструкция обеспечивает прекращение прокрутки при продвижении документа к его началу, как только позиция движка достигнет значения vsi.nMin.
Метод UpdateHscroll производит итоговую обработку всех сообщений от горизонтальной полосы прокрутки. Реализация метода аналогична реализации метода UpdateVscroll.
Метод PutText предназначен для вывода фрагмента текста из документа в клиентскую область окна.
Для создания полей слева и справа от видимого в окне текста (в данном примере шириной в один символ) используется регион отсечения hRgn. Он создается вызовом функции CreateRectRgnlndirect, причем в качестве аргумента передается адрес прямоугольника rect, который в вертикальном измерении совпадает с прямоугольником клиентской области, а в горизонтальном измерении уменьшен слева и справа на величину cxChar. Созданный регион выбирается в контекст устройства функцией SelectClipRgn.
Фрагмент текста выводится в цикле for в соответствии с текущим положением движка vsi.nPos на вертикальной полосе прокрутки и текущим положением движка hsi.nPos на горизонтальной полосе прокрутки. Если в текущей строке lines[i] нет символов табуляции, то вызывается функция TextOut. В противном случае используется функция TabbedTextOut.
По умолчанию в контексте устройства установлен режим отображения ММ_ТЕХТ, поэтому начало координат совмещено с левым верхним углом клиентской области. Координата у для вывода каждой следующей строки вычисляется с учетом смещения yStep.
Если значение hsi.nPos совпадает со значением hsi.nMin, то координата х, вычисляемая по формуле cxChar x (hsi.nMin - hsi.nPos + 1), имеет значение cxChar. В этом случае строка выводится в окно, начиная с первого символа. А поскольку в контексте устройства выбран регион отсечения с дескриптором hRgn, то первый видимый символ в окне нельзя выводить левее, чем х = cxChar.
В случае hsi.nPos > 0 координата х будет принимать сначала нулевое, а потом отрицательные значения, абсолютная величина которых возрастает по мере прокрутки документа по горизонтали вправо. То есть начало вывода строки приходится на точку экрана, лежащую слева за пределами окна приложения. Разумеется, за счет отсечения, за которым следит Windows, пользователь будет видеть только ту часть строки, которая попадает в клиентскую область окна. А еще точнее, только ту часть строки, которая попадает в регион отсечения.
Перед выходом из функции инструкция SelectClipRgn(hdc, NULL) удаляет из контекста устройства выбранный ранее регион отсечения.


« Предыдущая страница