MFC9.0 更改窗口的初始化大小位置初探
MFC9.0幾乎將其類庫擴(kuò)充了一倍,無疑是MFC史上的一次大的升級(jí)。在引入CMFCVirtualManager等類方便我們開發(fā)高水準(zhǔn)UI的同時(shí)也給習(xí)慣老版本MFC的用戶帶來了困難。
以前使用VC6.0的用戶在初次使用vs2008或2010時(shí)對(duì)于改變窗口的初始化大小很是費(fèi)解。
在VC6.0下,這種操作很容易實(shí)現(xiàn)
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
//想要的窗口大小
cs.cx=300;
cs.cy=300;
cs.x=0;
cs.Y=0;
return TRUE;
}
但如果在MFC9.0下,你會(huì)發(fā)現(xiàn)窗口的大小根本沒有改變。找不到原因,于是打算使用另一種途經(jīng)使用CWnd::SetWindowPos方法,在窗口創(chuàng)建之后緊接著改變其大小。
代碼如下:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
.....//MFC自己生產(chǎn)的代碼
SetWindowPos(CWnd::FromHandle(HWND_NOTOPMOST),200,200,300,300,SWP_FRAME CHANGED|SWP_SHOWWINDOW);
return 0;
}
這時(shí)你會(huì)發(fā)現(xiàn)窗口的大小先變成自定義的大小,緊接著又改變成了系統(tǒng)默認(rèn)的大小,如果變化太快看不清,如下代碼會(huì)讓你清楚的發(fā)現(xiàn)這一點(diǎn)。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
.....//MFC自己生產(chǎn)的代碼
SetWindowPos(CWnd::FromHandle(HWND_NOTOPMOST),200,200,300,300,SWP_FRAME CHANGED|SWP_SHOWWINDOW);
Sleep(3000);
return 0;
}
這是怎么回事呢????
回想使用windows API開發(fā)應(yīng)用程序中窗口的創(chuàng)建過程,窗口的創(chuàng)建簡(jiǎn)單分三步操作,創(chuàng)建窗口,顯示窗口,更新窗口,其中顯示更新窗口可以多次調(diào)用。在MFC中創(chuàng)建窗口的工作主要由CMainFrame::PreCreateWindow和CMainFrame::OnCreate來完成,同時(shí)CMainFrame::OnCreate完成后也會(huì)顯示窗口。會(huì)不會(huì)在調(diào)用完成CMainFrame::OnCreate之后在調(diào)用下個(gè)顯示窗口之前對(duì)窗口大小進(jìn)行改變的呢?的卻如此。下面就是調(diào)用的代碼。
BOOL CNewApp::InitInstance()
{
// 如果一個(gè)運(yùn)行在 Windows XP 上的應(yīng)用程序清單指定要
// 使用 ComCtl32.dll 版本 6 或更高版本來啟用可視化方式,
//則需要 InitCommonControlsEx()。否則,將無法創(chuàng)建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 將它設(shè)置為包括所有要在應(yīng)用程序中使用的
// 公共控件類。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinAppEx::InitInstance();
// 初始化 OLE 庫
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
EnableTaskbarInteraction(FALSE);
// 使用 RichEdit 控件需要 AfxInitRichEdit2()
// AfxInitRichEdit2();
// 標(biāo)準(zhǔn)初始化
// 如果未使用這些功能并希望減小
// 最終可執(zhí)行文件的大小,則應(yīng)移除下列
// 不需要的特定初始化例程
// 更改用于存儲(chǔ)設(shè)置的注冊(cè)表項(xiàng)
// TODO: 應(yīng)適當(dāng)修改該字符串,
// 例如修改為公司或組織名
SetRegistryKey(_T("應(yīng)用程序向?qū)傻谋镜貞?yīng)用程序"));
LoadStdProfileSettings(4); // 加載標(biāo)準(zhǔn) INI 文件選項(xiàng)(包括 MRU)
InitContextMenuManager();
InitKeyboardManager();
InitTooltipManager();
CMFCToolTipInfo ttParams;
ttParams.m_bVislManagerTheme = TRUE;
theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
// 注冊(cè)應(yīng)用程序的文檔模板。文檔模板
// 將用作文檔、框架窗口和視圖之間的連接
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CNewDoc),
RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CNewView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// 分析標(biāo)準(zhǔn) shell 命令、DDE、打開文件操作的命令行
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// 調(diào)度在命令行中指定的命令。如果
// 用 /RegServer、/Register、/Unregserver 或 /Unregister 啟動(dòng)應(yīng)用程序,則返回 FALSE。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// 唯一的一個(gè)窗口已初始化,因此顯示它并對(duì)其進(jìn)行更新
//m_pMainWnd->SetWindowPos(CWnd::FromHandle(HWND_NOTOPMOST),200,200,300,300,SWP_FRAMECHANGED);
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// 僅當(dāng)具有后綴時(shí)才調(diào)用 DragAcceptFiles
// 在 SDI 應(yīng)用程序中,這應(yīng)在 ProcessShellCommand 之后發(fā)生
return TRUE;
}
其實(shí)先前的MFC版本也有兩個(gè)函數(shù)的調(diào)用,為什么結(jié)果卻有所不同?這要了解MFC9.0中,窗口到顯示的整個(gè)過程。首先調(diào)用PreCreateWindow和 OnCreateWindow按cs中設(shè)定的值創(chuàng)建窗口(這時(shí)的窗口并沒有顯示出來),再調(diào)用
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
之前會(huì)從注冊(cè)表中讀取包括窗口上一次關(guān)閉時(shí)的大小和位置等其他信息(第一次創(chuàng)建時(shí)會(huì)把系統(tǒng)默認(rèn)的信息寫到注冊(cè)表),并根據(jù)這些信息改變窗口。這就是為什么在PreCreateWindow中更改窗口的大小和位置不起作用的原因。
要想更改可以在顯示窗口之前調(diào)用SetWindowPos,即:
SetWindowPos(CWnd::FromHandle(HWND_NOTOPMOST),200,200,300,300,SWP_FRAME CHANGED|SWP_SHOWWINDOW);
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
這樣窗口的大小和位置就可以根據(jù)需要隨意顯示了。
聯(lián)系客服