Как реагировать на кнопку OK или кнопку "Применить" в PropertySheet после обработки страниц?

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам