Операционная система Windows 95 для программиста© Александр Фролов, Григорий ФроловТом 22, М.: Диалог-МИФИ, 1993, 271 стр. 4.4. Приложение Some BooksПриложение Some Books создает дерево и отображает его в своем главном окне, как это показано на рис. 4.2.
Рис. 4.2. Просмотр дерева в главном окне приложения Some Books Вы можете открывать или закрывать отдельные уровни иерархии при помощи кнопок с изображением символов "+" и "-", а также выбирать любые элементы дерева. При выборе вложенных элементов нижней иерархии изображение закрытой книги заменяется на изображение открытой книги. Исходные тексты приложения Some BooksВсе функции приложения Some Books определены в файле somebook.c (листинг 4.1). Листинг 4.1. Файл somebook\somebook.c #define STRICT #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include "resource.h" #include "afxres.h" #include "somebook.h" // Корневой элемент дерева char szBooks[] = "Книги издательства АО 'Диалог-МИФИ'"; // Вложенные элементы первого уровня char szBSPSeries[] = "Библиотека системного программиста, " "(C) Фролов А.В., Фролов Г.В., 1991-1995 г."; char szStepSeries[] = "Персональный компьютер. Шаг за шагом, " "(C) Фролов А.В., Фролов Г.В., 1994-1995 г."; typedef struct tagBOOKINFO { char szBookName[256]; UINT nVolumeNumber; } BOOKINFO; // Вложенные элементы второго уровня BOOKINFO rgSPLBookInfo[]= { {"Microsoft Windows 3.1 для программиста", 11}, {"Графический интерфейс GDI в Microsoft Windows ", 14}, }; BOOKINFO rgStepBookInfo[]= { {"Операционная система Microsoft Windows. " "Руководство пользователя", 2}, {"Локальные сети персональных компьютеров", 3}, }; // Номера изображений для органа управления Tree View int idxBooks, idxBookClosed, idxBookOpened; HINSTANCE hInst; char szAppName[] = "SomeBookApp"; char szAppTitle[] = "Some programmer and user books"; HWND hwndTree; // ----------------------------------------------------- // Функция 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 = 0; 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; // Создаем главное окно приложения 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_SIZE, WndProc_OnSize); default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } } // ----------------------------------------------------- // Функция WndProc_OnCreate // ----------------------------------------------------- BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct) { RECT rc; HIMAGELIST himl; HBITMAP hBmp; HTREEITEM hRootItem; HTREEITEM hBSPItem; HTREEITEM hStepItem; // Определяем размеры внутренней области главного окна GetClientRect(hWnd, &rc); // Инициализируем библиотеку стандартных органов управления InitCommonControls(); // Создаем орган управления Tree View hwndTree = CreateWindowEx(0L, WC_TREEVIEW, "", WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hWnd, (HMENU) IDC_TREEVIEW, hInst, NULL); if(hwndTree == NULL) return FALSE; // Создаем список изображений himl = ImageList_Create(33, 33, FALSE, 3, 0); // Добавляем изображения в список hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BOOKS)); idxBooks = ImageList_Add(himl, hBmp, NULL); hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BOOK_CLOSED)); idxBookClosed = ImageList_Add(himl, hBmp, NULL); hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BOOK_OPENED)); idxBookOpened = ImageList_Add(himl, hBmp, NULL); // Добавляем список изображений TreeView_SetImageList(hwndTree, himl, TVSIL_NORMAL); // Вставляем корневой элемент hRootItem = InsTreeItem((HTREEITEM)TVI_ROOT, szBooks, (HTREEITEM)TVI_FIRST, idxBooks, idxBooks); // Вставляем вложенные элементы первого уровня hBSPItem = InsTreeItem(hRootItem, szBSPSeries, (HTREEITEM)TVI_SORT, idxBooks, idxBooks); hStepItem = InsTreeItem(hRootItem, szStepSeries, (HTREEITEM)TVI_SORT, idxBooks, idxBooks); // Вставляем вложенные элементы второго уровня InsTreeItem(hBSPItem, rgSPLBookInfo[0].szBookName, (HTREEITEM)TVI_SORT, idxBookClosed, idxBookOpened); InsTreeItem(hBSPItem, rgSPLBookInfo[1].szBookName, (HTREEITEM)TVI_SORT, idxBookClosed, idxBookOpened); InsTreeItem(hStepItem, rgStepBookInfo[0].szBookName, (HTREEITEM)TVI_SORT, idxBookClosed, idxBookOpened); InsTreeItem(hStepItem, rgStepBookInfo[1].szBookName, (HTREEITEM)TVI_SORT, idxBookClosed, idxBookOpened); return TRUE; } // ----------------------------------------------------- // Функция InsTreeItem // ----------------------------------------------------- HTREEITEM InsTreeItem(HTREEITEM hParent, LPSTR szText, HTREEITEM hAfter, int iImage, int iSelectedImage) { TV_INSERTSTRUCT tvins; HTREEITEM hItem; memset(&tvins, 0, sizeof(tvins)); tvins.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; tvins.item.pszText = szText; tvins.item.cchTextMax = lstrlen(szText); tvins.item.iImage = iImage; tvins.item.iSelectedImage = iSelectedImage; tvins.hInsertAfter = hAfter; tvins.hParent = hParent; hItem = TreeView_InsertItem(hwndTree, &tvins); return hItem; } // ----------------------------------------------------- // Функция WndProc_OnDestroy // ----------------------------------------------------- #pragma warning(disable: 4098) void WndProc_OnDestroy(HWND hWnd) { DestroyWindow(hwndTree); PostQuitMessage(0); return 0L; } // ----------------------------------------------------- // Функция WndProc_OnCommand // ----------------------------------------------------- #pragma warning(disable: 4098) void WndProc_OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify) { DWORD dwStyle = 0; switch (id) { case ID_FILE_EXIT: PostQuitMessage(0); return 0L; break; case ID_HELP_ABOUT: break; default: break; } return FORWARD_WM_COMMAND(hWnd, id, hwndCtl, codeNotify, DefWindowProc); } // ----------------------------------------------------- // Функция WndProc_OnSize // ----------------------------------------------------- #pragma warning(disable: 4098) void WndProc_OnSize(HWND hwnd, UINT state, int cx, int cy) { MoveWindow(hwndTree, 0, 0, cx, cy, TRUE); return FORWARD_WM_SIZE(hwnd, state, cx, cy, DefWindowProc); } Файл somebook.h (листинг 4.2) содержит писание функций и определение константы IDC_TREEVIEW (идентификатор органа управления Tree View). Листинг 4.2. Файл somebook\somebook.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); HTREEITEM InsTreeItem(HTREEITEM hParent, LPSTR szText, HTREEITEM hAfter, int iImage, int iSelectedImage); #define IDC_TREEVIEW 1235 В файле resource.h (который создается автоматически системой Microsoft Visual C++) находятся определения констант для работы с ресурсами приложения Some Books. Этот файл представлен в листинге 4.3. Листинг 4.3. Файл somebook\resource.h //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by somebook.rc // #define IDR_APPMENU 102 #define IDI_APPICON 103 #define IDI_APPICONSM 104 #define IDB_BOOKS 115 #define IDB_BOOK_CLOSED 118 #define IDB_BOOK_OPENED 120 #define ID_FILE_EXIT 40001 #define ID_HELP_ABOUT 40003 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 121 #define _APS_NEXT_COMMAND_VALUE 40002 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif Файл somebook.rc (листинг 4.4) содержит определение ресурсов приложения Some Books. Он создается автоматически. Листинг 4.4. Файл somebook\somebook.rc //Microsoft Visual C++ generated resource script. #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ////////////////////////////////////////////////////////////// // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ////////////////////////////////////////////////////////////// // Menu // IDR_APPMENU MENU DISCARDABLE BEGIN POPUP "&File" BEGIN MENUITEM "E&xit", ID_FILE_EXIT END END #ifdef APSTUDIO_INVOKED ////////////////////////////////////////////////////////////// // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END ////////////////////////////////////////////////////////////// #endif // APSTUDIO_INVOKED ////////////////////////////////////////////////////////////// // Icon // IDI_APPICON ICON DISCARDABLE "sbook.ico" IDI_APPICONSM ICON DISCARDABLE "sbooksm.ico" ////////////////////////////////////////////////////////////// // Bitmap // IDB_BOOKS BITMAP DISCARDABLE "books.bmp" IDB_BOOK_CLOSED BITMAP DISCARDABLE "closed.bmp" IDB_BOOK_OPENED BITMAP DISCARDABLE "opened.bmp" ////////////////////////////////////////////////////////////// // String Table STRINGTABLE DISCARDABLE BEGIN ID_FILE_EXIT "Quits the application" END #ifndef APSTUDIO_INVOKED ////////////////////////////////////////////////////////////// // Generated from the TEXTINCLUDE 3 resource. // ////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED Описание функцийВ этом разделе мы кратко опишем глобальные переменные и функции приложения Some Books. Глобальные переменныеВ массиве szBooks находится текстовая строка, которая отображается как корневой элемент дерева (название библиотеки книг - "Книги издательства АО 'Диалог-МИФИ'"). Массивы szBSPSeries и szStepSeries содержат два вложенных элемента, которые являются дочерними для корневого элемента (названия двух серий книг, которые издаются в АО 'Диалог-МИФИ'). И, наконец, массивы rgSPLBookInfo и rgStepBookInfo хранят вложенные элементы самого нижнего уровня (названия некоторых книг, входящих в эти две серии). Эти элементы являются дочерними для элементов, заданных массивами szBSPSeries и szStepSeries. В переменных idxBooks, idxBookClosed и idxBookOpened находятся номера изображений. Изображение с номером idxBooks используется для корневого элемента и элементов первого уровня вложенности. Изображения idxBookClosed и idxBookOpened (закрытая и раскрытая книга) нужны для элементов нижнего уровня иерархии (названий книг). В переменной hInst хранится идентификатор приложения, полученный функцией WinMain. Строчные массивы szAppName и szAppTitle хранят, соответственно, имя и заголовок приложения. Переменная hwndTree используется для хранения идентификатора созданного органа управления Tree View. WinMainФункция WinMain в приложении Some Books полностью аналогична функции WinMain предыдущего приложения. Она сохраняет идентификатор приложения и проверяет, не было ли это приложение запущено ранее. Если было, то активизируется окно работающего приложения. Далее функция регистрирует класс главного окна приложения, создает и отображает это окно, а затем запускает цикл обработки сообщений. WndProcФункция WndProc обрабатывает следующие сообщения: WM_CREATE, WM_DESTROY, WM_COMMAND, WM_SIZE. Как и в предыдущих наших приложениях, обработка выполняется с использованием макрокоманды HANDLE_MSG. WndProc_OnCreateЭта функция обрабатывает сообщение WM_CREATE, создавая и инициализируя орган управления Tree View. Размеры окна органа управления устанавливаются равными размерам внутренней области главного окна приложения и в дальнейшем изменяются соответствующим образом обработчиком сообщения WM_SIZE. В процессе инициализации функция WndProc_OnCreate создает список изображений, которые будут использованы для элементов дерева, и добавляет в этот список три изображения. При этом в глобальные переменные idxBooks, idxBookClosed и idxBookOpened записываются номера изображений. После этого список изображений подключается к органу управления Tree View. Далее функция WndProc_OnCreate заполняет дерево, добавляя в него корневой элемент и вложенные элементы. Для этого она вызывает функцию InsTreeItem, описанную ниже. InsTreeItemФункция InsTreeItem добавляет элементы к дереву, вызывая для этого макрокоманду TreeView_InsertItem. Перед этим она инициализирует структуру tvins типа TV_INSERTSTRUCT, записывая в нее информацию о добавляемом элементе и его расположении в иерархии существующих элементов дерева. Для каждого элемента, в частности, определяется пара номеров изображений iImage и iSelectedImage, которые используются для отображения элемента, соответственно, в невыбранном и выбранном состоянии. WndProc_OnDestroyФункция WndProc_OnDestroy вызывается, когда пользователь завершает работу приложения. Она уничтожает окно органа управления Tree View и останавливает цикл обработки сообщений, вызывая функцию PostQuitMessage. WndProc_OnCommandЭта функция обрабатывает сообщение WM_COMMAND, поступающее от главного меню приложения. WndProc_OnSizeПриложение изменяет размеры органа управления Tree View таким образом, чтобы они всегда соответствовали размерам внутренней области главного окна приложения Some Books. Для этого оно обрабатывает сообщение WM_SIZE. Изменения размеров окна органа управления выполняется функцией WndProc_OnSize. |