Невозможно использовать PropSheet для создания диалогового окна листа свойств - PullRequest
0 голосов
/ 07 декабря 2011

Я создаю немодальный лист свойств, используя следующие настройки:

   PROPSHEETHEADER pshdr = { 0 };

   pshdr.dwSize = sizeof(PROPSHEETHEADER);
   pshdr.dwFlags = PSH_NOAPPLYNOW | PSH_PROPSHEETPAGE |
                   PSH_MODELESS | PSH_USECALLBACK;
   pshdr.pfnCallback = PropSheetProc;
   pshdr.hwndParent = mGlobalState->trayWin;
   pshdr.pszCaption = L"My Settings";
   pshdr.nPages = mPages.size();
   pshdr.ppsp = mWinPages;

В PropSheetProc я ловлю сообщение PSCB_PRECREATE и изменяю шаблон диалога, чтобы он получал стиль DS_CENTER:

static int CALLBACK
PropSheetProc(HWND hwndDlg,  // IN
              UINT uMsg,     // IN
              LPARAM lParam) // IN
{
   // Before the dialog is created, bless it with the DS_CENTER style.
   if (uMsg == PSCB_PRECREATE) {
      DLGTEMPLATE *dlgTemplate = (DLGTEMPLATE *)lParam;
      _ASSERT(dlgTemplate);

      dlgTemplate->style |= DS_CENTER;
   }

   return 0;
}

Однако центрирование диалога не удается. Вместо этого я попытался перехватить PSCB_INITIALIZED и вызвать метод CenterWindow на hwnd, переданном в PropSheetProc:

void
CenterWindow(HWND hwndWindow) // IN
{
   int nX, nY, nScreenWidth, nScreenHeight;
   RECT rectWindow;

   nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
   nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

   GetWindowRect(hwndWindow, &rectWindow);

   nX = (nScreenWidth - (rectWindow.right - rectWindow.left)) / 2;
   nY = (nScreenHeight - (rectWindow.bottom - rectWindow.top)) / 2;

   SetWindowPos(hwndWindow, 0, nX, nY, 0, 0,
                SWP_NOZORDER | SWP_NOSIZE);
}

Но это тоже не работает!

Наконец, я переместил вызов CenterWindow непосредственно после вызова PropSheet:

   mHwnd = (HWND)PropertySheet(&pshdr);
   CenterWindow(mHwnd);
   return mHwnd != NULL;

И это работает, хотя в сильно загруженной системе диалоговое окно мигает из своего начального положения в конечное положение, которое является неоптимальным.

Использование PropSheetProc для изменения структуры DLGTEMPLATE кажется интуитивно понятным. На самом деле, я могу применить другие стили окна. Но DS_CENTER, кажется, не имеет никакого эффекта. Так что я делаю не так? Есть много способов обойти эту разбитость, но почему она вообще сломана?

1 Ответ

1 голос
/ 07 декабря 2011

Перегрузите InitialUpdate () таблицы CPropertySheet и поместите там вызов CenterWindow ().Это происходит до того, как окно будет нарисовано на экране, но после того, как оно будет создано, поэтому оно будет действительным.Там нет ничего сломанного.Диалог должен быть создан, чтобы иметь действительный HWND.В качестве альтернативы, если вы работаете с редактором ресурсов, вы можете установить его свойство по центру, и оно достигнет того же результата.Почему вы перегружаете WinProc для правильной таблицы?Причина, по которой MFC использует карты сообщений, заключалась в том, чтобы исключить необходимость даже касаться WinProc.

Если вы используете raw api win в приложении стиля SDK ::

Обрабатывайте WM_CREATE в WinProc свойствапростынь.Структура LPCREATE в LPARAM будет содержать действительный HWND из вызова create.Просто убедитесь, что вы передаете правильные параметры обратно WndProcDefault (), иначе создание окна завершится неудачей.

...