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

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. Диалог с панелью инструментов и подсказками