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

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

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