- •Часть 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.5. Включение подсказок
Работая с Windows, Вы, вероятно, заметили, что при задержке указателя мыши на несколько секунд на кнопках некоторых панелей инструментов автоматически появляются небольшие текстовые окошки, содержащие краткое описание назначения кнопок. Они называются подсказками (tooltips). И хотя это и не является обязательным, лучше все-таки иметь такие подсказки, поскольку многим пользователям они помогают ориентироваться среди множества кнопок. В этом разделе будет рассказано, как это делается.
Для включения подсказок при создании панели инструментов следует задать стиль TBSTYLE_TOOLTIPS. Это разрешает посылку сообщения WM_NOTIFY при нахождении указателя мыши над кнопкой панели инструментов в течение более чем одной секунды. В сообщении WM_NOTIFY параметр lParam содержит указатель на структуру TOOLTIPTEXT, которая определяется следующим образом:
typedef struct
{
NMHDR hdr;
LPSTR lpszText;
char szText[80];
HINSTANCE hinst;
UINT uFlags;
}
TOOLTIPTEXT;
Первым полем структуры TOOLTIPTEXT является структура NMHDR:
typedef struct tagNMHDR
{
HWND hwndFrom; // Дескриптор элемента управления
UINT idFrom; // Идентификатор элемента управления
UINT code; // Код, передаваемый в сообщении
}
NMHDR;
Если запрашивается подсказка, то поле code будет содержать TTN_NEEDTEXT, a поле idFrom – идентификатор кнопки, для которой требуется подсказка. Текст подсказки можно задать одним из трех способов: скопировать текст в поле szText структуры TOOLTIPTEXT, либо записать в поле lpszText указатель на текстовую строку, либо, наконец, задать идентификатор ресурса строки. В последнем случае идентификатор строки записывается в поле lpszText, а поле hinst содержит дескриптор приложения, содержащего ресурс. Конечно, простейший способ – это записать в lpszText указатель на строку, определенную в программе. Следующий фрагмент обрабатывает запросы подсказок в нашей программе вывода графики:
LPTOOLTIPTEXT TTtext;
//...
case WM_NOTIFY: // Обработка запроса от подсказки
TTtext=(LPTOOLTIPTEXT)lParam;
if(TTtext->hdr.code == TTN_NEEDTEXT)
{
switch( TTtext->hdr.idFrom )
{
case ID_LINES:
TTtext->lpszText="Линии";
break;
case ID_RECTANGLES:
TTtext->lpszText="Прямоугольники";
break;
case ID_ELLIPSES:
TTtext->lpszText="Эллипсы";
break;
case ID_RESET:
TTtext->lpszText="Сброс";
break;
case ID_HELP:
TTtext->lpszText="Помощь";
break;
}
break;
После того как текст подсказки определен, подсказка отображается автоматически при возврате управления к Windows, и программе больше не нужно выполнять никаких действий. Как видите, подсказки хорошо автоматизированы и просты в использовании.
Пример 10-2. Программа создания Toolbar с подсказками.
В этом разделе приводится полный текст программы создания панели инструментов и подсказок. В ней используются те же файлы ресурсов и определений, что и в предыдущей версии программы.
// Демонстрация панели инструментов с подсказками
#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|
TBSTYLE_TOOLTIPS,
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;
LPTOOLTIPTEXT TTtext;
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_NOTIFY: // Обработка запросов подсказок
TTtext=(LPTOOLTIPTEXT)lParam;
if(TTtext->hdr.code == TTN_NEEDTEXT)
{
switch(TTtext->hdr.idFrom)
{
case ID_LINES:
TTtext->lpszText="Линии";
break;
case ID_RECTANGLES:
TTtext->lpszText="Прямоугольники";
break;
case ID_ELLIPSES:
TTtext->lpszText="Эллипсы";
break;
case ID_RESET:
TTtext->lpszText="Сброс";
break;
case ID_HELP:
TTtext->lpszText="Помощь";
break;
}
}
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;
}
Пример окна такой программы показан на рис. 10.3.
В следующей главе речь вновь пойдет об общих элементах управления, поддерживаемых в Windows: мы рассмотрим спин (up-down control, spin control), ползунок (track bar) и индикатор (progress bar).
Рис. 10.3. Диалог с панелью инструментов и подсказками
