- •Часть 2 (продолжение): Прикладное программирование в Windows
- •Глава 8. Виртуальное окно: работа с текстом
- •8.1. Оконные координаты, цвета, отображение строк
- •Кодировка rgb-значений
- •Размеры системных метрик
- •8.2. Виртуальное окно
- •Способы заполнения прямоугольной области
- •8.3. Изменение шрифтов
- •Макроимена распространенных шрифтов
- •8.4. Создание собственных шрифтов
- •Глава 9. Программирование графики
- •9.1. Логическая система координат
- •Рекомендуемый самый яркий состав цветов
- •9.2. Пиксели, линии, дуги, прямоугольники, эллипсы и секторы
- •9.3. Работа с перьями и кистями
- •Типы линий, создаваемых пером
- •9.4. Технология виртуального окна
- •9.5. Режимы отображения и области вывода
- •Текущий режим отображения (mappind mode)
- •Глава 10. Работа с панелями инструментов
- •10.1. Общие элементы управления
- •Общие элементы управления
- •10.2. Подключение и инициализация общих элементов управления
- •10.3. Работа с панелью инструментов
- •Начальные состояния кнопок панели инструментов
- •Стиль кнопки определяется (значения поля fsStyle)
- •Сообщения к панели инструментов
- •10.4. Создание растрового изображения для панели инструментов
- •10.5. Включение подсказок
- •Глава 11. Спины, ползунки и индикаторы процессов
- •11.1. Работа со спином
- •Стили «up-down control»
- •Сообщения, которые можно посылать спину
- •11.2. Создание спина с «приятельским» окном
- •11.3. Работа с ползунком
- •Значения стилей для ползунка
- •Перечень сообщений, которые можно посылать ползунку
- •Перечень нотификационных сообщения ползунка
- •11.4. Индикатор процесса
- •Управляющие сообщения индикатору
- •Глава 12. Многозадачность: процессы и потоки
- •12.1. Создание нового процесса (отдельной задачи)
- •Разрешенные значения поля dwFlags
- •12.2. Многопотоковые программы
- •12.3. Работа с несколькими потоками
- •12.4. Синхронизация процессов и потоков: семафоры
- •12.5. Обработка событий
- •Глава 13. Приемы программного управления вычислительным процессом
- •13.1. Использование функций Проводника Explorer для работы в файловой системе
- •Управляющая информация Проводника
- •Режимы обработки файлов
- •13.2. Создание собственных динамических библиотек (dll-файлов)
- •13.3. Работа с буфером обмена Clipboard
- •Функции подсистемы Clipboard
- •Свойства выделяемого блока памяти
- •Форматы и типы данных
- •Литература
10.4. Создание растрового изображения для панели инструментов
Прежде чем использовать панели инструментов, нужно создать иконки, формирующие изображения на кнопках панели. Для этого понадобится графический редактор. Процесс создания растрового изображения идентичен в целом процессу рисования иконки (Вы делали это, создавая пользовательские иконки к примерам гл. 6). Однако тут есть и одно существенное отличие: с панелью инструментов может быть связано только одно растровое изображение, и оно должно содержать все изображения для кнопок. Таким образом, если панель инструментов должна содержать шесть кнопок, то и растр, связанный с ней, должен содержать шесть изображений. Например, если изображения кнопок имеют размер 1616 пикселей и панель инструментов содержит шесть кнопок, то растр, связанный с этой панелью, должен иметь высоту 16 и ширину 96 (1616) пикселей.
Для примеров программ, приведенных в этой главе, нам потребуется пять изображений для кнопок. Каждое из них имеет размер 1616 пикселей. Это означает, что Вам понадобится создать растровое изображение размером 8016 пикселей. На рис. 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. Окно диалога с панелью инструментов
