Операционная система Windows 95 для программиста© Александр Фролов, Григорий ФроловТом 22, М.: Диалог-МИФИ, 1993, 271 стр. 2.3. Приложение Smart ApplicationТеперь настало время проверить работу органов управления Toolbar и Statusbar на практике. Для этого мы предлагаем вам ознакомится с исходными текстами приложения Smart Application, внешний вид главного окна которого показан на рис. 2.3.
Рис. 2.3. Главное окно приложения Smart Application В этом приложении есть меню, орган управления Toolbar с функциями Tool Tip, кнопки которого дублируют некоторые строки меню, а также окно Statusbar, разделенное на три области. Первая область используется для отображения текстового описания строк меню, вторая не используется, а в третьей мы нарисовали маленькие часы. В качестве упражнения вы можете попытаться их запустить. Если сделать двойной щелчок левой клавишей мыши по окну Toolbar , на экране появится диалоговая панель настройки Customize Toolbar, показанная на рис. 2.4.
Рис. 2.4. Диалоговая панель настройки Customize Toolbar С помощью этой диалоговой панели вы можете перемещать кнопки из списка Toolbar buttons в список Available buttons и обратно. Первый список содержит все кнопки, отображаемые в настоящий момент в окне Toolbar, второй при первом отображении диалоговой панели содержит только разделитель Separator. Выделяя кнопки из списка Toolbar buttons и нажимая кнопку Add, вы можете их скрыть. Скрытые кнопки появятся в списке Available buttons. Впоследствии вы сможете их вставить на прежнее или другое место окна Toolbar. Кнопки Move Up и Move Down предназначены для перемещения кнопок по окну Toolbar . Впрочем, такое перемещение можно выполнить левой клавишей мыши, нажав клавишу <Shift> и установив курсор мыши на нужную кнопку. Кнопки Help и Reset никак не задействованы в нашем приложении, однако вы и сами легко сможете найти для них применение. Достаточно предусмотреть обработку извещений TBN_CUSTHELP и TBN_RESET , описанных нами ранее. Заметим, что диалоговая панель Customize Toolbar не определена в ресурсах приложения Smart Application, а встроена в орган управления Toolbar. Так что мы пользуемся готовым средством настройки Toolbar, а не создаем свое. Исходные тексты приложения Smart ApplicationОсновной файл исходных текстов приложения Smart Application представлен в листинге 2.1. Листинг 2.1. Файл smart\smart.c
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "resource.h"
#include "afxres.h"
#include "smart.h"
// -----------------------------------------------------
// Глобальные переменные
// -----------------------------------------------------
HINSTANCE hInst;
char szAppName[] = "Smart";
char szAppTitle[] = "Smart Application";
HWND hwndTb; // идентификатор Toolbar
HWND hwndSb; // идентификатор Statusbar
int ptWidth[3]; // таблица ширин для Statusbar
HBITMAP hSbLogoBmp; // изображение для Statusbar
// Идентификаторы строк описания временных меню
UINT nIdPopup[] =
{
IDS_FILEMENU,
IDS_EDITMENU,
IDS_HELPMENU
};
// Описание кнопок Toolbar
TBBUTTON tbButtons[] =
{
{ 0, ID_FILE_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 1, ID_FILE_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 2, ID_FILE_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0},
{ 3, ID_EDIT_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 4, ID_EDIT_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 5, ID_EDIT_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0},
{ 6, ID_FILE_PRINT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0},
{ 7, ID_HELP_ABOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}
};
// -----------------------------------------------------
// Функция WinMain
// -----------------------------------------------------
int APIENTRY
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hWnd;
MSG msg;
hInst = hInstance;
// Преверяем, не было ли это приложение запущено ранее
hWnd = FindWindow(szAppName, NULL);
if(hWnd)
{
if(IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
return FALSE;
}
// Регистрируем класс окна
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadImage(hInst,
MAKEINTRESOURCE(IDI_APPICONSM), IMAGE_ICON, 16, 16, 0);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadImage(hInst,
MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 32, 32, 0);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_APPMENU);
wc.lpszClassName = szAppName;
if(!RegisterClassEx(&wc))
if(!RegisterClass((LPWNDCLASS)&wc.style))
return FALSE;
// Инициализируем библиотеку стандартных органов управления
InitCommonControls();
// Создаем главное окно приложения
hWnd=CreateWindow(szAppName,szAppTitle,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL, NULL, hInst, NULL);
if(!hWnd) return(FALSE);
// Отображаем окно и запускаем цикл обработки сообщений
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
// -----------------------------------------------------
// Функция WndProc
// -----------------------------------------------------
LRESULT WINAPI
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hWnd, WM_CREATE, WndProc_OnCreate);
HANDLE_MSG(hWnd, WM_DESTROY, WndProc_OnDestroy);
HANDLE_MSG(hWnd, WM_COMMAND, WndProc_OnCommand);
HANDLE_MSG(hWnd, WM_NOTIFY, WndProc_OnNotify);
HANDLE_MSG(hWnd, WM_SIZE, WndProc_OnSize);
HANDLE_MSG(hWnd, WM_DRAWITEM, WndProc_OnDrawItem);
HANDLE_MSG(hWnd, WM_MENUSELECT, WndProc_OnMenuSelect);
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
}
// -----------------------------------------------------
// Функция WndProc_OnCreate
// -----------------------------------------------------
BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
// Создаем Toolbar
hwndTb = CreateToolbarEx(hWnd,
WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS |
CCS_ADJUSTABLE,
IDT_TOOLBAR, // идентификатор органа Toolbar
8, // количество пиктограмм
hInst, // идентификатор приложения
IDB_TBBITMAP,// идентификатор битового изображения
// кнопок
(LPCTBBUTTON)&tbButtons,// адрес описания кнопок
11, // количество кнопок
16,16, // ширина и высота кнопок
16,16, // ширина и высота пиктограмм
sizeof(TBBUTTON)); // размер структуры в байтах
if(hwndTb == NULL)
return FALSE;
// Создаем Statusbar
hwndSb = CreateWindowEx(
0L, // расширенный стиль окна
STATUSCLASSNAME, // класс окна для Statusbar
"", // заголовок окна отсутствует
WS_CHILD | WS_BORDER | // стиль окна
WS_VISIBLE | SBARS_SIZEGRIP,
0, 0, 0, 0, // координаты, ширина, высота
hWnd, // идентификатор родительского окна
(HMENU)IDS_STATUSBAR, // идентификатор Statusbar
hInst, // идентификатор приложения
NULL ); // доп. данные для окна
if(hwndSb == NULL)
return FALSE;
// Делим Statusbar на 3 области
SendMessage(hwndSb, SB_SETPARTS, 3, (LPARAM)ptWidth);
// Инициализируем области Statusbar
SendMessage(hwndSb, SB_SETTEXT, 0, (LPARAM)"");
SendMessage(hwndSb, SB_SETTEXT, 1 | SBT_NOBORDERS,
(LPARAM)"");
// Загружаем изображение, которое будет нарисовано
// в третьей части Statusbar
hSbLogoBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SBLOGO));
if(hSbLogoBmp== NULL)
return FALSE;
// Рисуем это изображение
SendMessage(hwndSb, SB_SETTEXT, 2 | SBT_OWNERDRAW,
(LPARAM)hSbLogoBmp);
return TRUE;
}
// -----------------------------------------------------
// Функция WndProc_OnDestroy
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnDestroy(HWND hWnd)
{
PostQuitMessage(0);
return FORWARD_WM_DESTROY(hWnd, DefWindowProc);
}
// -----------------------------------------------------
// Функция WndProc_OnCommand
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnCommand(HWND hWnd, int id,
HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case ID_FILE_EXIT:
PostQuitMessage(0);
break;
case ID_FILE_NEW:
case ID_FILE_OPEN:
case ID_FILE_SAVE:
case ID_FILE_SAVEAS:
case ID_FILE_PRINT:
case ID_EDIT_CUT:
case ID_EDIT_COPY:
case ID_EDIT_PASTE:
case ID_HELP_ABOUT:
default:
MessageBox(NULL,"Command stub","Smart Application",MB_OK);
}
return FORWARD_WM_COMMAND(hWnd, id, hwndCtl, codeNotify,
DefWindowProc);
}
// -----------------------------------------------------
// Функция WndProc_OnNotify
// -----------------------------------------------------
LRESULT WndProc_OnNotify(HWND hWnd, int idFrom, NMHDR* pnmhdr)
{
LPTOOLTIPTEXT lpToolTipText;
LPTBNOTIFY lptbn;
int nItem;
static CHAR szBuf[128];
switch(pnmhdr->code)
{
// Если получили сообщение от ToolTips, загружаем из
// ресурсов соответствующую текстовую строку
case TTN_NEEDTEXT:
lpToolTipText = (LPTOOLTIPTEXT)pnmhdr;
LoadString(hInst, lpToolTipText->hdr.idFrom,
szBuf, sizeof(szBuf));
lpToolTipText->lpszText = szBuf;
break;
// Возвращаем окну Toolbar характеристики кнопки,
// с номером, заданным в lptbn->iItem
case TBN_GETBUTTONINFO:
lptbn = (LPTBNOTIFY)pnmhdr;
nItem = lptbn->iItem;
lptbn->tbButton.iBitmap = tbButtons[nItem].iBitmap;
lptbn->tbButton.idCommand = tbButtons[nItem].idCommand;
lptbn->tbButton.fsState = tbButtons[nItem].fsState;
lptbn->tbButton.fsStyle = tbButtons[nItem].fsStyle;
lptbn->tbButton.dwData = tbButtons[nItem].dwData;
lptbn->tbButton.iString = tbButtons[nItem].iString;
// Если запрашиваются характеристики несуществующей
// кнопки, возвращаем FALSE
return((nItem < sizeof(tbButtons)/sizeof(tbButtons[0]))?
TRUE : FALSE);
break;
// Разрешаем удаление любой кнопки, кроме самой первой
case TBN_QUERYDELETE:
lptbn = (LPTBNOTIFY)pnmhdr;
nItem = lptbn->iItem;
return (nItem == 0)? FALSE : TRUE;
break;
// Разрешаем вставку любой кнопки, кроме самой первой
case TBN_QUERYINSERT:
lptbn = (LPTBNOTIFY)pnmhdr;
nItem = lptbn->iItem;
return (nItem == 0)? FALSE : TRUE;
break;
// В ответ на завершение операции перемещения
// перерисовываем Toolbar
case TBN_TOOLBARCHANGE:
SendMessage(hwndTb, TB_AUTOSIZE, 0L, 0L);
return TRUE;
break;
default:
break;
}
return FALSE;
}
// -----------------------------------------------------
// Функция WndProc_OnSize
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnSize(HWND hwnd, UINT state, int cx, int cy)
{
// Изменяем размеры Toolbar и Statusbar в соответствии с
// новыми размерами окна
SendMessage(hwndTb, WM_SIZE, cx, cy);
SendMessage(hwndSb, WM_SIZE, cx, cy);
// Рассчитываем размеры областей Statusbar
ptWidth[0] = cx/2;
ptWidth[1] = cx/2 + cx/4;
ptWidth[2] = -1;
// Устанавливаем новые размеры Statusbar
SendMessage(hwndSb, SB_SETPARTS, 3, (LPARAM)ptWidth);
return FORWARD_WM_SIZE(hwnd, state, cx, cy, DefWindowProc);
}
// -----------------------------------------------------
// Функция WndProc_OnDrawItem
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnDrawItem(HWND hwnd,
const DRAWITEMSTRUCT * lpDrawItem)
{
// Необходимо выполнить перерисовку области Statusbar,
// которая была определена как SBT_OWNERDRAW
if(lpDrawItem->CtlID == IDS_STATUSBAR)
{
LPDRAWITEMSTRUCT lpDis;
HDC hdcMem;
HBITMAP hbmOld;
BITMAP bm;
// Рисуем битовое изображение внутри области
lpDis = (LPDRAWITEMSTRUCT)lpDrawItem;
hdcMem = CreateCompatibleDC(lpDis->hDC);
hbmOld = SelectObject(hdcMem, hSbLogoBmp);
GetObject(hSbLogoBmp, sizeof(bm), &bm);
BitBlt(lpDis->hDC,
lpDis->rcItem.left, lpDis->rcItem.top,
bm.bmWidth, bm.bmHeight,
hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
}
return FORWARD_WM_DRAWITEM(hwnd, lpDrawItem, DefWindowProc);
}
// -----------------------------------------------------
// Функция WndProc_OnMenuSelect
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnMenuSelect(HWND hwnd, HMENU hmenu, int item,
HMENU hmenuPopup, UINT flags)
{
static char szBuf[128];
UINT nStrID = 0;
szBuf[0] = 0;
// Пользователь закрыл меню
if(flags == 0xffffffff && hmenu == NULL)
nStrID = IDS_DESCRIPTION;
// Пользователь выделил в меню строку разделителя
else if(flags & MFT_SEPARATOR)
nStrID = 0;
// Выбрано временное меню
else if(flags & MF_POPUP)
{
// Выбрано системное меню
if(flags & MF_SYSMENU)
nStrID = IDS_SYSMENU;
// Вычисляем идентификатор строки, описывающей
// временное меню
else
nStrID = ((item < sizeof(nIdPopup)/sizeof(nIdPopup[0]))?
nIdPopup[item] : 0);
}
// Используем идентификатор строки, соответствующий
// выделенной строке меню
else nStrID = item;
// Загружаем строку из ресурсов приложения
if(nStrID != 0)
LoadString(hInst, nStrID, szBuf, sizeof(szBuf));
// Отображаем строку в первой области Toolbar
SendMessage(hwndSb, SB_SETTEXT, 0, (LPARAM)szBuf);
return FORWARD_WM_MENUSELECT(hwnd, hmenu, item,
hmenuPopup, flags, DefWindowProc);
}
В листинге 2.2 мы привели файл smart.h, который содержит прототипы функций и определения констант. Листинг 2.2. Файл smart\smart.h // ----------------------------------------------------- // Описание функций // ----------------------------------------------------- LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct); void WndProc_OnDestroy(HWND hWnd); void WndProc_OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify); LRESULT WndProc_OnNotify(HWND hWnd, int idFrom, NMHDR FAR * pnmhdr); void WndProc_OnSize(HWND hwnd, UINT state, int cx, int cy); void WndProc_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem); void WndProc_OnMenuSelect(HWND hwnd, HMENU hmenu, int item, HMENU hmenuPopup, UINT flags); #define IDT_TOOLBAR 801 #define IDS_STATUSBAR 802 #define IDS_SCSIZE SC_SIZE #define IDS_SCMOVE SC_MOVE #define IDS_SCMINIMIZE SC_MINIMIZE #define IDS_SCCLOSE SC_CLOSE #define IDS_SCRESTORE SC_RESTORE #define IDS_SCTASKLIST SC_TASKLIST #define IDS_SCMAXIMIZE SC_MAXIMIZE Файл resource.h (листинг 2.3) был создан автоматически системой разработки приложений Microsoft Visual C++. Он содержит определения констант, которые используются для доступа к ресурсам приложения Smart Application. Листинг 2.3. Файл smart\resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by SMART.RC
//
#define IDI_APPICON 102
#define IDI_APPICONSM 103
#define IDR_APPMENU 104
#define IDB_TBBITMAP 105
#define IDB_SBLOGO 107
#define ID_FILE_EXIT 40001
#define ID_FILE_SAVEAS 40002
#define ID_HELP_ABOUT 40010
#define IDS_DESCRIPTION 57638
#define IDS_SYSMENU 57639
#define IDS_FILEMENU 57640
#define IDS_EDITMENU 57641
#define IDS_HELPMENU 57642
#define IDS_TEST 61745
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_3D_CONTROLS 1
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40013
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
И, наконец, файл smart.rc (листинг 2.4) содержит описание ресурсов приложения Smart Application. Как и предыдущий файл, он был создан автоматически системой разработки приложений Microsoft Visual C++. Листинг 2.4. Файл smart\smart.rc
//Microsoft Visual C++ generated resource script.
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
//////////////////////////////////////////////////////////////
// Generated from the TEXTINCLUDE 2 resource.
#include "afxres.h"
#include "smart.h"
//////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
//////////////////////////////////////////////////////////////
// Icon
IDI_APPICON ICON DISCARDABLE "smart.ico"
IDI_APPICONSM ICON DISCARDABLE "smartsm.ico"
#ifdef APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////
// TEXTINCLUDE
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""smart.h""\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
//////////////////////////////////////////////////////////////
#endif // APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////
// Menu
//
IDR_APPMENU MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New...", ID_FILE_NEW
MENUITEM "&Open...", ID_FILE_OPEN
MENUITEM "&Close", ID_FILE_CLOSE
MENUITEM SEPARATOR
MENUITEM "&Save", ID_FILE_SAVE
MENUITEM "Save &As...", ID_FILE_SAVEAS
MENUITEM SEPARATOR
MENUITEM "&Print...", ID_FILE_PRINT
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Edit"
BEGIN
MENUITEM "Cu&t", ID_EDIT_CUT
MENUITEM "&Copy", ID_EDIT_COPY
MENUITEM "&Paste", ID_EDIT_PASTE
END
POPUP "&Help"
BEGIN
MENUITEM "&About...", ID_HELP_ABOUT
END
END
//////////////////////////////////////////////////////////////
// Bitmap
//
IDB_TBBITMAP BITMAP DISCARDABLE "toolbar.bmp"
IDB_SBLOGO BITMAP DISCARDABLE "sblogo.bmp"
//////////////////////////////////////////////////////////////
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
ID_FILE_NEW "Creates a new document"
ID_FILE_OPEN "Open an existing document"
ID_FILE_CLOSE "Closes the active document"
ID_FILE_SAVE "Save the active document"
ID_FILE_PRINT "Prints the active document"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_FILE_EXIT "Exit application"
ID_FILE_SAVEAS "Saves the active document under a different name"
ID_HELP_ABOUT "Displays information about application"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_EDIT_COPY "Copies the selection and puts it on the clipboard"
ID_EDIT_CUT "Cuts the selection and puts it on the clipboard"
ID_EDIT_PASTE "Inserts the clipboards contents at the insertion point"
IDS_DESCRIPTION "Smart Application"
IDS_SYSMENU "Move, size or close application window"
IDS_FILEMENU "Create, open, save or print documents"
IDS_EDITMENU "Delete, copy and insert"
IDS_HELPMENU "Get help"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_SCSIZE "Changes the size of the window"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_SCMOVE "Changes the position of the window"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_SCMINIMIZE "Minimizes the window to an icon"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_SCCLOSE "Closes the window"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_SCRESTORE "Restores the window to normal size"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_SCTASKLIST "Switches to another application through the Windows Task Manager"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_SCMAXIMIZE "Enlarges the window to full size"
END
#ifndef APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////
// Generated from the TEXTINCLUDE 3 resource.
//////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
Описание функцийПриведем краткое описание функций, определенных в файле smart.c приложения Smart Application. WinMainФункция WinMain сохраняет идентификатор приложения в переменной hInst и проверяет, было ли приложение Smart Application запущено ранее. Для этого используется функция FindWindow, с которой вы знакомы по предыдущему приложению Window Application. После регистрации класса главного окна приложения функцией RegisterClassEx (или функцией RegisterClass, если приложение работает в среде Microsoft Windows NT версии 3.5). Затем для инициализации библиотеки стандартных органов управления COMCTL32.DLL вызывается функция InitCommonControls . Далее функция WinMain создает главное окно приложения и запускает цикл обработки сообщений обычным образом. WndProcФункция главного окна приложения Smart Application обрабатывает сообщения WM_CREATE, WM_DESTROY, WM_COMMAND, WM_NOTIFY, WM_SIZE, WM_DRAWITEM и WM_MENUSELECT. Для этого она использует макрокоманду HANDLE_MSG, передавая ей в качестве второго параметра адрес функции обработки сообщения. WndProc_OnCreateЭта функция обрабатывает сообщение WM_CREATE и, следовательно, вызывается при создании главного окна приложения. В задачу обработчика сообщения входит создание и инициализация органов управления Toolbar и Statusbar. Орган управления Toolbar создается специально предназначенной для этого функцией CreateToolbarEx. Для того чтобы пользователь смог получать краткую подсказку о назначении кнопок Toolbar , мы указали стиль TBSTYLE_TOOLTIPS . Кроме этого, был задан стиль CCS_ADJUSTABLE, позволяющий пользователю выполнять настройку Toolbar. Так как между кнопками имеются промежутки, количество пиктограмм (восемь) больше, чем количество кнопок (одиннадцать). В массиве структур tbButtons находятся описания кнопок. Формат этих структур вы уже знаете. Что же касается Statusbar, то этот орган управления в нашем примере создается при помощи функции CreateWindowEx с использованием стиля окна STATUSCLASSNAME . Для того чтобы правый нижний угол Statusbar можно было использовать для изменения размеров главного окна приложения, мы включили стиль SBARS_SIZEGRIP . После создания Statusbar его окно разделяется на три области. Для этого окну Statusbar посылается сообщение SB_SETPARTS . Первые две области инициализируются пустыми строками при помощи сообщения SB_SETTEXT . Область с номером 1 отображается без рамки, так как этот номер скомбинирован при помощи логической операции ИЛИ с константой SBT_NOBORDERS . Область с номером 2 используется для отображения небольшой картинки, загруженной из ресурса приложения с идентификатором IDB_SBLOGO. Поэтому номер области комбинируется с константой SBT_OWNERDRAW . WndProc_OnDestroyЭта функция обрабатывает сообщение WM_DESTROY, вызывая функцию PostQuitMessage. В результате приложение завершает свою работу. WndProc_OnCommandЗадача функции WndProc_OnCommand - обработка сообщения WM_COMMAND, поступающего от меню приложения, а также от органа управления Toolbar . Для всех идентификаторов, кроме ID_FILE_EXIT, в этой функции стоит "заглушка", которая выводит сообщение при помощи функции MessageBox. Если же пользователь выбирает строку Exit из меню File, функция обработки сообщения WM_COMMAND вызывает функцию PostQuitMessage для завершения работы приложения. WndProc_OnNotifyФункция WndProc_OnNotify обрабатывает извещения, поступающие от органа управления Toolbar в виде сообщения WM_NOTIFY. Мы уже рассказывали вам о том, как нужно обрабатывать эти извещения. Для примера наш обработчик извещений запрещает пользователю выполнять удаление и вставку самой первой кнопки в органе управления Toolbar . WndProc_OnSizeФункция WndProc_OnSize обрабатывает сообщение WM_SIZE . Напомним, что это сообщение приходит при создании окна, а также при изменении его размеров. Наш обработчик посылает сообщение WM_SIZE органам управления Toolbar и Statusbar. В ответ на это они изменяют свои размеры таким образом, чтобы расположиться, соответственно, в верхней и нижней части главного окна приложения. Кроме этого, обработчик сообщения WM_SIZE рассчитывает размеры областей органа управления Statusbar, заполняя массив ptWidth. Правая граница первой области располагается в середине окна Statusbar, а правая граница второй области - на расстоянии 3/4 длины окна Statusbar от его левой границы. Правая граница третьей области будет простираться до правой границы окна Statusbar. Размеры устанавливаются при помощи сообщения SB_SETPARTS . WndProc_OnDrawItemФункция WndProc_OnDrawItem обрабатывает сообщение WM_DRAWITEM , которое посылается органом управления Statusbar при необходимости перерисовки третьей области его окна. Соответствующая процедура рисует небольшое битовое изображение при помощи функции BitBlt, которая была нами подробно описана в 14 томе "Библиотеки системного программиста". Идентификатор битового изображения передается через структуру типа DRAWITEMSTRUCT. Адрес структуры, в свою очередь, передается через параметр lParam сообщения WM_DRAWITEM. WndProc_OnMenuSelectПервая область окна Statusbar используется для отображения краткой подсказки о назначении строк системного меню, временных меню приложений и строк временных меню приложений. Для того чтобы проследить выделение строк перечисленных меню пользователем, в нашем приложении предусмотрен обработчик сообщения WM_MENUSELECT . Его роль выполняет функция WndProc_OnMenuSelect. Обработчик сообщения WM_MENUSELECT анализирует переменные item, flags и hmenu, которые образуются из параметров сообщения следующим образом: item = (UINT)LOWORD(wParam); flags = (UINT)HIWORD(wParam); hmenu = (HMENU)lParam; Через 16-разрядный параметр item передается номер временного меню или идентификатор строки меню. Параметр flags также 16-разрядный. Через него передается тип меню или тип строки. Например, константа MF_POPUP соответствует временному меню, константа MF_SYSMENU - системному меню, а константа MFT_SEPARATOR - разделительной строке во временном меню. В результате анализа параметров обработчик сообщения записывает в переменную nStrID идентификатор текстовой строки из ресурсов приложения, содержащей нужную подсказку. Если такой строки нет, в переменную nStrID будет записано нулевое значение. Когда пользователь закрывает меню, например, при помощи клавиши <Esc>, параметр flags содержит значение 0xffff. При этом в параметр hmenu (идентификатор меню) записывается значение NULL. В параметрах функции WndProc_OnMenuSelect параметр item описан как имеющий тип int, поэтому его значение расширяется до 32-разрядного. Именно поэтому для того чтобы определить момент, когда пользователь закрыл меню, мы сравниваем его значение с константой 0xffffffff:
if(flags == 0xffffffff && hmenu == NULL)
nStrID = IDS_DESCRIPTION;
Если пользователь открыл системное или временное меню, в переменную nStrID записывается, соответственно, идентификатор строки IDS_SYSMENU или идентификатор, взятый из массива nIdPopup. Массив nIdPopup содержит таблицу идентификаторов текстовых строк, предназначенных для краткого описания временных меню. В том случае, когда пользователь открыл временное меню и перемещается по его строкам, в переменную nStrID записывается идентификатор соответствующей строки меню. В ресурсах приложения определены строки с идентификаторами, равными идентификаторам строк меню. В том случае, когда нужная строка определена, она загружается из ресурсов приложения функцией LoadString и отображается в первой области окна Satusbar при помощи сообщения SB_SETTEXT . |

