在VC中无论调用MFC 中的CFileDialog 还是 WTL 的 CFileDialog 还是 API GetOpenFileName 中都会保留前一次打开对话框。因为每次显示对话框都在不同的位置给人的印象是
很混乱,那么如何才能让对话框居中显示呢。
我从WTL 的 CFileDialog 派生了一个类,然后在OnInitDialog 中SetWindowPos ,在设置之后没有效果。在其他的 消息处理函数WM_SIZE ,等中也没有效果。后来SetHookWindowEx
g_hook = SetWindowsHookEx(WH_CALLWNDPROCRET,CallWndRetProc,NULL,GetCurrentThreadId());
static LRESULT CALLBACK CallWndRetProc( int nCode,
WPARAM wParam,
LPARAM lParam
)
{
CWPRETSTRUCT* p = (CWPRETSTRUCT*)lParam;
if(p && p->message == WM_SHOWWINDOW && p->hwnd == ::GetParent(g_hwnd))
{
CheckWindow(p->hwnd);
}
return CallNextHookEx(g_hook,nCode,wParam,lParam);
}
static void Center(HWND hwnd)
{
ULONG w=GetSystemMetrics(SM_CXSCREEN);
ULONG h =GetSystemMetrics(SM_CYSCREEN);
ULONG left ,top;
CRect rt;
::GetWindowRect(hwnd,&rt);
left = (w-rt.Width())/2;
top =(h-rt.Height())/2;
::SetWindowPos(hwnd,0,left,top,0,0,SWP_NOSIZE|SWP_NOACTIVATE);
}
static int CheckWindow(HWND hwnd)
{
CRect rt;
::GetWindowRect(hwnd,&rt);
if(rt.top == FixedTop(hwnd) && rt.left ==FixedLeft(hwnd))
{
return 1;
}
Center(hwnd);
return 0;
}
static ULONG FixedTop(HWND hwnd)
{
ULONG h =GetSystemMetrics(SM_CYSCREEN);
ULONG top;
CRect rt;
::GetWindowRect(hwnd,&rt);
top =(h-rt.Height())/2;
return top;
}
static ULONG FixedLeft(HWND hwnd)
{
ULONG w=GetSystemMetrics(SM_CXSCREEN);
ULONG left ;
CRect rt;
::GetWindowRect(hwnd,&rt);
left = (w-rt.Width())/2;
return left;
}
结果就OK了,因为显示的窗口的位置是由Windows 来记住的的,是由其父窗口来决定的。
所以我们处理父窗口的位置就OK了。