Операционная система 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 . |