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

