Виртуальное окно

виртуальное

Виртуальное окно

Проблема перерисовки. Предыдущая программа демонстрирует работу основных текстовых и системных функций Windows. Однако при ее выполнении снова возникает проблема, которая уже рассматривалась в гл. 3. Вы запускаете эту программу, отображаете текст, затем Ваше окно перекрывается другим окном - и текст теряется. Если же окно перек­рывается не полностью, а частично, то пропадает часть текста. Решение проблемы состоит в том, что окно должно перерисовываться каждый раз при получении сообщения WM_PAINT, чего нет в нашем примере. Однако здесь возникает другой вопрос: какой механизм должно использовать это окно для перерисовки рабочей области? Как было сказано выше, имеется три основных метода. Напомним:

1) восстановить содержимое рабочей области, если оно формируется при помощи каких-либо вычислений;

2) можно запомнить последователь­ность событий и «проиграть» эту последовательность заново;

3) можно держать виртуальное окно и просто копировать его содержимое в рабочую область окна на экране каждый раз при получении сообщения VM_PAINT.

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

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

Дополнительные функции API. Поддержка виртуального окна осуществляется несколькими функциями API. Четыре из них - CreateCompatibleDC(),  SelectObject(),  GetStockObject() и BitBlt() - уже рассмотрены.

Кроме этих функций нам понадобятся функции

CreateCompatibleBitmap() и  PatBlt(),  которые описываются ниже.

Функция CreateCompatibleBitmap() создает в памяти растровое изображение, совмес­тимое с заданным контекстом устройства. Это растровое изображение (bitmap) может использоваться при помощи ссылок на совместимый контекст устройства который создается при помощи функции CreateCompatibleDC(). Прототип этой функции таков:

HBITMAP CreateCompatibleBitmap(HDC hdc, int width, int height);

Здесь hdc представляет контекст устройства, с которым должно быть совместимо создаваемое растровое изображение. Размеры растра задаются параметрами width и height и указываются в пикселях. Функция возвращает дескриптор созданного растра в случае успешного завершения и NULL - в случае возникновения ошибки.

Функция PatBlt() заполняет заданную прямоугольную область, используя цвет и способ заполнения, определяемый текущей кистью. Кисть (brush) - это объект, задающий способ заполнения окна (или области). Заполнение некоторой области при помощи кисти обычно называется рисованием области. Прототип функции PatBlt() выглядит так:

BOOL PatBlt(HDC hdc, int X, int Y, int width,

               int  height, DWORD dwRaster) ;

Здесь hdc представляет контекст устройства, на котором выполняется заполнение. Параметры Х и Y задают координаты верхнего левого угла прямоугольной области, которая будет заполняться. Размеры этой области задаются параметрами width и height. Параметр dwRaster определяет способ применения кисти и может принимать одно из следующих значений (табл. 8.3.):


Таблица 8.3

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

Параметр dwRaster

Способ заполнения

1

BLACKNESS

Область заполняется черным цветом (кисть игнорируется)

2

WHITENESS

Область заполняется белым цветом (кисть игнорируется)

3

PATCOPY

Область заполняется текущей кистью

4

PATINVERT

Логическая операция OR (ИЛИ) для цвета области с те­кущей кистью

5

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)

  

   return msg. wParam;

   }

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

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

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

LRESULT CALLBACK WindowFunc(HWND hwnd,

                            UINT message,

                            WPARAM wParam,

                            LPARAM lParam)

  

         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 приводит к заполнению окна белым цветом и, соответственно, к затиранию его содержимого.


Источник: http://www.scritub.com/limba/rusa/22111151419.php


Рекомендуем посмотреть ещё:


Закрыть ... [X]

Утро России / Алексеенко: виртуальное окно. / Видео / Как и из чего сделать ёлку

Виртуальное окно

Виртуальное окно в мир Winscape с трекингом положения

Виртуальное окно

Виртуальное окно - Мастерская своего дела

Виртуальное окно

Illumotion - виртуальные окна для офиса и дома

Виртуальное окно

Виртуальное фальш окно Eye

Виртуальное окно

Виртуальное окно

Виртуальное окно

БМВД - суперконцентраты для свиней. Реализация

Виртуальное окно

Бантики из атласных лент. Пошаговая инструкция с фото

Виртуальное окно

Гнезда и насесты для кур несушек: их размеры и как правильно

Виртуальное окно

День рождения ребенка 1 год, сценарий дня рождения 1

Виртуальное окно

Дневник glebova_aa : LiveInternet - Российский Сервис

Виртуальное окно

Идеи для дома, подарков и безделушек своими руками

Виртуальное окно

Как выбрать секатор? : Энциклопедия роз

Виртуальное окно

Как сделать теплый пол от отопления

Виртуальное окно

Лагуна Мягкая мебель Ваши отзывы, мнения



ШОКИРУЮЩИЕ НОВОСТИ