0

我正在使用以下设置创建无模式属性表:

   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 并在传递给 PropSheetProc 的 hwnd 上调用 CenterWindow 方法:

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 似乎没有效果。那么我做错了什么?有很多方法可以解决这种损坏,但为什么它首先会损坏?

4

1 回答 1

1

重载 CPropertySheet 的 InitialUpdate(),并将 CenterWindow() 调用放在那里。这发生在窗口在屏幕上绘制之前,但在它创建之后,所以它的 hwnd 将是有效的。没有任何损坏。必须创建对话框才能具有有效的 HWND。或者,如果您使用资源编辑器,您可以将其属性设置为居中,并且将获得相同的结果。为什么要为属性表重载 WinProc?MFC 使用消息映射的全部原因是为了消除甚至触摸 WinProc 的需要。

如果您在 SDK 风格的应用程序中使用 raw win api::

在属性表的 WinProc 中处理 WM_CREATE。LPARAM 中的 LPCREATE 结构将包含来自 create 调用的有效 HWND。只需确保将正确的参数传递回 WndProcDefault() 否则窗口创建将失败。

于 2011-12-06T22:44:35.123 回答