Как реагировать на кнопку OK или кнопку "Применить" в PropertySheet после обработки страниц?
PropertySheet
API позволяет определить PropSheetProc
который может (в Windows XP и выше) получать сообщения при нажатии кнопки OK или Применить. Это позволяет выполнять обработку при нажатии одной из этих кнопок.
Однако этот обработчик вызывается до того, как отдельные страницы свойств получат PSN_APPLY
уведомление через их соответствующие процедуры диалога. Я хочу сделать свою обработку после обработки этих уведомлений, желательно без уродливых хаков. Как мне это сделать?
Справочная информация: я храню свою конфигурацию в одном struct
и отдельные страницы каждая изменяют части этого struct
когда они применяются. Затем, после того, как эти значения были записаны, я хочу применить настройки из struct
все сразу, вместо повторного применения всех из каждой страницы свойств.
3 ответа
Я закончил тем, что использовал PropSheetProc
обратный вызов для захвата дескриптора окна листа свойств, а затем подключить процедуру окна подкласса, например так:
// This is not officially defined, but the whole world uses it.
#define ID_APPLY_NOW 0x3021
WNDPROC origWinProc;
LRESULT CALLBACK MyWinProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
// Call the original window procedure.
LRESULT retVal = CallWindowProc(origWinProc, hwndDlg, msg, wParam, lParam);
// Now, and only now, do our own stuff.
switch (msg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case ID_APPLY_NOW:
applyConfig();
saveConfig();
break;
}
break;
}
// Return the original winproc's result.
return retVal;
}
int CALLBACK myPropSheetProc(HWND hwndDlg, UINT msg, LPARAM lParam) {
switch (msg) {
case PSCB_INITIALIZED:
// Override the property sheet's window procedure with our own.
origWinProc = (WNDPROC)SetWindowLongPtr(hwndDlg, GWLP_WNDPROC, (LONG_PTR)&MyWinProc);
break;
}
return 0;
}
(Да, я использую switch
заявления, даже если есть только один случай для рассмотрения. Я такой странный.)
Вам НЕ НУЖНО применять структуру из любого из обработчиков диалога. Итак, если это модальный лист свойств, вы можете сделать что-то простое, например:
// Display the property sheet.
PropertySheet(&theSheet);
// The peroperty sheets PSN_APPLY notification sets this bool to true in the struct.
if(theStruct.fApply)
ApplyTheStruct(&theStruct);
Кроме того, я не понимаю, почему, учитывая, что "struct" просто собирает информацию, введенную на страницах, вы не изменяете структуру, когда пользователь взаимодействует со страницей. Игнорировать на странице PSN_APPLY
сообщения и применять структуру при вызове PropSheetProc. ИЛИ полностью отменить его, если уведомление PSN_CANCEL
,
Не могли бы вы просто перехватить сообщение WM_COMMAND BL_CLICKED для идентификаторов IDOK, IDAPPLY и IDCANCEL?
Вы используете MFC? или ATL?
Хотя я не могу вспомнить время, когда я не смог бы перехватить BM_CLICKED...
Изменить: Хмм никогда не использовал страницы свойств через эту функцию... Просто прочитал его. Вы установили функцию pfnCallback и флаг PSH_USECALLBACK?
На каждой странице также есть диалог proc. Вы не можете перехватить ОК, отменить и применить оттуда, а? Я думаю, что другой план, кажется, подходит больше, хотя.