Как реагировать на кнопку OK или кнопку «Применить» в PropertySheet после обработки страниц? - PullRequest
1 голос
/ 01 октября 2009

API PropertySheet позволяет определить PropSheetProc, который может (в Windows XP и выше) получать сообщения при нажатии кнопки OK или Применить. Это позволяет выполнять обработку при нажатии одной из этих кнопок.

Однако этот обработчик вызывается до , когда отдельные страницы свойств получают уведомление PSN_APPLY через соответствующие диалоговые процедуры. Я хочу выполнить обработку после обработки этих уведомлений, желательно без уродливых хаков. Как мне это сделать?

Справочная информация: Я храню свою конфигурацию в одном struct, и отдельные страницы изменяют части этого struct, когда они применяются. Затем, после того, как эти значения были записаны, я хочу применить настройки из struct сразу, вместо повторного применения всех из каждой страницы свойств.

Ответы [ 3 ]

2 голосов
/ 02 октября 2009

В итоге я использовал обратный вызов 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 заявления, даже если есть только один случай для рассмотрения. Я странный, как это.)

0 голосов
/ 01 октября 2009

Вам НЕ НУЖНО применять структуру из любого из обработчиков диалогов. Итак, если это модальный лист свойств, вы можете сделать что-то простое, например:

// 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.

0 голосов
/ 01 октября 2009

не могли бы вы просто перехватить сообщение BL_CLICKED от WM_COMMAND для идентификаторов IDOK, IDAPPLY и IDCANCEL?

Вы используете MFC? или ATL?

Хотя я не могу вспомнить время, я не смог бы перехватить BM_CLICKED ...

Редактировать: Хмм никогда не использовал страницы свойств через эту функцию ... Просто прочитал ее. Вы установили функцию pfnCallback и флаг PSH_USECALLBACK?

На каждой странице также есть диалог proc. Вы не можете перехватить ОК, отменить и применить оттуда, а? Я думаю, что другой план кажется более подходящим.

...