Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows

.pdf
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
13.15 Mб
Скачать

Элементы управления главного окна

391

 

 

 

 

 

int dxBitmap,

// ширина изображения кнопки в пикселах

 

 

int dyBitmap,

// высота изображения кнопки в пикселах

 

 

UINT uStructSize

// размер структуры TBBUTTON

 

);

 

 

Стили панели инструментов определяются параметром ws. Он обязательно дол жен содержать флаги WS_CHILD и WS_VISIBLE. Могут также указываться и другие стандартные стили, например WS_BORDER. Кроме того, есть два специальных стиля, которые предназначены для панелей инструментов. Один из них, TBSTYLE_TOOLTIPS, задает поддержку всплывающих подсказок для кнопок панели инструментов. Вто рым стилем является TBSTYLE_WRAPABLE. Включение этого флага означает, что слиш ком длинные панели инструментов будут автоматически переходить на другую стро ку. Дополнительно могут указываться флаги основного стиля элементов управления общего пользования, приведенные в табл. 8.7. Если вы не указываете эти флаги, то по умолчанию применяется стиль CCS_TOP.

Параметру wID необходимо передать идентификатор панели инструментов. Вы можете использовать любой целочисленный идентификатор, но нужно следить за тем, чтобы это значение не повторялось среди идентификаторов, определен ных в файле resource.h.

Параметры dxButton и dyButton задают ширину и высоту самих кнопок в пиксе лах, а параметры dxBitmap и dyBitmap — ширину и высоту изображения кнопки в пикселах. Если вы не хотите особых приключений, то передайте нулевое значе ние для всех четырех параметров. В этом случае используются значения по умол чанию: dxButton=16, dyButton=16, dxBitmap=16, dyBitmap=15. На самом деле Windows выводит изображения кнопок, включающие рамки, шириной не менее dxButton+7 и высотой не менее dyButton+6 пикселов.

Изменение размеров панели инструментов

Когда панель инструментов инициализирована, ее размеры устанавливаются со ответственно текущим размерам родительского окна. Но если размер окна из меняется, то размер панели инструментов автоматически изменяться не будет. Особых неприятностей это не причиняет, однако при увеличении окна панель инструментов может оказаться слишком маленькой. Для решения этой пробле мы необходимо посылать сообщение TB_AUTOSIZE панели инструментов каждый раз, когда изменяются размеры родительского окна. Проще всего это сделать при обработке сообщения WM_SIZE:

SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0);

Реакция панели инструментов на это сообщение определяется флагами ее стиля (см. табл. 8.7). Например, панель инструментов со стилем CCS_TOP устанавливает свое местоположение и размеры. С другой стороны, панель инструментов со сти лем CCS_NORESIZE игнорирует это сообщение и требует явной установки ее место положения и размеров.

Поддержка элемента управления «подсказка»

Окно подсказки (Tooltip) — это маленькое окно, содержащее текст подсказки. Обыч но подсказка всплывает, когда курсор мыши оказывается в «горячей» (hot) обла сти, обслуживаемой данным элементом управления, задерживаясь в ней на неко торое время.

Элемент управления Tooltip хранит список «горячих» областей, которые для него ассоциируются с инструментами (tool). Каждая «горячая» область опреде

392

Глава 8. Элементы управления общего пользования

 

 

ляется как некоторая прямоугольная область в обслуживаемом окне или отно сится к окну целиком.

Существует две категории окон подсказки:

автономные элементы управления Tooltip, создаваемые при помощи функции CreateWindowEx как окна предопределенного оконного класса TOOLTIPS_CLASS;

элементы управления Tooltip, встроенные в панель инструментов.

Техника работы с ними различна. Первую категорию мы рассмотрим позже. Сейчас нас интересуют подсказки, встроенные в панель инструментов.

Если при создании панели инструментов указан стиль TBSTYLE_TOOLTIPS, то каж дая кнопка, добавляемая в панель инструментов, регистрирует инструмент под сказки. Когда подсказка становится активной, она посылает сообщение WM_NOTIFY с кодом уведомления WM_NEEDTEXT. Панель инструментов передает это сообще ние своему родительскому окну, которое должно его обработать, если необходи мо отобразить на экране текст подсказки.

При получении сообщения WM_NOTIFY параметр lParam содержит адрес струк туры типа TOOLTIPTEXT, имеющей следующее определение:

typedef struct {

 

NMHDR

hdr;

// информация об уведомительном сообщении

LPTSTR

lpszText;

// указатель на строку или строковый ресурс

WCHAR

szText[80]; // буфер для текста подсказки

HINSTANCE hinst;

// дескриптор экземпляра приложения, содержащего

 

 

// строковый ресурс

UINT

uflags;

// это поле не используется

} TOOLTIPTEXT;

 

Поле hdr содержит данные типа NMHDR, сопровождающие любое сообщение WM_NOTIFY. Эти данные включают информацию об элементе управления, послав шем сообщение, и информацию о самом сообщении:

typedef struct tagNMHDR {

HWND hwndFrom; //

дескриптор окна элемента управления

UINT idFrom;

// идентификатор элемента управления

UINT code;

//

код уведомления

} NMHDR;

Обрабатывая сообщение WM_NOTIFY, приложение обычно сохраняет значение параметра lParam в переменной lpTTT типа LPTOOLTIPTEXT, после чего проверяет зна чение поля lpTTT->hdr.code. Если оно равно TTN_NEEDTEXT, то это свидетельствует о поступлении запроса на отображение подсказки. Идентификатор кнопки, кото рая запросила отображение подсказки, хранится в поле lpTTT->hdr.idFrom. Зная этот идентификатор, приложение может выбрать необходимый текст для передачи окну подсказки.

Структура TOOLTIPTEXT позволяет использовать три способа передачи текста

вподсказку:

1.Копирование текста в буфер с адресом lpTTT->szText.

2.Запись адреса буфера, содержащего текст, в поле lpTTT->lpszText.

3.Запись идентификатора строки, хранящейся в ресурсе таблицы строк, в поле lpTTT->lpszText и одновременно запись дескриптора экземпляра приложения, содержащего строковый ресурс, в поле lpTTT->hinst.

Элементы управления главного окна

393

 

 

 

Реализация первых двух способов требует применения оператора switch, при помощи которого выбирается источник копирования текста в зависимости от зна чения поля lpTTT->hdr.idFrom.

Третий способ позволяет применить наиболее красивое решение. Оно основа но на довольно простой идее. Если все строки с текстами подсказок поместить в ресурс таблицы строк1 и присвоить им идентификаторы, совпадающие с иден тификаторами кнопок панели инструментов, то можно обойтись без оператора switch с гирляндой блоков case. Обработка сообщения WM_NOTIFY в этом случае будет выглядеть следующим образом:

case WM_NOTIFY:

lpTTT = (LPTOOLTIPTEXT)lParam;

if (lpTTT->hdr.code == TTN_NEEDTEXT) { lpTTT->hinst = GetModuleHandle(NULL);

lpTTT->lpszText = MAKEINTRESOURCE(lpTTT->hdr.idFrom);

}

break;

В результате такой обработки панель инструментов отобразит подсказку для кнопки с идентификатором lpTTT->hdr.idFrom. При этом содержимым подсказки будет строка из таблицы строк точно с таким же идентификатором.

Применим новые знания, вернувшись к разработке приложения ToolBar.

Продолжение разработки приложения ToolBar

Добавьте к приложению ресурс таблицы строк. Введите в таблицу следующие стро ки:

Идентификатор

Строка

 

 

ID_RECTANGLE

Прямоугольник

ID_RHOMB

Ðîìá

ID_ELLIPSE

Эллипс

ID_RED

Красная составляющая цвета

ID_GREEN

Зеленая составляющая цвета

ID_BLUE

Синяя составляющая цвета

ID_DARK

Темный цвет

ID_MEDIUM

Средний цвет

ID_LIGHT

Светлый цвет

 

 

В настоящий момент текст в файле ToolBar.cpp является точной копией текста файла MenuDemo1.cpp. Замените его текстом, приведенным в листинге 8.1.

Листинг 8.1. Проект ToolBar

//////////////////////////////////////////////////////////////////////

// ToolBar.cpp #include <windows.h> #include <commctrl.h> #include <stdio.h> #include "KWnd.h"

продолжение

1 Работа с ресурсом «Таблица строк» описана в главе 5.

394

 

Глава 8. Элементы управления общего пользования

 

Листинг 8.1 (продолжение)

#include

"resource.h"

#define W

200

// ширина фигуры

#define H

140

// высота фигуры

enum ShapeSize { MAX, MIN };

typedef struct {

 

int id_shape;

// идентификатор фигуры

BOOL fRed;

// компонент красного цвета

BOOL fGreen;

// компонент зеленого цвета

BOOL fBlue;

// компонент синего цвета

int id_bright;

// идентификатор яркости цвета

} ShapeData;

 

#define ID_TOOLBAR 201 #define NUM_BUTTONS 11 #define SEPARATOR_WIDTH 10

HWND hwndToolBar;

HWND InitToolBar(HWND hWnd);

void UpdateToolBar(ShapeData& sd);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //==================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

MSG msg;

KWnd mainWnd("ToolBar", hInstance, nCmdShow, WndProc, MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);

// Инициализация библиотеки "Common Control Library" INITCOMMONCONTROLSEX icc;

icc.dwSize = sizeof(INITCOMMONCONTROLSEX); icc.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&icc);

while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg);

}

return msg.wParam;

}

//==================================================================== HWND InitToolBar(HWND hWnd) {

HWND hToolBar;

int btnID[NUM_BUTTONS] = { ID_RECTANGLE, ID_RHOMB, ID_ELLIPSE, ID_SEP, ID_RED, ID_GREEN, ID_BLUE, ID_SEP, ID_DARK, ID_MEDIUM, ID_LIGHT };

int btnStyle[NUM_BUTTONS] = { TBSTYLE_BUTTON, TBSTYLE_BUTTON, TBSTYLE_BUTTON, TBSTYLE_SEP, TBSTYLE_CHECK, TBSTYLE_CHECK, TBSTYLE_CHECK, TBSTYLE_SEP, TBSTYLE_CHECKGROUP, TBSTYLE_CHECKGROUP, TBSTYLE_CHECKGROUP };

TBBUTTON tbb[NUM_BUTTONS];

Элементы управления главного окна

395

 

 

 

memset(tbb, 0, sizeof(tbb));

for (int i = 0; i < NUM_BUTTONS; ++i) { if (btnID[i] == ID_SEP)

tbb[i].iBitmap = SEPARATOR_WIDTH; else tbb[i].iBitmap = i;

tbb[i].idCommand = btnID[i]; tbb[i].fsState = TBSTATE_ENABLED; tbb[i].fsStyle = btnStyle[i];

}

hToolBar = CreateToolbarEx(hWnd,

WS_CHILD | WS_VISIBLE | WS_BORDER | TBSTYLE_TOOLTIPS, ID_TOOLBAR, NUM_BUTTONS, GetModuleHandle(NULL), IDR_TOOLBAR1, tbb, NUM_BUTTONS, 0, 0, 0, 0, sizeof(TBBUTTON));

return hToolBar;

}

//==================================================================== void UpdateToolBar(ShapeData& sd) {

SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_RED, sd.fRed); SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_GREEN, sd.fGreen); SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_BLUE, sd.fBlue);

SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_DARK, (sd.id_bright == ID_DARK));

SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_MEDIUM, (sd.id_bright == ID_MEDIUM));

SendMessage(hwndToolBar, TB_CHECKBUTTON, ID_LIGHT, (sd.id_bright == ID_LIGHT));

}

//==================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

HDC hDC; PAINTSTRUCT ps; RECT rect;

static HMENU hMenu; // дескриптор главного меню int x0, y0, x1, y1, x2, y2;

POINT pt[4];

static ShapeSize shapeSize = MIN; static BOOL bShow = TRUE;

static HBRUSH hBrush, hOldBrush;

char* itemResizeName[2] = { "Decrease!", "Increase!"};

int intensity[3] = { 85, 170, 255 }; // интенсивность RGB-компонентов цвета int brightness;

static ShapeData shapeData;

RECT rcTB;

// позиция и размеры окна hwndToolBar

int tbHeight;

// высота окна hwndToolBar

LPTOOLTIPTEXT lpTTT;

switch (uMsg)

{

case WM_CREATE:

hMenu = GetMenu(hWnd); SetMenuDefaultItem(GetSubMenu(hMenu, 0), IDM_OPEN, FALSE);

продолжение

396

Глава 8. Элементы управления общего пользования

 

 

Листинг 8.1 (продолжение)

CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE, IDM_HIDE_SHAPE, IDM_SHOW_SHAPE, MF_BYCOMMAND);

CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_RECTANGLE, ID_ELLIPSE, ID_RECTANGLE, MF_BYCOMMAND);

CheckMenuRadioItem(GetSubMenu(hMenu, 2), ID_DARK, ID_LIGHT, ID_DARK, MF_BYCOMMAND);

shapeData.id_shape = ID_RECTANGLE; shapeData.id_bright = ID_DARK;

// Создание панели инструментов hwndToolBar = InitToolBar(hWnd);

SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0); break;

//Настройка размеров панели инструментов case WM_SIZE:

SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0); break;

//Обработка запроса на вывод подсказки

case WM_NOTIFY:

lpTTT = (LPTOOLTIPTEXT)lParam;

if (lpTTT->hdr.code == TTN_NEEDTEXT) { lpTTT->hinst = GetModuleHandle(NULL);

lpTTT->lpszText = MAKEINTRESOURCE(lpTTT->hdr.idFrom);

}

break;

case WM_COMMAND:

switch (LOWORD(wParam))

{

/* Текст оператора из листинга 6.1 */

}

UpdateToolBar(shapeData); // обновление состояния кнопок InvalidateRect(hWnd, NULL, TRUE);

break;

case WM_PAINT:

hDC = BeginPaint(hWnd, &ps);

brightness = intensity[shapeData.id_bright - ID_DARK];

if (bShow) {

hBrush = CreateSolidBrush(RGB( shapeData.fRed? brightness : 0, shapeData.fGreen? brightness : 0, shapeData.fBlue? brightness : 0));

hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);

// Определение центра фигуры (x0, y0)

 

GetClientRect(hWnd, &rect);

 

// Ì î ä è ô è ö è ð î â à í í û é

ê î ä

//Учитываем уменьшение клиентской области èç-çà

//размещения панели инструментов GetWindowRect(hwndToolBar, &rcTB); tbHeight = rcTB.bottom - rcTB.top; x0 = rect.right / 2;

Элементы управления главного окна

397

 

 

 

 

y0 = tbHeight + (rect.bottom - tbHeight) / 2;

 

 

// Координаты прямоугольника и эллипса

 

 

if (shapeSize == MIN) {

 

 

 

x1

= x0

- W/2;

y1

= y0 - H/2;

 

 

x2

= x0

+ W/2;

y2

= y0 + H/2;

 

}

 

 

 

 

 

 

else {

 

 

 

 

 

x1

= 0;

 

y1

= tbHeight;

 

 

x2 = rect.right;

y2 = rect.bottom;

 

}

 

 

 

 

 

//Далее - заимствованный код из MenuDemo1

//Координаты ромба

pt[0].x = (x1 + x2) / 2;

pt[0].y = y1;

pt[1].x = x2;

pt[1].y = (y1 + y2) / 2;

pt[2].x = (x1 + x2) / 2;

pt[2].y = y2;

pt[3].x = x1;

pt[3].y = (y1 + y2) / 2;

switch (shapeData.id_shape) {

 

case ID_RECTANGLE:

 

 

Rectangle(hDC, x1, y1, x2, y2);

break;

case ID_RHOMB:

 

 

Polygon(hDC, pt, 4);

 

break;

case ID_ELLIPSE:

 

 

Ellipse(hDC, x1, y1, x2, y2);

break;

}

DeleteObject(SelectObject(hDC, hOldBrush));

}

EndPaint(hWnd, &ps); break;

case WM_DESTROY: PostQuitMessage(0); break;

default:

return DefWindowProc(hWnd, uMsg, wParam, lParam);

}

return 0;

}

//////////////////////////////////////////////////////////////////////

Впрограмме появились две новые (по сравнению с MenuDemo1) функции:

InitToolBar и UpdateToolBar.

Втеле функции InitToolBar создается и инициализируется панель инструментов hToolBar. Массив структур tbb типа TBBUTTON заполняется в цикле for. Обратите вни мание на то, что для первой группы из трех кнопок назначается стиль TBSTYLE_BUTTON, для второй группы — стиль TBSTYLE_CHECK, а для третьей — TBSTYLE_CHECKGROUP. Полю tbb[i].iBitmap всех кнопок, за исключением кнопок разделителей, присваивается индекс изображения в растровом образе панели инструментов. Для кнопок разде лителей это поле получает значение константы SEPARATOR_WIDTH.

При вызове функции CreateToolbarEx помимо основных стилей окна передается также стиль TBSTYLE_TOOLTIPS, что позволяет обеспечить поддержку встроенной подсказки для кнопок панели инструментов. Идентификатор панели инструмен тов ID_TOOLBAR, передаваемый функции, определен с помощью директивы #define. Функция InitToolBar вызывается из оконной процедуры WndProc в блоке обработ ки сообщения WM_CREATE.

398

Глава 8. Элементы управления общего пользования

 

 

Кнопки панели инструментов, имеющие стиль TBSTYLE_CHECK или TBSTYLE_ CHECKGROUP, требуют к себе повышенного внимания. Дело в том, что для них нуж но обеспечить «обратную связь» от меню. Если изменение опции выполнено пользователем через пункт меню, то состояние указанных кнопок необходимо об новить, иначе оно не будет синхронизировано с изменившимся состоянием при ложения. Эту подзадачу решает функция UpdateToolBar, посылая обновляемым кнопкам сообщение TB_CHECKBUTTON. Функция UpdateToolBar вызывается в конце блока обработки сообщения WM_COMMAND.

Обрабатывая сообщение WM_SIZE, приложение посылает панели инструмен тов сообщение TB_AUTOSIZE, чтобы панель изменила свои размеры в соответствии с изменившимися размерами родительского окна. Это же сообщение посылается сразу после вызова функции InitToolBar. В принципе, в данной программе это не обязательно. Но если вы создаете панель инструментов со стилем TBSTYLE_WRAPABLE, то приведенная инструкция обеспечивает нормальную настройку начального вида панели инструментов.

Обрабатывая сообщение WM_NOTIFY, приложение выбирает из таблицы строк текст подсказки для соответствующей кнопки панели инструментов. В результа те панель инструментов отображает требуемое окно подсказки. Приведенный код мы разбирали выше в разделе «Поддержка элемента управления «"подсказка"».

Код обработки сообщения WM_PAINT слегка модифицирован, чтобы учесть уменьшение видимой части клиентской области из за размещения панели инст рументов.

На рис. 8.5 показан вид работающего приложения ToolBar.

Рис. 8.5. Окно приложения ToolBar с активизированной подсказкой «Эллипс»

Панель инструментов с дополнительными текстовыми метками

Ранее говорилось, что кнопки панели инструментов помимо растровых изобра жений могут содержать и текстовые метки. Элемент управления Toolbar имеет встроенный список текстовых строк, который можно заполнять, отправляя эле менту сообщения TB_ADDSTRING. Кроме того, при инициализации массива tbb не обходимо присвоить полю tbb[i].iString соответствующий индекс (удобнее всего, если этот индекс будет совпадать с индексом изображения).

Элементы управления главного окна

399

 

 

 

Чтобы посмотреть, как все это работает, сделаем небольшую доработку преды дущей программы. Создайте новый проект с именем ToolBarWithText. Скопируйте из папки проекта ToolBar (см. листинг 8.1) в папку проекта ToolBarWithText файлы с расширениями .cpp, .h и .rc, скорректировав их имена заменой подстроки ToolBar на ToolBarWithText. Скопируйте также файл toolbar1.bmp. Добавьте эти файлы в со став проекта. Также добавьте к настройкам проекта на вкладке Link библиотеку comctl32.lib.

Отредактируйте текст файла ToolBarWithText.cpp так, чтобы он соответствовал листингу 8.2.

Листинг 8.2. Проект ToolBarWithText

//////////////////////////////////////////////////////////////////////

// ToolBarWithText.cpp

/* Директивы препроцессора, объявления типов и глобальных переменных из листинга 8.1 */

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //==================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

MSG msg;

KWnd mainWnd("ToolBarWithText", hInstance, nCmdShow, WndProc, MAKEINTRESOURCE(IDR_MENU1), 100, 100, 430, 300);

/* Здесь такой же текст, как и в листинге 8.1 */

return msg.wParam;

}

//==================================================================== HWND InitToolBar(HWND hWnd) {

/* Определения переменной hToolBar и массивов btnID и btnStyle

– из листинга 8.1 */ TBBUTTON tbb[NUM_BUTTONS]; memset(tbb, 0, sizeof(tbb));

for (int i = 0; i < NUM_BUTTONS; ++i) { if (btnID[i] == ID_SEP)

tbb[i].iBitmap = SEPARATOR_WIDTH; else tbb[i].iBitmap = i;

tbb[i].idCommand = btnID[i]; tbb[i].fsState = TBSTATE_ENABLED; tbb[i].fsStyle = btnStyle[i];

tbb[i].iString = i; // индекс строки в списке строк

}

hToolBar = CreateToolbarEx(hWnd,

WS_CHILD | WS_VISIBLE | WS_BORDER | TBSTYLE_TOOLTIPS, ID_TOOLBAR, NUM_BUTTONS, GetModuleHandle(NULL), IDR_TOOLBAR1, tbb, NUM_BUTTONS, 0, 0, 0, 0, sizeof(TBBUTTON));

// Заполнение списка строк в элементе управления Toolbar

продолжение

400

Глава 8. Элементы управления общего пользования

 

 

Листинг 8.2 (продолжение)

const char* str[NUM_BUTTONS] = { "Rect", "Rhomb", "Ellips", "", "Red", "Green", "Blue", "", "Dark", "Medium", "Light" };

for (i = 0; i < NUM_BUTTONS; ++i)

SendMessage(hToolBar, TB_ADDSTRING, 0, (LPARAM)str[i]);

return hToolBar;

}

//==================================================================== void UpdateToolBar(ShapeData& sd) {

/* Здесь такой же текст, как и в листинге 8.1 */

}

//==================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

/* Здесь такой же текст, как и в листинге 8.1 */

}

//////////////////////////////////////////////////////////////////////

Обратите внимание на изменения и дополнения в тексте функции InitToolBar. В цикле инициализации массива tbb добавлено присваивание tbb[i].iString = i.

После создания панели инструментов ее встроенный список строк наполняется текстовыми метками из массива str. Чтобы индексы этих строк совпадали с ин дексами изображений кнопок в ресурсе IDR_TOOLBAR1, массив str содержит пустые строки в тех позициях, которые соответствуют кнопкам разделителям.

Окно работающего приложения показано на рис. 8.6.

Рис. 8.6. Окно приложения ToolBarWithText

Рис. 8.7. Панель инструментов со стилем TBSTYLE_LIST