Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

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

[Назад] [Содеожание] [Дальше]