
Ч. Петзолд Программирование для Windowsо 95 в двух томах Том I BHV Ч Санкт-Петербург Дюссельдорф Киев Москва Санкт-Петербург Содержание ЧАСТЬ I ВВЕДЕНИЕ ...
-- [ Страница 12 ] --//------------------------------------------------------------------- UINT CALLBACK ExStylePageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp) { switch(uMsg) { case PSPCB_CREATE :
// Store pointer to extended style data pTheExStyles =(LPDWORD) ppsp->lParam;
return TRUE;
case PSPCB_RELEASE :
break;
} return 0;
} //------------------------------------------------------------------- BOOL CALLBACK ExStyleDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_INITDIALOG :
{ BOOL bCheck;
DWORD dwOrigStyle = *pTheExStyles;
bCheck =(dwOrigStyle & WS_EX_CLIENTEDGE);
SetButtonCheck(hwndDlg, IDC_CLIENTEDGE, bCheck);
bCheck =(dwOrigStyle & WS_EX_CONTEXTHELP);
SetButtonCheck(hwndDlg, IDC_CONTEXTHELP, bCheck);
bCheck =(dwOrigStyle & WS_EX_DLGMODALFRAME);
SetButtonCheck(hwndDlg, IDC_DLGMODALFRAME, bCheck);
bCheck =(dwOrigStyle & WS_EX_OVERLAPPEDWINDOW);
SetButtonCheck(hwndDlg, IDC_EXOVERLAPPED, bCheck);
bCheck =(dwOrigStyle & WS_EX_PALETTEWINDOW);
SetButtonCheck(hwndDlg, IDC_PALETTE, bCheck);
bCheck =(dwOrigStyle & WS_EX_STATICEDGE);
SetButtonCheck(hwndDlg, IDC_STATICEDGE, bCheck);
bCheck =(dwOrigStyle & WS_EX_TOOLWINDOW);
SetButtonCheck(hwndDlg, IDC_TOOLWINDOW, bCheck);
bCheck =(dwOrigStyle & WS_EX_WINDOWEDGE);
SetButtonCheck(hwndDlg, IDC_WINDOWEDGE, bCheck);
bCheck =(dwOrigStyle & WS_EX_ACCEPTFILES);
SetButtonCheck(hwndDlg, IDC_ACCEPTFILES, bCheck);
bCheck =(dwOrigStyle & WS_EX_APPWINDOW);
SetButtonCheck(hwndDlg, IDC_APPWINDOW, bCheck);
bCheck =(dwOrigStyle & WS_EX_TOPMOST);
SetButtonCheck(hwndDlg, IDC_TOPMOST, bCheck);
bCheck =(dwOrigStyle & WS_EX_TRANSPARENT);
SetButtonCheck(hwndDlg, IDC_TRANSPARENT, bCheck);
bCheck =(dwOrigStyle & WS_EX_CONTROLPARENT);
SetButtonCheck(hwndDlg, IDC_CONTROLPARENT, bCheck);
bCheck =(dwOrigStyle & WS_EX_MDICHILD);
SetButtonCheck(hwndDlg, IDC_MDICHILD, bCheck);
bCheck =(dwOrigStyle & WS_EX_NOPARENTNOTIFY);
SetButtonCheck(hwndDlg, IDC_NOPARENTNOTIFY, bCheck);
return TRUE;
} case WM_COMMAND :
{ WORD wNotifyCode = HIWORD(wParam);
WORD wID = LOWORD(wParam);
HWND hwndSheet;
switch(wID) { case IDC_CLIENTEDGE :
case IDC_CONTEXTHELP :
case IDC_DLGMODALFRAME :
case IDC_EXOVERLAPPED :
case IDC_PALETTE :
case IDC_STATICEDGE :
case IDC_TOOLWINDOW :
case IDC_WINDOWEDGE :
case IDC_ACCEPTFILES :
case IDC_APPWINDOW :
case IDC_TOPMOST :
case IDC_TRANSPARENT :
case IDC_CONTROLPARENT :
case IDC_MDICHILD :
case IDC_NOPARENTNOTIFY :
hwndSheet = GetParent(hwndDlg);
PropSheet_Changed(hwndSheet, hwndDlg);
break;
} return TRUE;
} case WM_HELP :
// Catch F1 key strike MessageBox(hwndDlg, "WM_HELP Message Received", "ExStyleDlgProc", MB_OK);
return TRUE;
case WM_NOTIFY :
{ LPNMHDR pnmh =(LPNMHDR) lParam;
// Handle Finish button on wizard page if(pnmh->code == PSN_WIZFINISH) { HWND hwndPS;
hwndPS = GetParent(hwndDlg);
PropSheet_Apply(hwndPS);
return TRUE;
} // Handle OK and Apply buttons if(pnmh->code == PSN_APPLY || pnmh->code == PSN_RESET) { HWND hwndPS;
HWND hwndActive;
// Overwrite current style value *pTheExStyles = FetchExStyles(hwndDlg);
// Tell main window to re-create child window hwndPS = GetParent(hwndDlg);
hwndActive = PropSheet_GetCurrentPageHwnd(hwndPS);
// Only re-create if we're the active page if(hwndDlg == hwndActive) PostMessage(hwndMain, PM_CREATEWINDOW, 0, 0L);
} // Destroy modeless dialog on OK or Cancel if((IsWindowEnabled(hwndMain)) && (pnmh->code == PSN_APPLY || pnmh->code == PSN_RESET)) { LPPSHNOTIFY psh =(LPPSHNOTIFY) lParam;
HWND hwndPropSheet;
// Ignore Apply button if(pnmh->code == PSN_APPLY && psh->lParam == 0) return TRUE;
// Clicking OK or Cancel, destroy property sheet hwndPropSheet = GetParent(hwndDlg);
DestroyWindow(hwndPropSheet);
hwndModeless = NULL;
} // Enable Back and Finish buttons on wizard page if(bWizard && pnmh->code == PSN_SETACTIVE) { HWND hwndSheet = GetParent(hwndDlg);
PropSheet_SetWizButtons(hwndSheet, PSWIZB_BACK | PSWIZB_FINISH);
} // Support for Help button if(pnmh->code == PSN_HELP) { MessageBox(hwndDlg, "PSN_HELP Notification Received", "ExStyleDlgProc", MB_OK);
} return TRUE;
} default :
return FALSE;
} } //------------------------------------------------------------------- DWORD FetchExStyles(HWND hwndDlg) { DWORD dwStyle = 0L;
if(QueryButtonCheck(hwndDlg, IDC_CLIENTEDGE)) { dwStyle |= WS_EX_CLIENTEDGE;
} if(QueryButtonCheck(hwndDlg, IDC_CONTEXTHELP)) { dwStyle |= WS_EX_CONTEXTHELP;
} if(QueryButtonCheck(hwndDlg, IDC_DLGMODALFRAME)) { dwStyle |= WS_EX_DLGMODALFRAME;
} if(QueryButtonCheck(hwndDlg, IDC_EXOVERLAPPED)) { dwStyle |= WS_EX_OVERLAPPEDWINDOW;
} if(QueryButtonCheck(hwndDlg, IDC_PALETTE)) { dwStyle |= WS_EX_PALETTEWINDOW;
} if(QueryButtonCheck(hwndDlg, IDC_STATICEDGE)) { dwStyle |= WS_EX_STATICEDGE;
} if(QueryButtonCheck(hwndDlg, IDC_TOOLWINDOW)) { dwStyle |= WS_EX_TOOLWINDOW;
} if(QueryButtonCheck(hwndDlg, IDC_WINDOWEDGE)) { dwStyle |= WS_EX_WINDOWEDGE;
} if(QueryButtonCheck(hwndDlg, IDC_ACCEPTFILES)) { dwStyle |= WS_EX_ACCEPTFILES;
} if(QueryButtonCheck(hwndDlg, IDC_APPWINDOW)) { dwStyle |= WS_EX_APPWINDOW;
} if(QueryButtonCheck(hwndDlg, IDC_TOPMOST)) { dwStyle |= WS_EX_TOPMOST;
} if(QueryButtonCheck(hwndDlg, IDC_TRANSPARENT)) { dwStyle |= WS_EX_TRANSPARENT;
} if(QueryButtonCheck(hwndDlg, IDC_CONTROLPARENT)) { dwStyle |= WS_EX_CONTROLPARENT;
} if(QueryButtonCheck(hwndDlg, IDC_MDICHILD)) { dwStyle |= WS_EX_MDICHILD;
} if(QueryButtonCheck(hwndDlg, IDC_NOPARENTNOTIFY)) { dwStyle |= WS_EX_NOPARENTNOTIFY;
} return dwStyle;
} HELPER.C /*-------------------------------- HELPER.C -- Helper routines (c) Paul Yao, --------------------------------*/ #include
if(bCheck) { Button_SetCheck(hwndCtrl, BST_CHECKED);
} } //------------------------------------------------------------------- BOOL QueryButtonCheck(HWND hwndDlg, int CtrlID) { HWND hwndCtrl = GetDlgItem(hwndDlg, CtrlID);
int nCheck = Button_GetCheck(hwndCtrl);
return(nCheck == BST_CHECKED);
} PROPERTY.RC #include "property.h" #include
Флаги стиля для создания дочернего окна запоминаются в двух глобальных переменных, определенных в файле PROPERTY.C:
DWORD dwChildStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CAPTION;
DWORD dwChildExStyle = 0L;
Указатели на каждую из этих переменных передаются каждой странице свойств в поле lParam структуры PRPSHEETPAGE. Например, ниже показано, как dwChildStyle передается первой странице свойств (см. файл SHEET.C):
pspage[0].lParam =(LPARAM) &dwChildStyle;
Первая страница свойств извлекает это значение в своей оконной процедуре (StylePageProc). Расположенная в файле PAGE1.C, эта функция вызывается непосредственно перед созданием страницы свойств с кодом сообщения PSPCB_CREATE. Этот указатель запоминается в глобальной переменной, объявленной как static, и поэтому, имеющей область видимости, ограниченную этим исходным файлом:
// Сохранить указатель на данные о стиле pTheStyles =(LPDWORD) ppsp->lParam;
Здесь ppsp Ч указатель на структуру страницы свойств PROPSHEETPAGE, переданную в функцию страницы свойств.
Каждая страница свойств имеет указатель на данные, которые могут быть изменены в ней. Поэтому, когда становится необходимым применить сделанные изменения, каждая диалоговая процедура страницы свойств записывает эти изменения обратно в источник данных. Кажется, что было бы проще использовать глобальные переменные. Это общая практика при работе с обычными диалоговыми окнами. Но мы используем параметр lParam для того, чтобы показать, как "удаленная" страница свойств Ч такая как расположенная в динамически подключаемой библиотеке Ч может быть инициализирована без использования чего-либо кроме содержимого структуры PROPSHEETPAGE.
Внутри диалоговых процедур страниц свойств наиболее интересным является обработка сообщения WM_NOTIFY. При нажатии кнопок OK или Apply диалоговые процедуры получают уведомление PSN_APPLY. Как уже упоминалось ранее, страницы свойств создаются по мере их активизации пользователем. Только страницы, которые были реально созданы, получают уведомления. Это означает, что когда набор страниц свойств уничтожается, только одна или обе диалоговые процедуры могут получить уведомление PSN_APPLY.
Для того, чтобы быть уверенным в том, что изменения данных будут применены только один раз, каждая диалоговая процедура проверяет, являлась ли ее страница активной перед посылкой запроса PM_CREATEWINDOW главному окну программы. Это делается с помощью посылки сообщения PSM_GETCURRENTPAGEHWND окну набора страниц свойств, в ответ на которое возвращается описатель окна активной страницы. Запрос на воссоздание дочернего окна посылается функцией PostMessage с целью избежать временных проблем при посылке сообщения из диалоговой процедуры активной страницы:
HWND hwndPS = GetParent(hwndDlg);
HWND hwndActive = PropSheet_GetCurrentPageHwnd(hwndPS);
// Только для активной страницы if(hwndDlg == hwndActive) PostMessage(hwndMain, PM_CREATEWINDOW, 0, 0L);
Программа PROPERTY показывает, что все, что вы знаете о работе с диалоговыми окнами применимо к наборам страниц свойств. Имеется несколько различий, связанных с большей сложностью. Это касается мастеров, немодальных наборов страниц свойств и использования различных наборов кнопок.
Pages: | 1 | ... | 10 | 11 | 12 |
Книги, научные публикации