1

PropertySheetAPI 允许您定义一个PropSheetProc可以(在 Windows XP 及更高版本上)在按下 OK 或 Apply 按钮时接收消息。这使您可以在单击这些按钮之一时进行处理。

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

背景:我将我的配置存储在一个 中struct,并且各个页面struct在应用时都会修改其中的一部分。然后,在写入这些值之后,我想struct一次应用所有设置,而不是从每个属性页重新应用所有设置。

4

3 回答 3

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即使只有一种情况需要考虑,我也会使用陈述。我很奇怪。)

于 2009-10-01T20:38:47.870 回答
0

你不能只截取 IDOK、IDAPPLY 和 IDCANCEL 的 WM_COMMAND 的 BL_CLICKED 消息吗?

你在使用 MFC 吗?还是 ATL?

虽然我想不出我无法拦截 BM_CLICKED 的时间......

编辑:嗯,从来没有通过该功能使用过属性页......只是读过它。您是否设置了 pfnCallback 函数和 PSH_USECALLBACK 标志集?

每个页面也有一个对话过程。你不能从那里截取确定、取消和申请吗?不过,我认为另一个计划似乎更适合。

于 2009-09-30T20:50:50.647 回答
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);

或者,我不明白为什么,鉴于“结构”只是收集在页面上输入的信息,当用户与页面交互时,您不会更改结构。在调用 PropSheetProc 时忽略每页PSN_APPLY消息并应用结构。或者如果通知是 ,则完全丢弃它PSN_CANCEL

于 2009-10-01T08:09:31.100 回答