![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Взаимодействие прикладной программы и устройств в 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;
Глава 21. СОЗДАНИЕ ПРИЛОЖЕНИЙ 21.1. Обзор классов библиотеки MFC
|