Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СОВРЕМЕННЫЕ МЕТОДЫ ПРОГРАММИРОВАНИЯ.docx
Скачиваний:
0
Добавлен:
03.01.2020
Размер:
797.27 Кб
Скачать

20.6. Ресурсы Windows

Для уменьшения объема основного модуля программы данные некоторых объектов Windows, используемых в программе, помещаются в отдельный файл, который называется файлом ресурсов. Объекты Windows, описания которых хранятся в файле ресурсов, называются ресурсами. К ресурсам относят диалоговые панели, меню, панели инструментов, акселераторы (горячие клавиши), строки, иконки, курсоры, рисунки в формате bmp.

Файл ресурсов представляет собой текстовый файл и имеет тип *.rc. Возможны два способа редактирования файла ресурсов: при помощи простейшего текстового редактора или специального графического редактора ресурсов. Для редактирования файла ресурсов в текстовом редакторе пользователь должен знать язык описания ресурсов.

Приведем пример описания диалоговой панели, в которую включены строка заголовка, системное меню, кнопка:

/////////////////////////////////////////////////////////////////////////////

//

//Dialog

//

IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95

STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU

CAPTION "Заголовок окна"

FONT 8, "MS Sans Serif"

BEGIN

PUSHBUTTON "OK1",IDC_OK,123,23,32,16,BS_CENTER | BS_VCENTER

END

/////////////////////////////////////////////////////////////////////////////

Графический редактор ресурсов упрощает процесс редактирования файла ресурсов, так как не требует знания языка описания ресурсов. Редактор входит в состав инструментальной среды для разработки программ для Windows, при этом пользователь выполняет редактирование ресурса визуально, а текст rc-файла среда формирует автоматически.

Компиляция файла ресурсов выполняется специальным компилятором, в результате компиляции создается файл *.res.

Каждый ресурс имеет имя или идентификатор. Имя ресурса представляет собой строку и записывается в двойных кавычках, например, "Menu1". Идентификатор ресурса сопоставляется с некоторым числовым значением и записывается в файл resource.h. Приведем строчку из этого файла, в которой объявляется идентификатор диалоговой панели IDD_DIALOG1 (идентификаторы ресурсов принято записывать прописными буквами):

#define IDD_DIALOG1 100

Когда в программу добавляется новый ресурс или объект Windows, среда Visual C++ автоматически редактирует файл resource.h.

Файл resource.h подключается к каждому модулю, использующему ресурсы.

20.7. Взаимодействие прикладной программы и устройств в Windows

В операционной системе Windows запрещены операции, непосредственно передающие информацию внешним устройствам компьютера; этот запрет распространяется также и на графические устройства, например, монитор, принтер. Информация для графического устройства передается так называемому контексту устройства. Контекст устройства DC (Device Context) используется для логического представления в программе какого-либо внешнего графического устройства. Контекст устройства хранит информацию о пере, кисти, шрифте, растровом изображении, в соответствии с которой происходит формирование изображения, передаваемого дальше на графическое устройство. Контекст устройства может быть не связан с физическим устройством – данные из контекста могут быть адресованы логическим устройствам, например, метафайл Windows – совокупность структур, в которых хранится изображение в формате, зависимом от конкретного устройства; bitmap – совокупность точек растра, образующих изображение.

Контекст устройства представляет собой выделенную область оперативной памяти размером 64 кбайт; в программах, использующих библиотеку Win32 API, контекст устройства доступен через дескриптор контекста устройства HDC. Прежде чем использовать контекст, его надо запрашивать. Когда программа запрашивает контекст, операционная система передает ей дескриптор (хэндл) контекста устройства, т. е. адрес размещения контекста в оперативной памяти. По завершении работы с контекстом устройства его надо освободить.

В интерфейс Win32 API включены:

     контекст дисплея, используемый для графических операций на мониторе;

     контекст принтера, поддерживающий графические операции на принтере;

     контекст в памяти, поддерживающий графические операции над растровыми изображениями;

     информационный контекст, обеспечивающий чтение данных с графических устройств.

Рассмотрим наиболее часто используемый контекст дисплея, так как любые операции рисования в окнах, перерисовка окон при их перекрытии, свертывании, развертывании выполняются в контексте дисплея.

Существуют два варианта контекста дисплея.

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

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

Для перерисовки окна, соответствующей сообщению WM_PAINT, дескриптор контекста дисплея создается с помощью функции BeginPaint(); после завершения перерисовки контекст освобождается функцией EndPaint().

Для рисования на поверхности окна при получении любого другого сообщения, кроме WM_PAINT, контекст дисплея создается функцией GetDC() или GetDCEx(); освобождение контекста выполняется функциями ReleaseDC() или ReleaseDCEx().

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

Если приложение использует приватный контекст, то получить дескриптор контекста можно так же, как и в случае общего контекста, однако освобождать его не надо. Система сама освобождает контекст при закрытии окна.

Выбор варианта контекста дисплея происходит при создании класса главного окна. Для выбора приватного контекста при заполнении структуры типа WNDCLASS (WNDCLASSEX) следует указать стиль окна CS_OWNDC, иначе приложение будет использовать общий контекст.

Стиль окна, использующего приватный контекст, задается следующим образом:

WinExam1.style = CS_OWNDC|CS_HREDRAW|CS_VREDRAW;

Оконная процедура обеспечивает обработку трех сообщений: WM_CREATE, WM_COMMAND и WM_DESTROY. Последнее сообщение посылается при завершении работы программы. Сообщение WM_CREATE посылается при создании окна. Сообщение WM_COMMAND программа получает при выборе пользователем команды меню или при нажатии кнопок. В нашем примере в окне размещены две кнопки. Создание кнопок происходит с помощью функции CreateWindow() при инициализации окна, т. е. во время обработки сообщения WM_CREATE.

Получение дескриптора контекста дисплея выполняется при обработке сообщения WM_COMMAND, возникающего при нажатии одной из кнопок, размещенных в окне, для этого используется функция GetDC():

#include "windows.h"

HINSTANCE hInst;

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

int APIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

hInst=hInstance;

//Создание класса главного окна

WNDCLASSEX WinExam1;

WinExam1.cbSize=sizeof(WNDCLASSEX);

WiExam1.style=CS_OWNDC|CS_HREDRAW|CS_VREDRAW;

WinExam1.lpfnWndProc=WndProc;

WinExam1.cbClsExtra=0;

WinExam1.cbWndExtra=0;

WinExam1.hInstance=hInst;

WinExam1.hIcon=LoadIcon(hInst, IDI_APPLICATION);

WinExam1.hCursor=LoadCursor(hInst,

IDC_APPSTARTING);

WinExam1.hbrBackground=HBRUSH(COLOR_WINDOW+1);

WinExam1.lpszMenuName=NULL;

WinExam1.lpszClassName="Examp1Win";

WinExam1.hIconSm=LoadIcon(hInst,

IDI_APPLICATION);

//Регистрация класса главного окна

RegisterClassEx(&WinExam1);

//Создание главного окна

HWND hWnd1=CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,

"Examp1Win","Child windows 1",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,0,CW_USEDEFAULT,

0,NULL,NULL,hInst,NULL);

//Отображение главного окна

ShowWindow(hWnd1, SW_SHOW);

//Цикл обработки сообщений

MSG Msg;

while (GetMessage(&Msg,(HWND)NULL,0,0))

{

DispatchMessage(&Msg);

}

return 0;

}

//Оконная процедура обработки сообщений

LRESULT CALLBACK WndProc(HWND hWnd,UINT Msg,

WPARAM wParam,LPARAM lParam)

{

HDC dc;

switch (Msg)

{

case WM_CREATE:

//Создаем две кнопки

CreateWindow("BUTTON","Первая кнопка",

WS_CHILD|BS_PUSHBUTTON|WS_VISIBLE,

0,0,160,20,hWnd,0,hInst,NULL);

CreateWindow("BUTTON","Вторая кнопка",

WS_CHILD|BS_PUSHBUTTON|WS_VISIBLE,

0,25,160,20,hWnd,(HMENU)1,hInst,NULL);

break;

//Обработка сообщений - уведомлений

case WM_COMMAND:

dc=GetDC(hWnd); //Получение контекста дисплея

switch(LOWORD(wParam))

{

case 0: //Пришло сообщение от первой кнопки

TextOut(dc,170,0,"Нажата первая кнопка",20);

break;

case 1:

TextOut(dc,170,0,"Нажата вторая кнопка",20);

break;

};

break;

case WM_DESTROY:

//Сообщаем системе о завершении программы

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd,Msg,wParam,lParam);

}

return 0;