Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основы программирования для информатиков и инженеров. Часть 2 Прикладное программирование в Windows.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
603.45 Кб
Скачать

9.4. Технология виртуального окна

 

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

 

Пример 9-1. Демонстрация основных графических функций:

 

// Демонстрация основных графических функций

#include <Windows.h>

#include <String.h>

#include <Stdio.h>

#include "Graph.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, hOldbrush; // Дескрипторы кистей

HPEN    hOldpen;    // Дескриптор прежнего пера

HPEN hRedpen,hGreenpen,hBluepen,hYellowpen; // Перья

 

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;

   PAINTSTRUCT paintstruct;

   switch(message)

      {

      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);

         // Создать новые перья

         hRedpen  =CreatePen(PS_SOLID,1,RGB(255,0,0));

         hGreenpen=CreatePen(PS_SOLID,1,RGB(0,255,0));

         hBluepen =CreatePen(PS_SOLID,1,RGB(0,0,255));

         hYellowpen=

                 CreatePen(PS_SOLID,1,RGB(255,255,0));

         hOldpen=(HPEN)SelectObject(memdc,hRedpen);

         SelectObject(memdc,hOldpen); // Старое перо

         ReleaseDC(hwnd,hdc);

         break;

      case WM_COMMAND:

         switch(LOWORD(wParam))

            {

            case ID_LINES:

               // Вывести 2 черных пикселя

               SetPixel(memdc,40,14,RGB(0,0,0));

               SetPixel(memdc,40,15,RGB(0,0,0));

               // Вывести прямую линию

               LineTo(memdc,100,50);

               MoveToEx(memdc,100,50,NULL);

               // Установить зеленое перо

               hOldpen=

                  (HPEN)SelectObject(memdc,hGreenpen);

               LineTo(memdc,200,100);

               // Установить желтое перо

               SelectObject(memdc,hYellowpen);

               LineTo(memdc,0,200);

               // Установить синее перо

               SelectObject(memdc,hBluepen);

               LineTo(memdc,200,200);

               // Установить красное перо

               SelectObject(memdc,hRedpen);

               LineTo(memdc,0,0);

               // Вернуться к прежнему перу

               SelectObject (memdc, hOldpen);

               // Провести дугу

               Arc(memdc,0,0,300,300,0,50,200,50);

               // Показать линии, отрезающие дугу

               MoveToEx(memdc,150,150,NULL);

               LineTo(memdc,0,50);

               MoveToEx(memdc,150,150,NULL);

               LineTo(memdc,200,50);

               InvalidateRect(hwnd,NULL,1);

               break;

            case ID_RECTANGLES:

               // Прямоугольники не заполняются

               hOldbrush=(HBRUSH)SelectObject(memdc,

                        GetStockObject(HOLLOW_BRUSH));

               // Рисуем прямоугольники

               Rectangle(memdc,50,50,300,300);

               RoundRect(memdc,125,125,220,240,15,13);

               // Выбираем красное перо

               SelectObject(memdc,hRedpen);

               Rectangle(memdc,100,100,200,200);

               SelectObject(memdc,hOldpen);

               // Вернуться к прежнему перу

               // Восстановить прежнюю кисть

               SelectObject(memdc,hOldbrush);

               InvalidateRect(hwnd,NULL,1);

               break;

            case ID_ELLIPSES:

               // Создаем синюю кисть

               hbrush=CreateSolidBrush(RGB(0,0,255));

               hOldbrush=

                   (HBRUSH)SelectObject(memdc,hbrush);

               // Рисуем эллипсы с синим заполнением

               Ellipse(memdc,50,200,100,280);

               Ellipse(memdc,75,25,280,100);

               // Рисуем красным пером, зеленой кистью

               SelectObject(memdc,hRedpen);

               DeleteObject(hbrush); // Удалить кисть

               // Создать зеленую кисть

               hbrush=CreateSolidBrush(RGB(0,255,0));

               SelectObject(memdc,hbrush);

               Ellipse(memdc,100,100,200,200);

               // Рисуем сектор

               Pie(memdc,200,200,340,340,225,200,

                   200,250);

               SelectObject(memdc,hOldpen);

               // Вернуться к прежнему перу

               SelectObject(memdc,hOldbrush);

               // Восстановить прежнюю кисть и удалить

               DeleteObject(hbrush);  // зеленую кисть

               InvalidateRect(hwnd,NULL,1);

               break;

            case ID_RESET:

               // Восстановить текущую позицию в 0,0

               MoveToEx(memdc,0,0,NULL);

               // Стереть изображение при помощи

               // перерисовки фона

               PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

               InvalidateRect(hwnd,NULL,1);

               break;

            case ID_HELP:

               MessageBox(hwnd,

                          "F2: линии\n"

                          "FЗ: прямоугольники\n"

                          "F4: эллипсы\n"

                          "F5: сброс",

                          "Работа с графикой",MB_OK); 

               break;

            }

         break;

      case WM_PAINT: // Перерисовка окна

         // Получить DC */

         hdc=BeginPaint(hwnd,&paintstruct);

         // Теперь копируем растр из памяти на экран

         BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);

         // Освободить DC

         EndPaint(hwnd,&paintstruct);

         break;

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

         // Удалить созданные перья

         DeleteObject(hRedpen);

         DeleteObject(hGreenpen);

         DeleteObject(hBluepen);

         DeleteObject(hYellowpen);

         DeleteDC(memdc);  // Удалить виртуальное окно

         PostQuitMessage(0);

         break;

      default:

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

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

         // умолчанию

         return DefWindowProc(hwnd,message,

                              wParam,lParam);

      }

   return 0;

   }

 

Для этой программы потребуется следующий файл ресурсов:

 

#include <Windows.h>

#include "Graph.h"

MYMENU MENU

   {

   MENUITEM "&Линии", ID_LINES

   MENUITEM "&Прямоугольники",ID_RECTANGLES

   MENUITEM "&Эллипсы",ID_ELLIPSES

   MENUITEM "&Cбpоc",ID_RESET

   MENUITEM "Помощь",ID_HELP

   }

MYMENU ACCELERATORS

   {

   VK_F2, ID_LINES,      VIRTKEY

   VK_F3, ID_RECTANGLES, VIRTKEY

   VK_F4, ID_ELLIPSES,   VIRTKEY

   VK_F5, ID_RESET,      VIRTKEY

   VK_F1, ID_HELP,       VIRTKEY

   }

 

Потребуется также файл определений Graph.h:

 

#define ID_LINES      100

#define ID_RECTANGLES 101

#define ID_ELLIPSES   102

#define ID_RESET      103

#define ID_HELP       104

 

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