我正在使用以下设置创建无模式属性表:
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);
}
但这也不起作用!
最后,我在PropSheet调用之后直接调用了CenterWindow调用:
mHwnd = (HWND)PropertySheet(&pshdr);
CenterWindow(mHwnd);
return mHwnd != NULL;
虽然在一个负载很重的系统上,但是这个DOES有效,但是对话框从其初始位置闪烁到最终位置,这是次优的。
使用PropSheetProc修改DLGTEMPLATE结构似乎很直观。实际上,我可以应用其他窗口样式。但DS_CENTER似乎没有效果。那么我做错了什么?我有很多方法可以解决这个问题,但为什么它首先会被打破?
答案 0 :(得分:1)
重载CPropertySheet的InitialUpdate(),并将CenterWindow()调用放在那里。这是在屏幕上绘制窗口之前发生的,但在创建之后,它的hwnd将是有效的。什么都没有打破。必须创建对话框以具有有效的HWND。或者,如果您使用资源编辑器,则可以将其属性设置为居中,并且它将获得相同的结果。为什么要为属性表重载WinProc? MFC使用消息映射的全部原因是为了消除甚至触摸WinProc的需要。
如果你在SDK风格的应用程序中使用raw win api ::
处理属性表的WinProc中的WM_CREATE。 LPARAM中的LPCREATE结构将包含来自create调用的有效HWND。只需确保将正确的参数传递回WndProcDefault(),否则窗口创建将失败。