Здавалка
Главная | Обратная связь

Виды контекста отображения



УП. 3. Вывод в окно

План:

УП. 3. Вывод в окно. 1

3.1. Сообщение WM_PAINT. 2

3.2. Виды контекста отображения. 7

Общий контекст отображения. 8

Контекст отображения для класса окон. 11

Личный контекст отображения. 14

Родительский контекст отображения. 15

Контекст отображения для окна. 15

3.3. Установка атрибутов контекста отображения. 17

3.4. Вывод текста. 24

3.4.1. Настройка параметров шрифта. 24

3.4.2. Выбор шрифта в контекст отображения. 27

3.4.3. Функции вывода текста. 27

3.4.4. Пример вывода текста в окно. 29

3.4.5. Определение метрик шрифта. 31

3.5. Рисование геометрических фигур. 41

3.5.1. Функции рисования точки. 41

3.5.2. Функции рисования линий. 42

3.5.3. Функции рисования замкнутых фигур. 51

Контрольные вопросы.. 54

Упражнения. 54

Приложение 3. 57

 

Вывод в окна обладает рядом особенностей.

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

2. Интерфейс графических устройств (Graphics Device Interface – GDI) системы открывает доступ к большому количеству функций вывода. Приложения, обращаясь к функциям GDI, работают не с физическими устройствами вывода, а с логическими. То есть описание вызова функций не зависит от физического способа отображения. GDI передает указания о выводе драйверу устройства вывода. Драйвер работает непосредственно с физическим устройством и при управлении выводом учитывает его ограниченные возможности и аппаратные особенности. Благодаря этому приложения способны работать с любым устройством вывода, драйвер которого установлен в системе. В этой главе рассматриваются функции и параметры вывода в окно на экране видеомонитора. Но не все физические устройства вывода способны поддерживать те режимы, в которых работает видеомонитор. Поэтому, описывая последовательность операций вывода, например на принтер, следует учитывать ограниченные возможности установленного принтера.

3. Параметры вывода устанавливают в контексте отображенияс помощью функций GDI. Контекст отображения – это структура данных, которая содержит характеристики устройства вывода и указатели на выбранные инструменты рисования. Функции GDI используют только выбранные в контекст отображения параметры и инструменты рисования. Например, для рисования линии некоторой толщины в контекст отображения приложение должно выбрать перо этой толщины.

4. Дескриптор контекста отображения служит первым аргументом вызова всех функций, связанных с выводом в окно.

Сообщение WM_PAINT

Стремление описывать вывод в окно при обработке сообщения WM_PAINT объясняется следующим. Windows следит за изменением расположения окон и при необходимости перерисовки окна посылает функции окна сообщение WM_PAINT. Функция окна при обработке этого сообщения перерисовывает все окно или указанные части.

Сообщение WM_PAINT обрабатывают следующим образом:

 

case WM_PAINT:

{

PAINTSTRUCT ps;

HDC hdc = BeginPaint(hwnd, &ps);

// Здесь настраивают контекст отображения

// и выводят в окно

EndPaint(hwnd, &ps);

return 0;

}

 

Структура PAINTSTRUCT описана следующим образом:

 

typedef struct {

НDС hdc;

BOOL fErase;

RECT rcPaint;

BOOL fRestore;

BOOL fIncUpdate;

BYTE rgbReserved[16];

} PAINTSTRUCT;

 

Поля переменной ps заполняет функция BeginPaint. После ее вызова поле hdc структуры ps содержит дескриптор контекста отображения (тот же, который возвращает функция BeginPaint). Поле rcPaint содержит координаты прямоугольной области обновления. Поле fErase определяет необходимость стирания фона области обновления. Если fErase = TRUE, фон окна стирается, иначе фон окна не изменяется. Остальные поля использует операционная система, приложение не должно изменять их содержимое.

После выполнения операций вывода приложение освобождает используемые ресурсы – вызывает функцию EndPaint.

Задача. В центре рабочей области окна вывести текст.

Листинг 3.1 содержит решение данной задачи.

Листинг 3.1. Вывод текста в центре рабочей области.

#include <windows.h>

#include <tchar.h>

 

BOOL RegClass(WNDPROC, LPCTSTR, UINT);

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

 

HINSTANCE hInstance;

TCHAR szClass[] = TEXT("OutputClass");

 

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)

{

MSG msg;

HWND hwnd;

hInstance = hInst;

if (!RegClass(WndProc, szClass, COLOR_WINDOW))

return FALSE;

hwnd = CreateWindow(szClass, TEXT("Вывод текста"),

WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL);

if (!hwnd) return FALSE;

ShowWindow(hwnd, SW_SHOWMAXIMIZED);

UpdateWindow(hwnd);

while(GetMessage(&msg, 0,0, 0)) DispatchMessage(&msg);

return msg.wParam;

}

 

BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)

{

WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.cbClsExtra = wc.cbWndExtra = 0;

wc.lpfnWndProc = Proc;

wc.hInstance = hInstance;

wc.lpszClassName = szName;

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH)(brBackground +1);

wc.lpszMenuName = NULL;

return (RegisterClass(&wc) != 0);

}

 

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

TCHAR szText[] = TEXT("Выводим какой-либо текст");

static short cx, cy;

switch (msg)

{

case WM_SIZE:

{

cx=LOWORD(lParam); cy=HIWORD(lParam);

return 0;

}

case WM_PAINT:

{

PAINTSTRUCT ps;

HDC hdc = BeginPaint(hwnd, &ps);

//Настриваем атрибуты вывода текста

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

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

SetTextAlign(hdc, TA_CENTER);

//Выводим текст

TextOut(hdc, cx/2, cy/2, szText, _tcslen(szText));

EndPaint(hwnd, &ps);

return 0;

}

case WM_DESTROY: { PostQuitMessage(0); return 0; }

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

 

Обратите внимание, что в стиле класса окна, обрабатывающего сообщение WM_PAINT, нужно указывать, что оно должно перерисовывать содержимое при изменении размеров окна:

 

wc.style = CS_HREDRAW | CS_VREDRAW;

 

Окна класса с таким стилем получают сообщение WM_PAINT при изменении их размеров.

При обработке сообщения WM_PAINT добавились операторы настраивания атрибутов контекста отображения и вывода в окно:

 

//Настриваем атрибуты вывода текста

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

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

SetTextAlign(hdc, TA_CENTER);

//Выводим текст

TextOut(hdc, cx/2, cy/2, szText, strlen(szText));

 

Функции настраивания атрибутов и вывода в окно рассматриваются ниже.

Представим теперь, что содержимое окна требуется обновить при обработке других сообщений. Для этого функции обновляемого окна достаточно передать сообщение WM_PAINT.

Одна из функций, которые посылают сообщение WM_PAINT, а именно UpdateWindow, использовалась ранее.

Эта функция объявлена следующим образом:

 

BOOL UpdateWindow( HWND hwnd );

 

Она посылает сообщение WM_PAINT непосредственно функции окна hwnd. В случае успешного выполнения функция UpdateWindow возвращает ненулевое значение, иначе – 0. Обычно ее вызывают для немедленной перерисовки области обновления.

Функция InvalidateRect добавляет прямоугольник в область перерисовки окна hwnd. Она объявлена следующим образом:

 

BOOL InvalidateRect( HWND hwnd, CONST RECT lpRect, BOOL bErase);

 

Параметр hwnd указывает на обновляемое окно. Если это параметр указывает на NULL, перерисовывают все окна. Параметр lpRect указывает на нуждающийся в обновлении прямоугольник в рабочей области. Если lpRect = NULL, то нужно обновить всю рабочую область окна hwnd. Параметр bErase определяет, нужно ли перекрасить фон указанной прямоугольной области. Если bErase = TRUE, фон перекрашивают, иначе фон остается неизменным.

В случае успешного выполнения функция возвращает ненулевое значение.

Добавляемые прямоугольники накапливаются до обработки сообщения WM_PAINT. В качестве единой области перерисовки Windows вычисляет один прямоугольник, который охватывает все добавленные прямоугольники.

Функция ValidateRect удаляет прямоугольную область из списка прямоугольников перерисовки. Прототип этой функции:

 

BOOL ValidateRect( HWND hwnd, CONST RECT lpRect);

 

Параметр hwnd указывает на окно, из области перерисовки которого исключается прямоугольник. Если этот параметр NULL, Windows перерисовывает все окна – посылает сообщения WM_ERASEBKGND и WM_NCPAINT функциям всех окон. Параметр lpRect указывает на прямоугольник, который будет удален от области перерисовки. Если lpRect = NULL, из области обновления удаляют все прямоугольники.

В случае успешного выполнения функция возвращает ненулевое значение.

Функция BeginPaint из области обновления удаляет всю рабочую область окна.

Задача. В центре рабочей области окна вывести строку "Текст по умолчанию". После нажатия левой клавиши мыши содержимое этой строки сменить на текст "Нажата левая клавиша мыши".

Листинг 3.2. Перерисовка окна после нажатия левой клавиши мыши

#include <windows.h>

#include <tchar.h>

 

BOOL RegClass(WNDPROC, LPCTSTR, UINT);

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

 

HINSTANCE hInstance;

TCHAR szClass[] = TEXT("OtputClass2");

TCHAR szText[50] = TEXT("Текст no умолчанию");

 

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)

{

MSG msg;

HWND hwnd;

hInstance = hInst;

if (!RegClass(WndProc, szClass, COLOR_WINDOW))

return FALSE;

hwnd = CreateWindow(szClass, TEXT("Вывод текста"),

WS_OVERLAPPEDWINDOW | WS_VISIBLE,

CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

0, 0, hInstance, NULL);

if (!hwnd) return FALSE;

while(GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);

return msg.wParam;

}

 

BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)

{

WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.cbClsExtra = wc.cbWndExtra = 0;

wc.lpfnWndProc = Proc;

wc.hInstance = hInstance;

wc.lpszClassName = szName;

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH)(brBackground +1);

wc.lpszMenuName = NULL;

return (RegisterClass(&wc) != 0);

}

 

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

static short cx, cy;

switch (msg)

{

case WM_SIZE:

{ cx=LOWORD(lParam); cy=HIWORD(lParam); return 0; }

case WM_PAINT:

{

PAINTSTRUCT ps;

HDC hdc = BeginPaint(hwnd, &ps);

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

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

SetTextAlign(hdc, TA_CENTER);

TextOut(hdc, cx/2, cy/2, szText, _tcslen(szText));

EndPaint(hwnd,&ps);

return 0;

}

case WM_LBUTTONDOWN:

{

_tcscpy(szText, TEXT("Нажата левая клавиша мыши"));

InvalidateRect(hwnd, NULL, TRUE);

return 0;

}

case WM_DESTROY: { PostQuitMessage(0); return 0;}

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

 

Произошли следующие изменения:

1. Переменная szText описана глобально. При "вызове" функции окна эта переменная сохраняет последнее присвоенное значение.

2. При обработке сообщения WM_LBUTTONDOWN в переменную szText записывается текст "Нажата левая клавиша мыши" и в область перерисовки добавляется вся рабочая область:

 

strcpy(szText, "Нажата левая клавиша мыши");

InvalidateRect(hwnd, NULL, TRUE);

 

Виды контекста отображения

Существуют следующие виды контекста отображения:

- общий;

- для класса окон;

- личный;

- родительский;

- для окна.

Способы получения и освобождения контекста отображения зависят от вида контекста. Каждый контекст имеет свои особенности и назначение.







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.