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