如何在页面处理后响应PropertySheet的OK或Apply按钮?

时间:2009-09-30 20:46:36

标签: winapi button propertysheet

PropertySheet API允许您定义PropSheetProc,当按下“确定”或“应用”按钮时,可以(在Windows XP及更高版本上)接收消息。这使您可以在单击其中一个按钮时进行处理。

但是,此处理程序在之前被称为,各个属性页通过各自的对话程序接收PSN_APPLY通知。我希望在处理完这些通知后进行处理,最好没有丑陋的黑客攻击。我该怎么做?

后台:我将我的配置存储在一个struct中,并且每个页面在应用时都会修改此struct的部分内容。然后,在写完这些值之后,我想立即应用struct所有设置,而不是从每个属性页重新应用所有这些设置。

3 个答案:

答案 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,则完全丢弃。