PropertySheet
API允许您定义PropSheetProc
,当按下“确定”或“应用”按钮时,可以(在Windows XP及更高版本上)接收消息。这使您可以在单击其中一个按钮时进行处理。
但是,此处理程序在之前被称为,各个属性页通过各自的对话程序接收PSN_APPLY
通知。我希望在处理完这些通知后进行处理,最好没有丑陋的黑客攻击。我该怎么做?
后台:我将我的配置存储在一个struct
中,并且每个页面在应用时都会修改此struct
的部分内容。然后,在写完这些值之后,我想立即应用struct
所有设置,而不是从每个属性页重新应用所有这些设置。
答案 0 :(得分:2)
我最终使用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
语句,即使只有一个案例要考虑。我很奇怪。)
答案 1 :(得分:0)
你能不能直接拦截WM_COMMAND的BL_CLICKED消息ID ID,IDAPPLY和IDCANCEL?
您使用的是MFC吗?还是ATL?
虽然我想不出时间我无法拦截BM_CLICKED ......
编辑:嗯从未通过该功能使用过属性页面......只是读过它。您是否设置了pfnCallback功能并设置了PSH_USECALLBACK标志?
每个页面还有一个对话框proc。你能否拦截好的,取消并从那里申请?我认为另一个计划似乎更适合。
答案 2 :(得分:0)
您无需在任何对话框处理程序中应用结构。所以,如果它是一个模态属性表,你可以做一些简单的事情:
// 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
,则完全丢弃。