Способы заполнения прямоугольной области




 

Параметр dwRaster Способ заполнения
  BLACKNESS Область заполняется черным цветом (кисть игнорируется)
  WHITENESS Область заполняется белым цветом (кисть игнорируется)
  PATCOPY Область заполняется текущей кистью
  PATINVERT Логическая операция OR (ИЛИ) для цвета области с те­кущей кистью
  DSTINVERT Инвертирование цвета области (игнорирование кисти)

 

Таким образом, для сохранения способа заполнения, определенного текущей кис­тью, параметру dwRaster необходимо присвоить значение PATCOPY. Функция возвра­щает ненулевое значение в случае успешного завершения и 0 в противном случае.

Теперь, когда Вы знаете все необходимые функции, пора переходить к построе­нию виртуального окна.

 

Правила создания виртуального окна. Начнем с повторения алгоритма, который необходимо запрограммировать. Для создания простого и удобного способа восстановления содержимого окна при получении сообщения WM_PAINT строится виртуальное окно и весь вывод програм­мы направляется в это окно. При получении запроса на перерисовку окна содержимое виртуального окна копируется в реальное окно на экране. Теперь приступим к программированию.

 

Создание виртуального окна. Прежде всего необходимо создать виртуальный контекст устройства, совмести­мый с контекстом реального устройства. Это делается один раз – в начале выпол­нения программы при получении сообщения WM_CREATE. Созданный виртуальный контекст устройства будет существовать в течение всего времени выполнения про­граммы. Приведем фрагмент программы, выполняющий эти действия:

 

case WM_CREATE: // Получаем размеры экрана

maxX=GetSystemMetrics(SM_CXSCREEN);

maxY=GetSystemMetrics(SM_CYSCREEN);

hdc=GetDC(hwnd); //Строим совместимый с окном растр

memdc=CreateCompatibleDC(hdc);

hbit=CreateCompatibleBitmap(hdc,maxX,maxY);

SelectObject(memdc,hbit);

hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH);

SelectObject(memdc,hbrush);

PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

ReleaseDC(hwnd,hdc);

break;

 

Рассмотрим этот фрагмент более подробно. Сначала программа получает размеры экрана, – эти значения будут затем использоваться совместимым растром. Затем создается контекст устройства окна, а после этого – совместимый контекст устрой­ства памяти при помощи функции CreateCompatibleDC(). Полученный контекст сохраняется во внешней переменной memdc. Затем создается совместимый растр. Эта операция устанавливает также взаимно-однозначное соответствие между растром –виртуальным окном и реальным окном на экране.

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

Дескриптор растра сохраняется во внешней переменной hbit. Затем программа получает дескриптор встроенной белой кисти и запоминает его во внешней переменной hbrush Кисть выбирается как текущая для контекста устройства памяти, после чего функция PatBlt() рисует этой кистью виртуальное окно. Таким образом, виртуальное окно оказывается заполненным белым цветом, что соответствует фону реального окна в следующем примере. (Помните, что эти цвета должны быть одинаковыми, но Вы можете задавать их по своему усмотрению.) Наконец, контекст устройства физического окна освобождается; контекст же устройству памяти продолжает существовать до завершения программы.

 

Работа с виртуальным окном. После создания виртуального окна весь вывод программы направляется в него. (Вывод в физическое окно осуществляется только в одном месте программы – при обработке сообщения WM_PAINT.) Из предыдущего примера приведем фраг­мент программы обработки команды ID_SHOW, измененный для работы с виртуаль­ным окном:

 

case ID_SHOW:

SetTextColor(memdc,RGB(0,0,0)); // Черный текста

SetBkColor(memdc,RGB(0,255,255));//Ярко-голубой фон

GetTextMetrics(memdc,Stm); // Метрики текста

sprintf(str,"Высота шрифта %ld пикселей",

tm.tmHeight);

TextOut(memdc,X,Y,str,strlen(str));//Вывести строку

Y=Y+tm.tmHeight+tm.tmExternalLeading; // Следующая

// строка

strcpy(str,"Это следующая строка");

TextOut(memdc,X,Y,str,strlen(str)); // Вывод строки

// Определить длину строки

GetTextExtentPoint32(memdc,str,strlen(str),&size);

sprintf(str,"Длина предыдущей строки %ld единиц",

size.cx);

X=size.cx; // X в конец предыдущей строки

TextOut(memdc,X,Y,str,strlen(str));

Y=Y+tm.tmHeight+tm.tmExternalLeading; // Следующая

// строка

X=0; // X опять в начало */

sprintf(str,"Размеры экрана %d x %d",maxX,maxY);

TextOut(memdc,X,Y,str,strlen(str));

Y=Y+tm.tmHeight+tm.tmExternalLeading; // Следующая

// строка

InvalidateRect(hwnd,NULL,1);

break;

 

В этом фрагменте весь вывод направляется на устройство, соответствующее контексту memdc, после чего вызывается функция InvalidateRect() для перерисовки реального окна.

При получении сообщения WM_PAINT содержимое виртуального окна копи­руется в реальное окно на экране. Это выполняет следующий фрагмент:

 

case WM_PAINT: // Перерисовка окна

hdc=BeginPaint(hwnd,&paintstruct); // Получить DC

// Теперь копируем растр из памяти на экран

BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);

EndPaint(hwnd,&paintstruct); // Освободить DC

break;

 

Как видите, для копирования изображения из memdc в hdc используется функция BitBlt(). Вспомните, что параметр SRCCOPY определяет процесс копи­рования изображения «как есть». Поскольку весь вывод программы до этого направлялся контексту memdc, то после этой операции выводимая информация отображается на экране. Таким образом, если окно было перекрыто другим окном, а затем восстановлено, будет получено сообщение WM_PAINT и содержимое окна автоматически восстановится.

Как уже было сказано, есть несколько способов восстановления содержимого окна, однако только что описанный способ в большинстве случаев является наиболее эффек­тивным и применяется чаще других. Кроме того, поскольку Ваша программа может определить координаты области, которая должна быть перерисована, можно оптимизи­ровать приведенный выше код и сделать его более эффективным, просто восстанавливая окно частично, а не полностью. (Попробуйте сделать это самостоятельно.)

 

Пример 8-2. Приведем полный текст программы работы с виртуальным окном:

 

// Вывод текста с использованием виртуального окна

#include <Windows.h>

#include <String.h>

#include <Stdio.h>

#include "Text.h"

 

LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);

char szWinName[] = "МоеОкно"; // Имя класса окна

char str[255]; // Буфер строки вывода

int X=0, Y=0; // Текущие координаты строки

int maxX, maxY; // Размеры экрана

HDC memdc; // DC виртуального окна

HBITMAP hbit; // Растр - это виртуальное окно

HBRUSH hbrush; // Дескриптор кисти

 

int WINAPI WinMain (HINSTANCE hThisInst,

HINSTANCE hPrevInst,

LPSTR lpszArgs,

int nWinMode)

{

HWND hwnd;

MSG msg;

WNDCLASS wcl;

HACCEL hAccel;

// Определить класс окна

wcl.hInstance=hThisInst; // Дескриптор приложения

wcl.lpszClassName=szWinName; // Имя класса окна

wcl.lpfnWndProc=WindowFunc; // Функция окна

wcl.style=0; // Стиль по умолчанию

wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION); // Иконка

wcl.hCursor=LoadCursor(NULL,IDC_ARROW); // Курсор

wcl.lpszMenuName="MYMENU"; // Меню

wcl.cbClsExtra=0; // Без дополнительной

wcl.cbWndExtra=0; // информации

// Определить заполнение окна белым цветом

wcl.hbrBackground=

(HBRUSH)GetStockObject(WHITE_BRUSH);

if(!RegisterClass(&wcl)) // Зарегистр. класс окна

return 0;

// Создать окно

hwnd=CreateWindow(szWinName, // Имя класса

"Виртуальное окно с текстом",

WS_OVERLAPPEDWINDOW,// Стиль окна

CW_USEDEFAULT, // Х-координата

CW_USEDEFAULT, // Y-координата

CW_USEDEFAULT, // Ширина окна

CW_USEDEFAULT, // Высота окна

HWND_DESKTOP, // Нет родит. окна

NULL, // Нет меню

hThisInst, // Дескрип. приложения

NULL); // Без дополит. аргументов

// Загрузить акселераторы

hAccel=LoadAccelerators(hThisInst,"MYMENU");

ShowWindow(hwnd,nWinMode); // Показать окно и

UpdateWindow(hwnd); // перерисовать содержимое

// Запустить цикл обработки сообщений

while(GetMessage (&msg,NULL,0,0))

if(!TranslateAccelerator(hwnd,hAccel,&msg))

{

TranslateMessage(&msg); // Использ.Клавиатуры

DispatchMessage (&msg); // Возврат к Windows

}

return msg. wParam;

}

 

// Следующая функция вызывается операционной системой

// Windows и получает в качестве параметров сообщения

// из очереди сообщений данного приложения

 

LRESULT CALLBACK WindowFunc(HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT paintstruct;

TEXTMETRIC tm;

SIZE size;

switch(message)

{

case WM_CREATE: // Получаем размеры экрана

maxX=GetSystemMetrics(SM_CXSCREEN);

maxY=GetSystemMetrics(SM_CYSCREEN);

hdc=GetDC(hwnd); // Совмест. с окном растр

memdc=CreateCompatibleDC(hdc);

hbit=CreateCompatibleBitmap(hdc,maxX,maxY);

SelectObject(memdc,hbit);

hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH);

SelectObject(memdc,hbrush);

PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

ReleaseDC(hwnd,hdc);

break;

case WM_COMMAND:

switch(LOWORD(wParam))

{

case ID_SHOW:

SetTextColor(memdc,RGB(0,0,0)); // Черн

SetBkColor(memdc,RGB(0,255,255)); //Син

GetTextMetrics(memdc,&tm); // Метрики

sprintf(str,

"Высота шрифта %ld пикселей",

tm.tmHeight);

TextOut(memdc,X,Y,str,strlen(str));

Y=Y+tm.tmHeight // Следующая

+tm.tmExternalLeading; // строка

strcpy(str,"Это следующая строка.");

TextOut(memdc,X,Y,str,strlen(str));

GetTextExtentPoint32(memdc,str, //Длина

strlen(str),

&size);

sprintf(str,

"Длина предыдущей строки %ld",

size.cx);

X=size.cx; // В конец предыдущей строки

TextOut(memdc,X,Y,str,strlen(str));

Y=Y+tm.tmHeight // Следующая

+tm.tmExternalLeading; // строка

X=0; // X опять в начало

sprintf(str,"Размеры экрана %d x %d",

maxX,maxY);

TextOut(memdc,X,Y,str,strlen(str));

Y=Y+tm.tmHeight // Следующая

+tm.tmExternalLeading; // строка

InvalidateRect(hwnd,NULL,1); //Сообщить

break;

case ID_RESET:

X=Y=0; // Стереть перерисовкой фона

PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

InvalidateRect(hwnd,NULL,1); //Сообщить

break;

case ID_HELP:

MessageBox(hwnd,"F2: вывести текст,\n"

"F3: с начала экрана",

"Помощь",MB_OK);

break;

}

break;

case WM_PAINT: // Перерисовка окна

hdc=BeginPaint(hwnd,&paintstruct); // Пол. DC

// Теперь копируем растр из памяти на экран

BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);

EndPaint(hwnd,&paintstruct); // Освободить DC

break;

case WM_DESTROY: // Завершение программы

DeleteDC(memdc); // Удалить виртуальное окно

PostQuitMessage(0);

break;

default:

// Все сообщения, не обрабатываемые в данной

// функции, направляются на обработку по

// умолчанию

return DefWindowProc(hwnd,message,

wParam,lParam);

}

return 0;

}

 

Запустив эту программу, Вы сразу оцените два существенных преимущества. Во-первых, при необходимости восстанавливается содержимое окна. Во-вторых, по команде Сначала окно очищается. Это происходит потому, что вызов PatBlt() при обработке ID_RESET приводит к заполнению окна белым цветом и, соответственно, к затиранию его содержимого.

 

Изменение шрифтов

 

Как Вы, вероятно, знаете, одной из основных целей Windows является обеспечение полного управления пользовательским интерфейсом. Поэтому операционная система располагает богатыми и разнообразными возможностями работы с текстом, которые Вы можете использовать. Главной из них является поддержка множес­тва разнообразных шрифтов. Программируя в Windows, Вы можете не только использовать встроенные шрифты, но и создавать собственные. Следующие разделы посвящены обсуждению этих возможностей и их реализации.

 

Использование встроенных шрифтов. Встроенные шрифты – это системные объекты, которые могут быть выбраны при помощи функции GetStockObject(). Макроимена, ассоциированные с некоторыми шрифтами, приводятся в таблице 8.4.

 

Таблица 8.4



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-03-31 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: