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

10.4. Создание растрового изображения для панели инструментов

 

Прежде чем использовать панели инструментов, нужно создать иконки, форми­рующие изображения на кнопках панели. Для этого понадобится графический редактор. Процесс создания растрового изображения идентичен в целом процессу рисования иконки (Вы делали это, создавая пользовательские иконки к примерам гл. 6). Однако тут есть и одно существенное отличие: с панелью инструментов может быть связано только одно растровое изображение, и оно должно содержать все изображения для кнопок. Таким образом, если панель инструментов должна содер­жать шесть кнопок, то и растр, связанный с ней, должен содержать шесть изображе­ний. Например, если изображения кнопок имеют размер 1616 пикселей и панель инструментов содержит шесть кнопок, то растр, связанный с этой панелью, должен иметь высоту 16 и ширину 96 (1616) пикселей.

 

Для примеров программ, приведенных в этой главе, нам потребуется пять изображений для кнопок. Каждое из них имеет размер 1616 пикселей. Это означает, что Вам понадобится создать растровое изображение размером 8016 пикселей. На рис. 10.1 показано растровое изображение, которое использовано в примерах этой главы в графическом редакторе (четвертое изображение намеренно оставлено пус­тым). Панель инструментов используется как альтернативное меню для работающей с графикой программы из гл. 9. Вы можете создать собственное растровое изображе­ние и сохранить его в файле с именем Toolbar.bmp.

Рис. 10.1. Панель инструментов в процессе графического

 редактирования

 

Пример 10-1. Программа работы с панелью инструментов.

 

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

 

// Демонстрация панели инструментов

#include <Windows.h>

#include <Commctrl.h>

#include <String.h>

#include <Stdio.h>

#include "Tb.h"

#define   NUMBUTTONS  6

void InitToolBar(); // Функция инициализации панели

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

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

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

HDC     memdc;      // DC виртуального окна

HBITMAP hbit;       // Растр - это виртуальное окно

HBRUSH  hbrush, hOldbrush; // Дескрипторы кистей

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

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

TBBUTTON tbButtons[NUMBUTTONS];

HWND tbwnd;         // Дескриптор панели инструментов

 

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,          // Имя класса

              "Работа с панелью инструментов Toolbar", 

                     WS_OVERLAPPEDWINDOW,// Стиль окна

                     CW_USEDEFAULT,    // Х-координата

                     CW_USEDEFAULT,    // Y-координата

                     CW_USEDEFAULT,     // Ширина окна

                     CW_USEDEFAULT,     // Высота окна

                     HWND_DESKTOP,  // Нет родит. окна 

                     NULL,                 // Нет меню

                     hThisInst, // Дескрип. приложения 

                     NULL); // Без дополит. аргументов

   // Загрузить акселераторы

   hAccel=LoadAccelerators(hThisInst,"MYMENU");

   InitToolBar(); // Инициализация панели инструментов

   InitCommonControls();  // Общие элементы управления

   tbwnd=CreateToolbarEx(hwnd,

                        WS_VISIBLE|WS_CHILD|WS_BORDER,

                        ID_TOOLBAR, NUMBUTTONS,

                        hThisInst, IDTB_BMP,

                        tbButtons,

                        NUMBUTTONS,

                        0, 0, 16, 16,

                        sizeof(TBBUTTON));

   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_SHOW: // Показать панель toolbar

               ShowWindow(tbwnd, SW_RESTORE);

               break;

            case ID_HIDE: // Спрятать панель toolbar

               ShowWindow(tbwnd, SW_HIDE);

               break;

            case ID_HELP:

               // Показать кнопку помощи в панели

               // инструментов как нажатую

               SendMessage(tbwnd, TB_CHECKBUTTON,

                          (WPARAM)ID_HELP, 

                          (LPARAM)1);

               MessageBox(hwnd,

                          "F2: линии\n"

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

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

                          "F5: сброс\n"

                          "F6: показать toolbar\n"

                          "F7: спрятать toolbar\n",

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

               // Показать кнопку помощи в панели

               // инструментов как отжатую

               SendMessage(tbwnd, TB_CHECKBUTTON,

                          (WPARAM)ID_HELP, 

                          (LPARAM)0);

               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;

   }

 

// Инициализация структур панели инструментов

void InitToolBar()

   {

   tbButtons[0].iBitmap=0;

   tbButtons[0].idCommand=ID_LINES;

   tbButtons[0].fsState=TBSTATE_ENABLED;

   tbButtons[0].fsStyle=TBSTYLE_BUTTON;

   tbButtons[0].dwData=0L;

   tbButtons[0].iString=0;

   tbButtons[1].iBitmap=1;

   tbButtons[1].idCommand=ID_RECTANGLES;

   tbButtons[1].fsState=TBSTATE_ENABLED;

   tbButtons[1].fsStyle=TBSTYLE_BUTTON;

   tbButtons[1].dwData=0L;

   tbButtons[1].iString=0;

 

   tbButtons[2].iBitmap=2 ;

   tbButtons[2].idCommand=ID_ELLIPSES;

   tbButtons[2].fsState=TBSTATE_ENABLED;

   tbButtons[2].fsStyle=TBSTYLE_BUTTON;

   tbButtons[2].dwData=0L;

   tbButtons[2].iString=0;

   tbButtons[3].iBitmap=3;

   tbButtons[3].idCommand=ID_RESET;

   tbButtons[3].fsState=TBSTATE_ENABLED;

   tbButtons[3].fsStyle=TBSTYLE_BUTTON;

   tbButtons[3].dwData=0L;

   tbButtons[3].iString=0;

   // Разделитель кнопок

   tbButtons[4].iBitmap=0;

   tbButtons[4].idCommand= 0;

   tbButtons[4].fsState=TBSTATE_ENABLED;

   tbButtons[4].fsStyle=TBSTYLE_SEP;

   tbButtons[4].dwData=0L;

   tbButtons[4].iString=0;

   tbButtons[5].iBitmap=4;

   tbButtons[5].idCommand=ID_HELP;

   tbButtons[5].fsState=TBSTATE_ENABLED;

   tbButtons[5].fsStyle=TBSTYLE_BUTTON;

   tbButtons[5].dwData=0L;

   tbButtons[5].iString=0;

   }

 

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

 

#include <Windows.h>

#include "Tb.h"

IDTB_BMP BITMAP "Toolbar.bmp"

MYMENU MENU

   {

   POPUP "&Нарисовать"

      {

      MENUITEM "&Линии",            ID_LINES

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

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

      }

   POPUP "&Разное"

      {

      MENUITEM "&C6pос",            ID_RESET

      MENUITEM "&Показать Toolbar", ID_SHOW

      MENUITEM "&Спрятать Toolbar", ID_HIDE

      }

   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_F6,   ID_SHOW,       VIRTKEY

   VK_F7,   ID_HIDE,       VIRTKEY

   VK_F1,   ID_HELP,       VIRTKEY

   }

 

И, наконец, потребуется файл Tb.h:

 

#define ID_LINES      100

#define ID_RECTANGLES 101

#define ID_ELLIPSES   102

#define ID_SHOW       103

#define ID_HIDE       104

#define ID_RESET      105

#define ID_HELP       106

#define ID_TOOLBAR    200

#define IDTB_BMP      300

 

Большая часть этой программы Вам уже знакома. Приведем короткое описание остальной ее части. Вся информация, относящаяся к панели инструментов, хранится в массиве tbButtons. Инициализацию этого массива выполняет функция InitToolBar(). Заметьте, что структура ID_HIDE определяет промежуток между кнопками. В функ­ции WinMain() вызывается функция инициализации общих элементов управления InitCommonControls(). После этого создается панель инструментов и ее дескриптор сохраняется в переменной tbwnd.

Каждая кнопка панели инструментов соответствует определенной команде меню. Поэтому при нажатии такой кнопки соответствующая команда будет передана программе в параметрах сообщения WM_COMMAND точно так же, как если бы была выбрана команда меню. Фактически эти сообщения обрабатываются в одних и тех же операторах case.

Поскольку панель инструментов является окном, она может быть скрыта или отображена, как и любое другое окно, при помощи функции ShowWindow(). Панель инструментов может быть спрятана по команде Спрятать Toolbar в меню Опции. Чтобы она затем вновь появилась, в том же меню нужно выбрать команду Показать Toolbar. Поскольку панель инструментов уменьшает размер рабочей области окна, всегда следует предоставлять пользователю возможность убирать ее с экрана. Как видно из программы, делается это достаточно просто.

 

Наконец, обратите внимание на фрагмент программы, обрабатывающий команду ID_HELP. При выборе команды Помощь (в меню или нажатием соответствующей кнопки панели инструментов) кнопка помощи в панели инструментов нажимается вручную при помощи посылки сообщения TB_CHECKBUTTON. Когда же пользо­ватель закрывает окно сообщения со справочной информацией, кнопка вручную освобождается. Таким образом, кнопка помощи остается нажатой все время, пока окно сообщения находится на экране. Это пример того, как из программы можно управлять панелью инструментов. Пример окна, создаваемого этой программой, показан на рис. 10.2.

Рис. 10.2. Окно диалога с панелью инструментов