Winapi 如何响应属性表';页面处理完毕后,单击“确定”或“应用”按钮?

Winapi 如何响应属性表';页面处理完毕后,单击“确定”或“应用”按钮?,winapi,button,propertysheet,Winapi,Button,Propertysheet,PropertySheetAPI允许您定义一个PropSheetProc,当按下“确定”或“应用”按钮时,它可以(在Windows XP及更高版本上)接收消息。这使您可以在单击其中一个按钮时进行处理 但是,在各个属性页通过各自的对话框过程收到PSN\u APPLY通知之前,会调用此处理程序。我希望在处理完这些通知后再进行处理,最好不要进行任何令人讨厌的黑客攻击。我该怎么做 背景:我将配置存储在一个struct中,每个页面在应用时都会修改该struct的各个部分。然后,在写入这些值之后,我想一次应

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

但是,在各个属性页通过各自的对话框过程收到
PSN\u APPLY
通知之前,会调用此处理程序。我希望在处理完这些通知后再进行处理,最好不要进行任何令人讨厌的黑客攻击。我该怎么做


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

您不能截取WM_命令的BL_CLICKED消息以获取ids IDOK、IDAPPLY和IDCANCEL吗

你在用MFC吗?还是ATL

虽然我想不出有哪一次我不能拦截BMU

编辑:嗯,从未通过该功能使用过属性页。。。刚刚通读了一遍。您是否设置了pfnCallback函数和PSH_USECALLBACK标志集


每个页面也有一个对话框进程。你不能拦截“确定”、“取消”并从那里申请吗?不过,我认为另一种方案似乎更合适。

您不需要从任何对话框处理程序内部应用结构。因此,如果是模态属性表,您可以执行以下简单操作:

// 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”只是收集在页面上输入的信息,您不会在用户与页面交互时更改struct。忽略每页
PSN\u APPLY
消息,并在调用PropSheetProc时应用结构。或者如果通知是
PSN\u CANCEL

则完全放弃它。我最终使用
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;
}

(是的,我使用<代码>开关>代码>语句,即使只有一个案例要考虑。我很奇怪。)

我必须在我的主消息循环中这样做,这在应用程序的一个完全无关的部分。我甚至不确定这些消息是否会在那里传递,因为在属性页对话框关闭之前,
PropertySheet()
不会返回。@Edit:我使用的是
pfnCallback
,调用它很好,但在任何单个属性页的对话框过程之前。我想在所有这些人都完成了他们的工作后再做些事情,但那是行不通的。如果用户单击“应用”,则需要应用stuff,但
PropertySheet
函数尚未返回。PropertySheet函数将首先发送PSN_应用消息PRopSheetProc,然后发送到每个页面,然后返回。现在将设置结构,您可以应用它吗?在属性表明显关闭之前“应用”结构真的很重要吗?