лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows
.pdfЭлементы управления главного окна |
411 |
|
|
|
|
// Функция отладочной печати (аналог макроса TRACE в библиотеке MFC)
#define N 512
void TRACE(LPCTSTR szFormat, ...)
{
va_list args; va_start(args, szFormat); int nBuf;
char szBuffer[N];
nBuf = _vsnprintf(szBuffer, N, szFormat, args);
if (nBuf < 0) {
MessageBox(NULL, "Слишком длинная строка для TRACE!", "Ошибка", MB_OK | MB_ICONSTOP);
szBuffer[N-2] = '\n'; szBuffer[N-1] = 0;
}
OutputDebugString(szBuffer);
va_end(args);
}
//////////////////////////////////////////////////////////////////////
// ToolTip.cpp #include <windows.h> #include <commctrl.h> #include <stdio.h> #include "KWndEx.h" #include "resource.h"
/* Определения макросов, типов и глобальных переменных из листинга 8.3 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //==================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("ToolTip", hInstance, nCmdShow, WndProc, MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
// Добавление окна подсказки AddTooltip (mainWnd.GetHWnd(),
"Это клиентская область главного окна приложения");
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg);
}
return msg.wParam;
}
//====================================================================
продолжение
Элементы управления главного окна |
413 |
|
|
|
|
Обратите внимание на использованный способ получения дескриптора окна редактирования, входящего в состав комбинированного списка.
Функция TRACE, имеющая следующий прототип:
void TRACE(LPCTSTR szFormat, ...)
предназначена для отладочного вывода в окно Output. Функция принимает пе ременное количество аргументов, и обращение к ней похоже на обращение к функции printf из библиотеки С. Реализация функции основана на использо вании функции OutputDebugString.
Программисты, написавшие хотя бы один проект с библиотекой MFC, сразу оце нивают удобство использования макроса TRACE в режиме отладки. К сожалению, Win32 API этот макрос не поддерживает. Но теперь, подключив к любому проекту файлы KwndEx.h и KwndEx.cpp, вы не будете чувствовать себя ущемленными!
Чтобы использовать отладочную печать, не забудьте выполнить два условия. Во первых, проект должен компилироваться в отладочной конфигурации (Win32 Debug). Во вторых, программа должна запускаться на выполнение в режиме от ладки при помощи команды меню Start Debug Go или клавиши F5.
Откомпилируйте проект и проверьте, как работает подсказка для комбиниро ванного списка в панели инструментов и для главного окна приложения.
Проверьте также работу функции отладочного вывода TRACE. В блок обработ ки сообщения WM_NOTIFY можно добавить следующую инструкцию:
TRACE("uMsg = %04X, wParam = %08X, lParam = %08X\n", uMsg, wParam, lParam);
Теперь, если запустить программу в режиме отладки, благодаря функции TRACE в окно Output будут выводиться значения uMsg, wParam и lParam при каждом по ступлении в оконную процедуру сообщения WM_NOTIFY. Отладочная печать будет выглядеть примерно так:
uMsg = 004E, wParam = 000000C9, lParam = 0012F768 uMsg = 004E, wParam = 00009C48, lParam = 00135AC0 uMsg = 004E, wParam = 00009C48, lParam = 0012FA34
. . . . . . . . . . . . . . . . . . . . . . . . .
Строка состояния
Строка состояния (status bar) — это окно, обычно располагающееся в нижней части главного окна приложения и предназначенное для информирования поль зователя о текущем состоянии программы, о выполняемых операциях и режи мах. Довольно часто строка состояния используется для отображения подроб ного описания пунктов меню при наведении на них курсора мыши. Когда меню не просматривается, приложение может выводить другую справочную инфор мацию.
Для создания строки состояния следует использовать функцию CreateStatusWindow:
hwndStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWndParent, ID_STATUS_BAR);
В процессе своего выполнения эта функция вызывает функцию CreateWindow, которая создает дочернее окно с родительским окном hWndParent, идентификато ром ID_STATUS_BAR и выводит в окно строки состояния текст, заданный вторым параметром. В данном примере будет использоваться пустая строка.
414 |
Глава 8. Элементы управления общего пользования |
|
|
По умолчанию окно строки состояния имеет дополнительные стили CCS_BOTTOM (см. табл. 8.7) и SBARS_SIZEGRIP. Стиль SBARS_SIZEGRIP задает наличие «манипу лятора размера» в правом углу строки состояния. Этот декоративный элемент соз дает область, за которую можно ухватиться при изменении размера окна прило жения.
Строка состояния может работать в двух режимах:
Стандартный, или многочастный, режим (Multiple Part Status Bars), в кото ром строка состояния разбивается на несколько частей (полей). В каждом поле выводится отдельная строка текста.
Простой режим (Simple Mode Status Bars), в котором строка состояния реали зована как единый элемент и отображает только одну строку. Простой режим чаще всего используется при отображении справочной информации для пунк тов меню, когда пользователь перемещается по меню.
Переключение между режимами осуществляется посылкой сообщения SB_SIMPLE:
SendMessage(hwndStatusBar, SB_SIMPLE, fMode, 0);
Когда параметр fMode имеет значение TRUE, то устанавливается простой режим. При использовании значения FALSE строка состояния будет работать в стандарт ном (многочастном) режиме.
Разделение строки состояния на поля
Если строка состояния используется в стандартном режиме, то вы должны разде лить ее на отдельные поля при помощи отсылки сообщения SB_SETPARTS:
SendMessage(hwndStatusBar, SB_SETPARTS, nParts, (LPARAM)aWidths);
Здесь параметр nParts задает число полей, а aWidths — адрес целочисленного массива, каждый элемент которого определяет позицию (в клиентских координа тах) правой границы соответствующего поля. Если элемент массива aWidths равен –1, то границей соответствующего поля считается правая граница строки состоя ния.
Обычно в каждое поле строки состояния выводится отдельное текстовое сооб щение. Но вы можете также разместить в любом поле другой элемент управле ния, например индикатор процесса (Progress bar). При таком размещении полезно знать клиентские координаты этого поля, которые могут быть получены при по мощи отправки сообщения SB_GETRECT:
SendMessage(hwndStatusBar, SB_GETRECT, iPart, (LPARAM)&rect);
где iPart — номер поля, отсчитываемый от нуля, а rect — структура типа RECT, при нимающая координаты поля.
Вывод текстового сообщения
Для отображения текста в строке состояния посылается сообщение SB_SETTEXT:
SendMessage(hwndStatusBar, SB_SETTEXT, wParam, (LPARAM)szText);
где szText — указатель на C строку, а wParam задает номер поля в строке состояния и графический стиль для этого поля.
Значение параметра wParam может быть задано в виде объединения iPart | uType. Если строка состояния работает в стандартном режиме, то iPart содержит но мер поля. Если используется простой режим, то параметр iPart должен иметь зна
чение 255.
Элементы управления главного окна |
417 |
|
|
|
|
Таким образом, для меню первого уровня с нулевым индексом (submenuID=0) входящие в него пункты подменю получат номера 100, 101, 102 и т. д. Для меню первого уровня с единичным индексом входящие в него пункты подменю полу чат номера 200, 201, 202 и т. д. Такие же идентификаторы мы будем использовать и для строк в таблице строк приложения.
Из принятого нами ограничения на количество уровней меню вытекает, что все пункты второго (последнего) уровня являются пунктами командами и поэто му имеют уникальные идентификаторы.
Получив в результате обработки сообщения WM_MENUSELECT уникальный иден тификатор пункта меню itemID, мы можем извлечь из таблицы строк соответству ющую символьную строку в текстовый буфер text, а затем отобразить этот текст в строке состояния, которая работает в простом режиме. Это может быть реализо вано следующими инструкциями:
SendMessage(hwndStatusBar, SB_SIMPLE, TRUE, 0); LoadString(GetModuleHandle(NULL), itemID, text, 200); SendMessage(hwndStatusBar, SB_SETTEXT, 255, (LPARAM)text);
Для демонстрации предложенной технологии разработаем приложение StatusBar, являющееся модификацией приложения ToolBar. В результате доработки к про грамме будет добавлена строка состояния, работающая в простом и стандартном режимах.
Приложение StatusBar
Создайте новый проект с именем StatusBar. Скопируйте из папки проекта ToolBar
(см. листинг 8.1) в папку проекта StatusBar файлы ToolBar.cpp, ToolBar.rc и resource.h, скорректировав имена первых двух файлов заменой подстроки ToolBar на StatusBar. Скопируйте также файл toolbar1.bmp. Наконец, скопируйте из папки проекта ToolTip (см. листинг 8.4) файлы KWndEx.h и KWndEx.cpp.
Добавьте скопированные файлы в состав проекта. К настройкам проекта на вкладке Link нужно добавить библиотеку comctl32.lib.
Теперь откройте вкладку ResourceView в окне Workspace. В списке ресурсов от кройте папку String table и вызовите редактор таблицы строк двойным щелчком мыши на элементе String table.
Добавьте в таблицу строк следующие строки:
Идентификатор Строка
0Операции с файлами
1Параметры просмотра
2Параметры фигуры
300Тип фигуры
301Цвет фигуры
IDM_OPEN |
Открыть файл |
IDM_CLOSE |
Закрыть файл |
IDM_SAVE |
Сохранить файл |
IDM_EXIT |
Выход из программы |
IDM_SHOW_SHAPE |
Показать рисунок |
IDM_HIDE_SHAPE |
Скрыть рисунок |
IDM_RESIZE |
Изменение размеров фигуры |
IDM_ABOUT |
Информация о программе |
|
|
418 |
Глава 8. Элементы управления общего пользования |
|
|
Обратите внимание на целочисленные идентификаторы 0, 1, 2, 300, 301, назна ченные в соответствии с описанной выше процедурой однозначной идентифика ции пунктов подменю.
Отредактируйте текст файла StatusBar.cpp так, чтобы он соответствовал лис тингу 8.5.
Листинг 8.5. Проект StatusBar
//////////////////////////////////////////////////////////////////////
// StatusBar.cpp #include <windows.h> #include <commctrl.h> #include <stdio.h> #include "KWndEx.h" #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 ID_STATUSBAR 202 #define NUM_BUTTONS 11 #define SEPARATOR_WIDTH 10
#define N_PARTS 4
HWND hwndToolBar;
HWND hwndStatusBar;
HWND InitToolBar(HWND hWnd);
void UpdateToolBar(ShapeData& sd);
void UpdateStatusBar(HWND hwnd, ShapeData& sd);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //==================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWndEx mainWnd("StatusBar", hInstance, nCmdShow, WndProc, MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
/* Здесь такой же текст, как в листинге 8.1 */
}
//==================================================================== HWND InitToolBar(HWND hWnd) {
/* Здесь такой же текст, как в листинге 8.1 */
}
//====================================================================
Элементы управления главного окна |
419 |
|
|
|
|
void UpdateToolBar(ShapeData& sd) {
/* Здесь такой же текст, как в листинге 8.1 */
}
//==================================================================== void UpdateStatusBar(HWND hwnd, ShapeData& sd) {
int paneWidth;
int aWidths[N_PARTS]; char text[100];
RECT rect;
int brightness;
int intensity[3] = { 85, 170, 255 }; GetClientRect(hwnd, &rect);
paneWidth = rect.right / N_PARTS; aWidths [0] = paneWidth;
aWidths [1] = paneWidth * 2; aWidths [2] = paneWidth * 3; aWidths [3] = -1;
SendMessage(hwndStatusBar, SB_SETPARTS, N_PARTS, (LPARAM)aWidths);
LoadString(GetModuleHandle(NULL), sd.id_shape, text, 100);
SendMessage(hwndStatusBar, SB_SETTEXT, 0, (LPARAM)text);
brightness = intensity[sd.id_bright - ID_DARK];
int red = sd.fRed? brightness : 0; sprintf(text, "Red = %d", red);
SendMessage(hwndStatusBar, SB_SETTEXT, 1, (LPARAM)text);
int green = sd.fGreen? brightness : 0; sprintf(text, "Green = %d", green);
SendMessage(hwndStatusBar, SB_SETTEXT, 2, (LPARAM)text);
int blue = sd.fBlue? brightness : 0; sprintf(text, "Blue = %d", blue);
SendMessage(hwndStatusBar, SB_SETTEXT, 3, (LPARAM)text);
}
//==================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* Определения локальных переменных из листинга 8.1 */
RECT rcSB; // позиция и размеры окна hwndStatusBar int sbHeight; // высота окна hwndStatusBar
HMENU hClickMenu; int itemID;
static UINT submenuID; char text[200];
switch (uMsg)
{
case WM_CREATE:
/* Здесь такой же текст, как в листинге 8.1 */
// Создание строки состояния |
продолжение |
|
420 |
Глава 8. Элементы управления общего пользования |
|
|
Листинг 8.5 (продолжение)
hwndStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, ID_STATUSBAR);
break;
case WM_SIZE:
SendMessage(hwndToolBar, TB_AUTOSIZE, 0, 0);
UpdateStatusBar(hWnd, shapeData);
SendMessage (hwndStatusBar, WM_SIZE, wParam, lParam); break;
case WM_NOTIFY:
/* Здесь такой же текст, как в листинге 8.1 */ break;
case WM_MENUSELECT:
itemID = LOWORD(wParam); // меню нулевого уровня hClickMenu = (HMENU)lParam;
if (HIWORD(wParam) & MF_POPUP) { if (hClickMenu == hMenu)
submenuID = itemID; else
itemID += 100 * (submenuID + 1);
}
else if (!itemID) itemID = -1;
SendMessage(hwndStatusBar, SB_SIMPLE, TRUE, 0); LoadString(GetModuleHandle(NULL), itemID, text, 200); SendMessage(hwndStatusBar, SB_SETTEXT, 255, (LPARAM)text); break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
/* Обработка для кодов сообщений IDM_OPEN, IDM_CLOSE, … , IDM_RESIZE – как в листинге 8.1 */
case IDM_ABOUT: MessageBox(hWnd,
"StatusBar\nVersion 1.0\nCopyright: " "Finesoft Corporation, 2005.",
"About StatusBar", MB_OK); break;
default:
break;
}
UpdateToolBar(shapeData);
SendMessage(hwndStatusBar, SB_SIMPLE, FALSE, 0);
UpdateStatusBar(hWnd, shapeData);
InvalidateRect(hWnd, NULL, TRUE);
