Размеры системных метрик




Значение Получаемый размер
  SM_CXFULLSCREEN Ширина рабочей области максимизированного окна
  SM_CYFULLSCREEN Высота рабочей области максимизированного окна
  SM_CXICON Ширина большой иконки
  SM_CYICON Высота большой иконки
  SM_CXSMICON Ширина малой иконки
  SM_CYSMICON Высота малой иконки
  SM_CXSCREEN Ширина экрана
  SM_CYSCREEN Высота экрана

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

 

// Демонстрация вывода текста

#include <Windows.h>

#include <String.h>

#include <Stdio.h>

#include "Text.h"

 

LRESULT CALLBACK Window

Func(HWND,UINT,WPARAM,LPARAM);

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

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

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

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

 

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;

TEXTMETRIC tm;

SIZE size;

switch(message)

{

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

maxX=GetSystemMetrics(SM_CXSCREEN);

maxY=GetSystemMetrics(SM_CYSCREEN);

break;

case WM_COMMAND:

switch(LOWORD(wParam))

{

case ID_SHOW:

hdc=GetDC(hwnd); // Контекст устройства

// Установить черный цвет текста

SetTextColor(hdc,RGB(0,0,0));

// Установить ярко-голубой цвет фона

SetBkColor(hdc,RGB(0,255,255));

// Получить метрики текста

GetTextMetrics(hdc,&tm);

sprintf(str,

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

tm.tmHeight);

// Вывести строку

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

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

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

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

// Вывести строку

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

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

GetTextExtentPoint32(hdc,str,

strlen(str),

&size);

sprintf(str,

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

size.cx);

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

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

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

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

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

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

maxX,maxY);

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

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

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

ReleaseDC(hwnd,hdc); // Освободить DC

break;

case ID_RESET:

X=Y=0;

break;

case ID_HELP:

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

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

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

break;

}

break;

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

PostQuitMessage(0);

break;

default:

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

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

// умолчанию

return DefWindowProc(hwnd,message,

wParam,lParam);

}

return 0;

}

 

Вам также понадобится следующий файл ресурсов:

 

#include <Windows.h>

#include "Text.h"

 

MYMENU MENU

{

MENUITEM "&Текст", ID_SHOW

MENUITEM "&Сначала", ID_RESET

MENUITEM "Помощь", ID_HELP

}

MYMENU ACCELERATORS

{

VK_F2, ID_SHOW, VIRTKEY

VK_F3, ID_RESET, VIRTKEY

VK_F1, ID_HELP, VIRTKEY

}

 

Кроме того, потребуется файл определений Text.h:

#define ID_SHOW 100

#define ID_RESET 101

#define ID_HELP 102

 

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


Рис. 8.1. Окно программы работы с текстом

 

При создании окна его оконная функция получает сообщение WM_CREATE. При его обработке инициализируются внешние переменные mахХ и maxY. Они прини­мают значения размеров экрана при помощи функции GetSystemMetrics(). И хотя эти значения не используются в нашем примере, они понадобятся в последующих программах.

Заметьте, что в программе используются еще две внешние переменные X и Y, имеющие нулевые начальные значения. Эти переменные сохраняют текущие коор­динаты в окне, в которых будет отображаться следующая текстовая строка. Они постоянно обновляются при выводе текста.

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

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


После этого выводится строка: «Это следующая строка». Затем, прежде чем содержимое буфера вывода изменится в результате вызова sprintf(), с помощью функции GetTextExtentPoint32() вычисляется длина строки, хранящейся в буфере. Полученное при этом значение используется для увеличения координаты X, поэтому следующая строка выводится как продолжение предыдущей (заметьте, что координата Y не изменяется). После вывода следующей строки координата Y снова увеличивается, а X устанавливается в 0, так что последующий текст будет выводиться с новой строки.

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

По команде Сначала текст (после вызова команды Текст) будет выводиться с начала рабочей области окна, поскольку значения координат X и Y будут обнуляться. Однако рабочая область при этом не очищается.

 

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

 

Проблема перерисовки. Предыдущая программа демонстрирует работу основных текстовых и системных функций 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



Поделиться:




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

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


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