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

Операционная система Windows 95 для программиста

© Александр Фролов, Григорий Фролов
Том 22, М.: Диалог-МИФИ, 1993, 271 стр.

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

6.5. Приложение Wizard Demo

Немного изменив приложение Property Sheet Demo, мы превратили его в приложение Wizard Demo. Сравнив исходные тексты, попробуйте сами найти отличия.

Страницы блокнота теперь отображаются последовательно.

На рис. 6.6 показано первая страница органа управления Wizard.

Рис. 6.6. Первая страница органа управления Wizard в приложении Wizard Demo

Кнопка Back для этой страницы отображается всегда в заблокированном состоянии, так как эта страница первая. Для перехода ко второй странице (рис. 6.7) вы должны нажать кнопку Next.

Рис. 6.7. Вторая страница органа управления Wizard в приложении Wizard Demo

На второй странице кнопки Back и Next разблокированы, так что вы можете либо вернуться к первой странице, либо перейти к третьей (рис. 6.8).

Рис. 6.8. Третья страница органа управления Wizard в приложении Wizard Demo

Третья страница - последняя, поэтому вместо кнопки Next на ней отображается кнопка Finish. Если нажать на кнопку Finish, на экране появится диалоговая панель, отображающая установленные параметры (рис. 6.9).

Рис. 6.9. Отображение установленных параметров

Исходные тексты приложения Wizard Demo

Все функции приложения Wizard Demo определены в файле wizdemo.c (листинг 6.5).

Листинг 6.5. Файл wizdemo\wizdemo.c



#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "resource.h"
#include "afxres.h"
#include "wizdemo.h"

// Структура, в которой хранятся параметры
typedef struct 
{
  int  nBold;
  int  nItalic;
  int  nUnderline;
  int  nUseTabs;
  char szKeyWord[80];
} OPTIONS;

OPTIONS opt;

// Массив описаний страниц блокнота Wizard
PROPSHEETPAGE   psheetPage[3];

// Заголовок блокнота Wizard
PROPSHEETHEADER psheetHeader;

HINSTANCE hInst;
char szAppName[]  = "WizardApp";
char szAppTitle[] = "Wizard Demo";

// -----------------------------------------------------
// Функция 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);

    default:
      return(DefWindowProc(hWnd, msg, wParam, lParam));
  }
}

// -----------------------------------------------------
// Функция WndProc_OnCreate
// -----------------------------------------------------
BOOL WndProc_OnCreate(HWND hWnd, 
  LPCREATESTRUCT lpCreateStruct)
{
  // Инициализируем библиотеку стандартных органов управления
  InitCommonControls();

  // Инициализируем параметры
  opt.nBold =
  opt.nItalic =
  opt.nUnderline =
  opt.nUseTabs = 0;
  strcpy(opt.szKeyWord, "Undef");

  return TRUE;
}

// -----------------------------------------------------
// Функция WndProc_OnDestroy
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnDestroy(HWND hWnd)
{
  PostQuitMessage(0);
  return 0L;
}

// -----------------------------------------------------
// Функция 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); // завершаем работу приложения
      return 0L;
      break;
      
    case ID_HELP_ABOUT:
      MessageBox(hWnd, 
        "Wizard Demo Application, v.1.0\n"
        "(C) Alexandr Frolov, 1995\n"
        "Email: frolov@glas.apc.org",
        szAppTitle, MB_OK | MB_ICONINFORMATION);
      return 0L;
      break;

    case ID_FILE_OPTIONS:  
    {
      // Инициализируем страницы блокнота Wizard
      psheetPage[0].dwSize = sizeof(PROPSHEETPAGE);
      psheetPage[0].hInstance = hInst;
      psheetPage[0].pszIcon = MAKEINTRESOURCE(IDI_EFFECTS);
      psheetPage[0].dwFlags = PSP_USETITLE | PSP_USEICONID;
      psheetPage[0].pszTemplate = 
        MAKEINTRESOURCE(IDD_DIALOG1);
      psheetPage[0].pfnDlgProc = DlgProc1;
      psheetPage[0].pszTitle = "Set Effects";
      psheetPage[0].lParam = 0;

      psheetPage[1].dwSize = sizeof(PROPSHEETPAGE);
      psheetPage[1].hInstance = hInst;
      psheetPage[1].pszIcon = MAKEINTRESOURCE(IDI_TAB);
      psheetPage[1].dwFlags = PSP_USETITLE | PSP_USEICONID;
      psheetPage[1].pszTemplate = 
        MAKEINTRESOURCE(IDD_DIALOG2);
      psheetPage[1].pfnDlgProc = DlgProc2;
      psheetPage[1].pszTitle = "Using Tabs";
      psheetPage[1].lParam = 0;

      psheetPage[2].dwSize = sizeof(PROPSHEETPAGE);
      psheetPage[2].hInstance = hInst;
      psheetPage[2].pszIcon = MAKEINTRESOURCE(IDI_KEYWORD);
      psheetPage[2].dwFlags = PSP_USETITLE | PSP_USEICONID;
      psheetPage[2].pszTemplate = 
        MAKEINTRESOURCE(IDD_DIALOG3);
      psheetPage[2].pfnDlgProc = DlgProc3;
      psheetPage[2].pszTitle = "Keyword";
      psheetPage[2].lParam = 0;

      // Инициализируем заголовок блокнота Wizard
      psheetHeader.dwSize = sizeof(PROPSHEETHEADER);
      psheetHeader.hInstance = hInst;
      psheetHeader.pszIcon = NULL;
      psheetHeader.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD;
      psheetHeader.hwndParent = hWnd;
      psheetHeader.pszCaption = "Wizard Demo Sample";
      psheetHeader.nPages = 
        sizeof(psheetPage) / sizeof(PROPSHEETPAGE);
      psheetHeader.ppsp = (LPCPROPSHEETPAGE)&psheetPage;
      
      // Создаем и отображаем блокнот Wizard
      PropertySheet(&psheetHeader);

      return 0L;
      break;
    }
    default:
    break;
  }
  return FORWARD_WM_COMMAND(hWnd, id, hwndCtl, 
    codeNotify, DefWindowProc);
}

// -----------------------------------------------------
// Функция DlgProc1
// для первой страницы блокнота
// -----------------------------------------------------
BOOL APIENTRY
DlgProc1(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch(msg)
  {
    HANDLE_MSG(hdlg, WM_INITDIALOG, DlgProc1_OnInitDialog);
    HANDLE_MSG(hdlg, WM_NOTIFY,     DlgProc1_OnNotify);
    default:
      break;
  }
  return FALSE;
}

// -----------------------------------------------------
// Функция DlgProc1_OnInitDialog
// Вызывается при инициализации первой страницы
// -----------------------------------------------------
BOOL DlgProc1_OnInitDialog(HWND hdlg, 
  HWND hwndFocus, LPARAM lParam)
{
  // Устанавливаем переключатели в соответствии
  // со значениями параметров, записанных в 
  // структуре opt
  SendMessage(GetDlgItem(hdlg, IDC_BOLD), 
    BM_SETCHECK, opt.nBold, 0L);

  SendMessage(GetDlgItem(hdlg, IDC_ITALIC), 
    BM_SETCHECK, opt.nItalic, 0L);

  SendMessage(GetDlgItem(hdlg, IDC_UNDERLINE), 
    BM_SETCHECK, opt.nUnderline, 0L);

  return TRUE;
}

// -----------------------------------------------------
// Функция DlgProc1_OnNotify
// Обрабатывает извещение от первой страницы
// -----------------------------------------------------
LRESULT 
DlgProc1_OnNotify(HWND hdlg, int idFrom, NMHDR* pnmhdr)
{
  switch(pnmhdr->code)
  {
    case PSN_SETACTIVE:
    {
      // Разблокируем кнопку Next
      PropSheet_SetWizButtons(GetParent(hdlg), PSWIZB_NEXT);
      break;
    }

    case PSN_WIZNEXT:
    {
      opt.nBold = (int)SendMessage(
        GetDlgItem(hdlg, IDC_BOLD), BM_GETCHECK, 0L, 0L);

      opt.nItalic = (int)SendMessage(
        GetDlgItem(hdlg, IDC_ITALIC), BM_GETCHECK, 0L, 0L);

      opt.nUnderline = (int)SendMessage(
        GetDlgItem(hdlg, IDC_UNDERLINE), BM_GETCHECK, 0L, 0L);
      break;
    }
    default:
      break;
  }
  return FALSE;
}

// -----------------------------------------------------
// Функция DlgProc2
// для второй страницы 
// -----------------------------------------------------
BOOL APIENTRY
DlgProc2(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch(msg)
  {
    HANDLE_MSG(hdlg, WM_INITDIALOG, DlgProc2_OnInitDialog);
    HANDLE_MSG(hdlg, WM_NOTIFY,     DlgProc2_OnNotify);
    default:
      break;
  }
  return FALSE;
}

// -----------------------------------------------------
// Функция DlgProc2_OnInitDialog
// Вызывается при инициализации второй страницы
// -----------------------------------------------------
BOOL DlgProc2_OnInitDialog(HWND hdlg, 
  HWND hwndFocus, LPARAM lParam)
{
  SendMessage(GetDlgItem(hdlg, IDC_USETABS), 
    BM_SETCHECK, opt.nUseTabs, 0L);

  SendMessage(GetDlgItem(hdlg, IDC_DONTUSETABS), 
    BM_SETCHECK, (opt.nUseTabs) ? 0 : 1, 0L);

  return TRUE;
}

// -----------------------------------------------------
// Функция DlgProc2_OnNotify
// Обрабатывает извещение от второй страницы 
// -----------------------------------------------------
LRESULT 
DlgProc2_OnNotify(HWND hdlg, int idFrom, NMHDR* pnmhdr)
{
  switch(pnmhdr->code)
  {
    case PSN_SETACTIVE:
    {
      // Разблокируем кнопк Next и Back, когда страница
      // блокнота Wizard становится активной
      PropSheet_SetWizButtons(GetParent(hdlg), 
        PSWIZB_NEXT | PSWIZB_BACK);
      break;
    }

    case PSN_WIZNEXT:
    {
      opt.nUseTabs = (int)SendMessage(
        GetDlgItem(hdlg, IDC_USETABS), BM_GETCHECK, 0L, 0L);
      break;
    }
    default:
      break;
  }
  return FALSE;
}

// -----------------------------------------------------
// Функция DlgProc3
// для третьей страницы 
// -----------------------------------------------------
BOOL APIENTRY
DlgProc3(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch(msg)
  {
    HANDLE_MSG(hdlg, WM_INITDIALOG, DlgProc3_OnInitDialog);
    HANDLE_MSG(hdlg, WM_NOTIFY,     DlgProc3_OnNotify);
    HANDLE_MSG(hdlg, WM_COMMAND,    DlgProc3_OnCommand);
    default:
      break;
  }
  return FALSE;
}

// -----------------------------------------------------
// Функция DlgProc3_OnInitDialog
// Вызывается при инициализации третьей страницы 
// -----------------------------------------------------
BOOL DlgProc3_OnInitDialog(HWND hdlg, 
  HWND hwndFocus, LPARAM lParam)
{
  SetWindowText(GetDlgItem(hdlg, IDC_EDITKEYWORD), 
    opt.szKeyWord);
  return TRUE;
}

// -----------------------------------------------------
// Функция DlgProc3_OnNotify
// Обрабатывает извещение от третьей страницы 
// -----------------------------------------------------
LRESULT 
DlgProc3_OnNotify(HWND hdlg, int idFrom, NMHDR* pnmhdr)
{
  switch(pnmhdr->code)
  {
    case PSN_SETACTIVE:
    {
      // Разблокируем кнопку Back, когда страница
      // блокнота становится активной
      PropSheet_SetWizButtons(GetParent(hdlg), PSWIZB_BACK);
      break;
    }
        
    case PSN_WIZFINISH:
    {
      char szBuf[256];
      
      GetWindowText(GetDlgItem(hdlg, IDC_EDITKEYWORD), 
        opt.szKeyWord, 80);

      // Заполнение структуры opt завершено, теперь мы
      // выводим на экран установленные параметры
      wsprintf(szBuf,
        "Bold    \t= %d\n"
        "Italic  \t= %d\n"
        "Underline\t= %d\n"
        "Use Tabs\t= %d\n"
        "Keyword\t= %s\n",
        opt.nBold, opt.nItalic, opt.nUnderline,
        opt.nUseTabs, opt.szKeyWord);

      MessageBox(NULL, szBuf, "Options", 
        MB_OK | MB_ICONINFORMATION);
      break;
    }
    default:
    break;
  }
  return FALSE;
}

// -----------------------------------------------------
// Функция DlgProc3_OnCommand
// -----------------------------------------------------
#pragma warning(disable: 4098)
void DlgProc3_OnCommand(HWND hdlg, int id, 
  HWND hwndCtl, UINT codeNotify)
{
  // Сообщение от редактора текста
  if(id == IDC_EDITKEYWORD)
  {
    // Если пользователь изменил ключевое слово в окне
    // редактирования, разблокируем кнопку Finish
    if(codeNotify == EN_CHANGE)
    {
      PropSheet_SetWizButtons(GetParent(hdlg), 
        PSWIZB_BACK | PSWIZB_FINISH);
    }
  }
  return FALSE;
}

Файл wizdemo.h (листинг 6.6) содержит описание функций, определенный в нашем приложении.

Листинг 6.6. Файл wizdemo\wizdemo.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);
BOOL APIENTRY
DlgProc1(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL DlgProc1_OnInitDialog(HWND hwnd,HWND hwndFocus, 
  LPARAM lParam);
LRESULT DlgProc1_OnNotify(HWND hWnd, int idFrom, 
  NMHDR* pnmhdr);
BOOL APIENTRY
DlgProc2(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL DlgProc2_OnInitDialog(HWND hwnd, 
  HWND hwndFocus, LPARAM lParam);
LRESULT DlgProc2_OnNotify(HWND hWnd, int idFrom, 
  NMHDR* pnmhdr);
BOOL APIENTRY
DlgProc3(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL DlgProc3_OnInitDialog(HWND hwnd, 
  HWND hwndFocus, LPARAM lParam);
LRESULT DlgProc3_OnNotify(HWND hWnd, int idFrom, 
  NMHDR* pnmhdr);
void DlgProc3_OnCommand(HWND hWnd, int id, 
  HWND hwndCtl, UINT codeNotify);

В файле resource.h (который создается автоматически системой Microsoft Visual C++) находятся определения констант для работы с ресурсами приложения Wizard Demo. Этот файл представлен в листинге 6.7.

Листинг 6.7. Файл wizdemo\resource.h


//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by WIZDEMO.RC
//
#define IDR_APPMENU                     102
#define IDI_APPICON                     103
#define IDI_APPICONSM                   104
#define IDI_EFFECTS                     105
#define IDI_TAB                         106
#define IDI_KEYWORD                     107
#define IDD_DIALOG1                     121
#define IDD_DIALOG2                     122
#define IDD_DIALOG3                     123
#define IDC_BOLD                        1000
#define IDC_ITALIC                      1001
#define IDC_UNDERLINE                   1002
#define IDC_USETABS                     1004
#define IDC_EDITKEYWORD                 1006
#define IDC_DONTUSETABS                 1007
#define ID_FILE_EXIT                    40001
#define ID_HELP_ABOUT                   40003
#define ID_FILE_OPTIONS                 40029

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        125
#define _APS_NEXT_COMMAND_VALUE         40030
#define _APS_NEXT_CONTROL_VALUE         1008
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

Файл wizdemo.rc (листинг 6.8) содержит определение ресурсов приложения Wizard Demo. Он создается автоматически.

Листинг 6.8. Файл wizdemo\wizdemo.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 "&Options...",                 ID_FILE_OPTIONS
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       ID_FILE_EXIT
    END
    POPUP "&Help"
    BEGIN
        MENUITEM "&About...",                   ID_HELP_ABOUT
    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     "wizdemo.ico"
IDI_APPICONSM           ICON    DISCARDABLE     "wizdemsm.ico"
IDI_EFFECTS             ICON    DISCARDABLE     "EFFECTS.ICO"
IDI_TAB                 ICON    DISCARDABLE     "TAB.ICO"
IDI_KEYWORD             ICON    DISCARDABLE     "KEYWORD.ICO"

//////////////////////////////////////////////////////////////
// Dialog
//

IDD_DIALOG1 DIALOG DISCARDABLE  0, 0, 186, 95
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
FONT 8, "MS Sans Serif"
BEGIN
  CONTROL "Bold",IDC_BOLD,"Button",
    BS_AUTOCHECKBOX | WS_TABSTOP,19,21,35,10
  CONTROL "Italic",IDC_ITALIC,"Button",
    BS_AUTOCHECKBOX | WS_TABSTOP,19,32,35,10
  CONTROL "Underline",IDC_UNDERLINE,"Button",
    BS_AUTOCHECKBOX | WS_TABSTOP,19,43,46,10
  GROUPBOX "Effects",IDC_STATIC,8,7,112,53
END

IDD_DIALOG2 DIALOG DISCARDABLE  0, 0, 186, 95
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
FONT 8, "MS Sans Serif"
BEGIN
  CONTROL "Use Tabs", IDC_USETABS, "Button",
   BS_AUTORADIOBUTTON,18,22, 63,10
  GROUPBOX "Tabs",IDC_STATIC,9,7,105,63
  CONTROL  "Don't use Tabs",IDC_DONTUSETABS,"Button",
           BS_AUTORADIOBUTTON,18,35,83,10
END

IDD_DIALOG3 DIALOG DISCARDABLE  0, 0, 211, 102
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
FONT 8, "MS Sans Serif"
BEGIN
  EDITTEXT   IDC_EDITKEYWORD,24,58,138,13,ES_AUTOHSCROLL
  GROUPBOX   "Keyword",IDC_STATIC,11,38,166,52
  ICON       IDI_APPICON,IDC_STATIC,11,7,18,20
END

//////////////////////////////////////////////////////////////
// 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

Описание функций

Займемся описанием глобальных переменных и функций приложения Wizard Demo, обратив внимание на отличия от приложения Property Sheet Demo.

Глобальные переменные

Мы бы могли создать орган управления Wizard точно таким же способом, что и блокнот, добавляя страницы по одной с помощью функции CreatePropertySheetPage. Однако есть и другой способ, который не требует использования этой функции. В этом случае нам не потребуется и массив структур hPage типа HPROPSHEETPAGE, который мы изъяли из приложения Wizard Demo.

WndProc_OnCommand

При создании органа управления Wizard массив структур psheetPage, описывающих страницы, заполняется точно также, как и в приложении Property Sheet Demo.

Однако заголовок блокнота Wizard инициализируется немного по-другому. Например, в поле dwFlags устанавливаются флаги PSH_PROPSHEETPAGE и PSH_WIZARD.

Первый из них говорит о том, что в поле psheetHeader.ppsp будет записан адрес заполненного массива структур, описывающих страницы. Это поле используется вместо поля psheetHeader.phpage, в который мы записывали адрес массива идентификатора страниц, созданных функцией CreatePropertySheetPage.

Флаг PSH_WIZARD говорит о том, что необходимо создать орган управления Wizard, а не обычный блокнот Property Sheet.

Блокнот Wizard создается и отображается функцией PropertySheet, как и в предыдущем приложении.

DlgProc1_OnNotify

Функция DlgProc1_OnNotify обрабатывает извещения PSN_SETACTIVE и PSN_WIZNEXT.

Обработчик извещения PSN_SETACTIVE разблокирует кнопку Next, вызывая макрокоманду PropSheet_SetWizButtons :

PropSheet_SetWizButtons(GetParent(hdlg), PSWIZB_NEXT);

Эта макрокоманда посылает окну блокнота Wizard сообщение PSM_SETWIZBUTTONS. Второй параметр макрокоманды может принимать значения PSWIZB_BACK (разблокировка кнопки Back), PSWIZB_NEXT (разблокировка кнопки Next) или PSWIZB_FINISH (разблокировка кнопки Finish). Можно также использовать любую комбинацию этих значений, объединяя их при помощи логической операции ИЛИ. Если в качестве второго параметра макрокоманды PropSheet_SetWizButtons указать нулевое значение, все перечисленные выше кнопки будут заблокированы.

Извещение PSN_WIZNEXT поступает в функцию диалога первой страницы тогда, когда пользователь переходит к следующей странице, нажимая кнопку Next. Наш обработчик получает состояние переключателей и записывает его в соответствующие поля структуры opt.

DlgProc2_OnNotify

Задача функции DlgProc2_OnNotify - разблокировка кнопок Next и Back, когда пользователь переключается на вторую страницу. Для разблокировки вызывается только что описанная макрокоманда PropSheet_SetWizButtons :

PropSheet_SetWizButtons(GetParent(hdlg), 
  PSWIZB_NEXT | PSWIZB_BACK);

В ответ на извещение PSN_WIZNEXT функция DlgProc2_OnNotify получает состояние переключателя IDC_USETABS и записывает его в поле nUseTabs структуры opt.

DlgProc3_OnNotify

Функция DlgProc3_OnNotify обрабатывает извещения, которые поступают в функцию диалога второй страницы.

Обработчик извещения PSN_SETACTIVE разблокирует кнопку Back.

При поступлении извещения PSN_WIZFINISH функция диалога отображает установленные параметры. Однако для того чтобы такое извещение поступило в функцию диалога, кнопка Next должна быть преобразована в кнопку Finish. Эту задачу решает обработчик сообщения WM_COMMAND, описанный ниже.

DlgProc3_OnCommand

Обработчик сообщения WM_COMMAND отображает кнопки Back и Finish, когда пользователь изменил ключевое слово. Это делается так:

PropSheet_SetWizButtons(GetParent(hdlg),
  PSWIZB_BACK | PSWIZB_FINISH);
[Назад] [Содеожание] [Дальше]