MFC
微軟基礎(chǔ)類(lèi)庫(kù)(英語(yǔ):Microsoft Foundation Classes,簡(jiǎn)稱(chēng)MFC)是微軟公司提供的一個(gè)類(lèi)庫(kù)(class libraries),以C++類(lèi)的形式封裝了Windows API,并且包含一個(gè)應(yīng)用程序框架,以減少應(yīng)用程序開(kāi)發(fā)人員的工作量。其中包含大量Windows句柄封裝類(lèi)和很多Windows的內(nèi)建控件和組件的封裝類(lèi)。
MFC(MicrosoftFoundationClasses)是微軟基礎(chǔ)類(lèi)庫(kù)的簡(jiǎn)稱(chēng),是微軟公司實(shí)現(xiàn)的一個(gè)c++類(lèi)庫(kù),主要封裝了大部分的windows API函數(shù),vc++是微軟公司開(kāi)發(fā)的c/c++的集成開(kāi)發(fā)環(huán)境,所謂集成開(kāi)發(fā)環(huán)境,就是說(shuō)利用它可以編輯,編譯,調(diào)試,而不是使用多種工具輪換操作,靈活性較大。vc也指它的內(nèi)部編譯器,集成開(kāi)發(fā)環(huán)境必須有一個(gè)編譯器內(nèi)核,例如DevC++其中一個(gè)編譯器內(nèi)核就是gcc。
MFC除了是一個(gè)類(lèi)庫(kù)以外,還是一個(gè)框架,在vc++里新建一個(gè)MFC的工程,開(kāi)發(fā)環(huán)境會(huì)自動(dòng)幫你產(chǎn)生許多文件,同時(shí)它使用了mfcxx.dll。xx是版本,它封裝了mfc內(nèi)核,所以你在你的代碼看不到原本的SDK編程中的消息循環(huán)等等東西,因?yàn)镸FC框架幫你封裝好了,這樣你就可以專(zhuān)心的考慮你程序的邏輯,而不是這些每次編程都要重復(fù)的東西,但是由于是通用框架,沒(méi)有最好的針對(duì)性,當(dāng)然也就喪失了一些靈活性和效率。但是MFC的封裝很淺,所以效率上損失不大。
MFC初學(xué)教程
編寫(xiě)MFC程序,其實(shí)跟編寫(xiě)C++程序一樣,在VS編譯平臺(tái)上新建項(xiàng)目,然后一直默認(rèn)下一步就行,不過(guò)有其他需求則需要根據(jù)實(shí)際情況來(lái)添加。建好一個(gè)項(xiàng)目后,會(huì)出現(xiàn)兩個(gè)界面,一個(gè)是顯示窗口,一個(gè)是編程界面,類(lèi)似LV中的前面板和程序框圖。在界面右邊有個(gè)工具箱,可以根據(jù)需要添加控件。
下面主要編寫(xiě)一個(gè)簡(jiǎn)單的計(jì)算器程序,實(shí)現(xiàn)對(duì)輸入數(shù)的四則運(yùn)算,主要步驟如下:
1、在對(duì)話(huà)框中放置6個(gè)按鈕控件和3個(gè)編輯框控件
具體操作:界面右邊點(diǎn)擊工具箱,根據(jù)具體需要選擇具體控件。
2、將3個(gè)編輯框控件分別添加float型變量m_edit1、m_edit2、m_edit3
具體操作:選中編輯框點(diǎn)右鍵添加變量,將右邊類(lèi)別改為value,變量名分別改為m_edit1、m_edit2、m_edit3。
3、將6個(gè)個(gè)按鈕控件重新命名
具體操作:選中按鈕點(diǎn)擊右鍵屬性,將Caption改為所需要+ - * / 清除 關(guān)閉,具體可根據(jù)需要來(lái)命名。
4、選擇工具箱中Group Box將四則運(yùn)算框住,然后通過(guò)屬性改名字,同時(shí)在上方添加靜態(tài)文本(Static Text)來(lái)編輯命名。
界面主要部分完成,接下來(lái)就是編寫(xiě)代碼,雙擊各個(gè)控件,就可自動(dòng)跳轉(zhuǎn)到程序編寫(xiě)部分,主要代碼如下
?。踙tml] view plain copyvoid CMFC入門(mén)Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知處理程序代碼
UpdateData(true);//從控件獲得數(shù)據(jù)賦給變量
m_edit3 = m_edit1 + m_edit2;
UpdateData(false);//輸出變量的值到控件
}
void CMFC入門(mén)Dlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知處理程序代碼
UpdateData(true);
m_edit3 = m_edit1 - m_edit2;
UpdateData(false);
}
void CMFC入門(mén)Dlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知處理程序代碼
UpdateData(true);
m_edit3 = m_edit1*m_edit2;
UpdateData(false);
}
void CMFC入門(mén)Dlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知處理程序代碼
UpdateData(true);
if (m_edit2 == 0)
{
MessageBox(_T(“除數(shù)不能為0”));
return;
}
m_edit3 = m_edit1 / m_edit2;
UpdateData(false);
}
void CMFC入門(mén)Dlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知處理程序代碼
m_edit1 = 0;
m_edit2 = 0;
m_edit3 = 0;
UpdateData(false);
GotoDlgCtrl((CEdit*)GetDlgItem(IDC_EDIT1));//設(shè)置焦點(diǎn)在第一個(gè)編輯框
}
最后編寫(xiě)完成,運(yùn)行一下,彈出一個(gè)界面如下:
驗(yàn)證一下程序,以加法為例,m_edit1輸入18,m_edit2輸入36,得出結(jié)果如下所示。
mfc編程入門(mén)教程
1.MFC窗口類(lèi)CWnd
在Windows系統(tǒng)里,一個(gè)窗口的屬性分兩個(gè)地方存放:一部分放在“窗口類(lèi)”里頭,如上所述的在注冊(cè)窗口時(shí)指定;另一部分放在Windows Object本身,如:窗口的尺寸,窗口的位置(X,Y軸),窗口的Z軸順序,窗口的狀態(tài)(ACTIVE,MINIMIZED,MAXMIZED,RESTORED…),和其他窗口的關(guān)系(父窗口,子窗口…),窗口是否可以接收鍵盤(pán)或鼠標(biāo)消息,等等。
為了表達(dá)所有這些窗口的共性,MFC設(shè)計(jì)了一個(gè)窗口基類(lèi)CWnd。有一點(diǎn)非常重要,那就是CWnd提供了一個(gè)標(biāo)準(zhǔn)而通用的MFC窗口過(guò)程,MFC下所有的窗口都使用這個(gè)窗口過(guò)程。至于通用的窗口過(guò)程卻能為各個(gè)窗口實(shí)現(xiàn)不同的操作,那就是MFC消息映射機(jī)制的奧秘和作用了。這些,將在后面有關(guān)章節(jié)詳細(xì)論述。
CWnd提供了一系列成員函數(shù),或者是對(duì)Win32相關(guān)函數(shù)的封裝,或者是CWnd新設(shè)計(jì)的一些函數(shù)。這些函數(shù)大致如下。
方法/步驟
?。?)窗口創(chuàng)建函數(shù)
這里主要討論函數(shù)Create和CreateEx。它們封裝了Win32窗口創(chuàng)建函數(shù)::CreateWindowEx。Create的原型如下:
BOOL CWnd::Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd, UINT nID,
CCreateContext* pContext)
Create是一個(gè)虛擬函數(shù),用來(lái)創(chuàng)建子窗口(不能創(chuàng)建桌面窗口和POP UP窗口)。CWnd的基類(lèi)可以覆蓋該函數(shù),例如邊框窗口類(lèi)等覆蓋了該函數(shù)以實(shí)現(xiàn)邊框窗口的創(chuàng)建,視類(lèi)則使用它來(lái)創(chuàng)建視窗口。
Create調(diào)用了成員函數(shù)CreateEx。CWnd::CreateEx的原型如下:
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
CreateEx有11個(gè)參數(shù),它將調(diào)用::CreateWindowEx完成窗口的創(chuàng)建,這11個(gè)參數(shù)對(duì)應(yīng)地傳遞給::CreateWindowEx。參數(shù)指定了窗口擴(kuò)展風(fēng)格、“窗口類(lèi)”、窗口名、窗口大小和位置、父窗口句柄、窗口菜單和窗口創(chuàng)建參數(shù)。
CreateEx的處理流程將在后面4.4.1節(jié)討論窗口過(guò)程時(shí)分析。
窗口創(chuàng)建時(shí)發(fā)送WM_CREATE消息,消息參數(shù)lParam指向一個(gè)CreateStruct結(jié)構(gòu)的變量,該結(jié)構(gòu)有11個(gè)域,其描述見(jiàn)后面4.4.1節(jié)對(duì)窗口過(guò)程的分析,Windows使用和CreateEx參數(shù)一樣的內(nèi)容填充該變量
?。?)窗口銷(xiāo)毀函數(shù)
例如:
DestroyWindow函數(shù) 銷(xiāo)毀窗口
PostNcDestroy( ),銷(xiāo)毀窗口后調(diào)用,虛擬函數(shù)
3)用于設(shè)定、獲取、改變窗口屬性的函數(shù),例如:
SetWindowText(CString tiltle) 設(shè)置窗口標(biāo)題
GetWindowText() 得到窗口標(biāo)題
SetIcon(HICON hIcon, BOOL bBigIcon);設(shè)置窗口像標(biāo)
GetIcon( BOOL bBigIcon ) ;得到窗口像標(biāo)
GetDlgItem( int nID);得到窗口類(lèi)指定ID的控制子窗口
GetDC(); 得到窗口的設(shè)備上下文
SetMenu(CMenu *pMenu); 設(shè)置窗口菜單
GetMenu();得到窗口菜單
…
?。?)用于完成窗口動(dòng)作的函數(shù)
用于更新窗口,滾動(dòng)窗口,等等。一部分成員函數(shù)設(shè)計(jì)成或可重載(Overloaded)函數(shù),或虛擬(Overridden)函數(shù),或MFC消息處理函數(shù)。這些函數(shù)或者實(shí)現(xiàn)了一部分功能,或者僅僅是一個(gè)空函數(shù)。如:
有關(guān)消息發(fā)送的函數(shù):
SendMessage( UINT message,WPARAM wParam = 0, LPARAM lParam = 0 );
給窗口發(fā)送發(fā)送消息,立即調(diào)用方式
PostMessage(( UINT message,WPARAM wParam = 0, LPARAM lParam = 0 );
給窗口發(fā)送消息,放進(jìn)消息隊(duì)列
…
有關(guān)改變窗口狀態(tài)的函數(shù)
MoveWindow( LPCRECT lpRect, BOOL bRepaint = TRUE );
移動(dòng)窗口到指定位置
ShowWindow(BOOL );顯示窗口,使之可見(jiàn)或不可見(jiàn)
…
實(shí)現(xiàn)MFC消息處理機(jī)制的函數(shù):
virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam ); 窗口過(guò)程,虛擬函數(shù)
virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam );處理命令消息
…
消息處理函數(shù):
OnCreate( LPCREATESTRUCT lpCreateStruct );MFC窗口消息處理函數(shù),窗口創(chuàng)建時(shí)由MFC框架調(diào)用
OnClose();MFC窗口消息處理函數(shù),窗口創(chuàng)建時(shí)由MFC框架調(diào)用
…
其他功能的函數(shù)
CWnd的導(dǎo)出類(lèi)是類(lèi)型更具體、功能更完善的窗口類(lèi),它們繼承了CWnd的屬性和方法,并提供了新的成員函數(shù)(消息處理函數(shù)、虛擬函數(shù)、等等)。
常用的窗口類(lèi)及其層次關(guān)系見(jiàn)圖1-1。
2.在MFC下創(chuàng)建一個(gè)窗口對(duì)象
MFC下創(chuàng)建一個(gè)窗口對(duì)象分兩步,首先創(chuàng)建MFC窗口對(duì)象,然后創(chuàng)建對(duì)應(yīng)的Windows窗口。在內(nèi)存使用上,MFC窗口對(duì)象可以在棧或者堆(使用new創(chuàng)建)中創(chuàng)建。具體表述如下:
創(chuàng)建MFC窗口對(duì)象。通過(guò)定義一個(gè)CWnd或其派生類(lèi)的實(shí)例變量或者動(dòng)態(tài)創(chuàng)建一個(gè)MFC窗口的實(shí)例,前者在??臻g創(chuàng)建一個(gè)MFC窗口對(duì)象,后者在堆空間創(chuàng)建一個(gè)MFC窗口對(duì)象。
調(diào)用相應(yīng)的窗口創(chuàng)建函數(shù),創(chuàng)建Windows窗口對(duì)象。
例如:在前面提到的AppWizard產(chǎn)生的源碼中,有CMainFrame(派生于CMDIFrame(SDI)或者CMDIFrameWnd(MDI))類(lèi)。它有兩個(gè)成員變量定義如下:
CToolBar m_wndToolBar;
CStatusBar m_wndStatusBar;
當(dāng)創(chuàng)建CMainFrame類(lèi)對(duì)象時(shí),上面兩個(gè)MFC Object也被構(gòu)造。
CMainFrame還有一個(gè)成員函數(shù)
OnCreate(LPCREATESTRUCT lpCreateStruct),
它的實(shí)現(xiàn)包含如下一段代碼,調(diào)用CToolBar和CStatusBar的成員函數(shù)Create來(lái)創(chuàng)建上述兩個(gè)MFC對(duì)象對(duì)應(yīng)的工具欄HWND窗口和狀態(tài)欄HWND窗口:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
…
if (!m_wndToolBar.Create(this) ||
??!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0(“Failed to create toolbar\n”);
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
??!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0(“Failed to create status bar\n”);
return -1; // fail to create
}
…
}
關(guān)于工具欄、狀態(tài)欄將在后續(xù)有關(guān)章節(jié)作詳細(xì)討論。
在MFC中,還提供了一種動(dòng)態(tài)創(chuàng)建技術(shù)。動(dòng)態(tài)創(chuàng)建的過(guò)程實(shí)際上也如上所述分兩步,只不過(guò)MFC使用這個(gè)技術(shù)是由框架自動(dòng)地完成整個(gè)過(guò)程的。通常框架窗口、文檔框架窗口、視使用了動(dòng)態(tài)創(chuàng)建。介于MFC的結(jié)構(gòu),CFrameWnd和CView及其派生類(lèi)的實(shí)例即使不使用動(dòng)態(tài)創(chuàng)建,也要用new在堆中分配。理由見(jiàn)窗口的銷(xiāo)毀(2.2.5節(jié))。
至于動(dòng)態(tài)創(chuàng)建技術(shù),將在下一章具體討論。
在Windows窗口的創(chuàng)建過(guò)程中,將發(fā)送一些消息,如:
在創(chuàng)建了窗口的非客戶(hù)區(qū)(Nonclient area)之后,發(fā)送消息WM_NCCREATE;
在創(chuàng)建了窗口的客戶(hù)區(qū)(client area)之后,發(fā)送消息WM_CREATE;
窗口的窗口過(guò)程在窗口顯示之前收到這兩個(gè)消息。
如果是子窗口,在發(fā)送了上述兩個(gè)消息之后,還給父窗口發(fā)送WM_PARENATNOTIFY消息。其他類(lèi)或風(fēng)格的窗口可能發(fā)送更多的消息,具體參見(jiàn)SDK開(kāi)發(fā)文檔。
3.MFC窗口的使用
MFC提供了大量的窗口類(lèi),其功能和用途各異。程序員應(yīng)該選擇哪些類(lèi)來(lái)使用,以及怎么使用他們呢?
直接使用MFC提供的窗口類(lèi)或者先從MFC窗口類(lèi)派生一個(gè)新的C++類(lèi)然后使用它,這些在通常情況下都不需要程序員提供窗口注冊(cè)的代碼。是否需要派生新的C++類(lèi),視MFC已有的窗口類(lèi)是否能滿(mǎn)足使用要求而定。派生的C++類(lèi)繼承了基類(lèi)的特性并改變或擴(kuò)展了它的功能,例如增加或者改變對(duì)消息、事件的特殊處理等。
主要使用或繼承以下一些MFC窗口類(lèi)(其層次關(guān)系圖見(jiàn)圖1-1):
框架類(lèi)CFrameWnd,CMdiFrameWnd;
文檔框架CMdiChildWnd;
視圖CView和CView派生的有特殊功能的視圖如:列表CListView,編輯CEditView,樹(shù)形列表CTreeView,支持RTF的CRichEditView,基于對(duì)話(huà)框的視CFormView等等。
對(duì)話(huà)框CDialog。
通常,都要從這些類(lèi)派生應(yīng)用程序的框架窗口和視窗口或者對(duì)話(huà)框。
工具條CToolBar
狀態(tài)條CStatusBar
其他各類(lèi)控制窗口,如列表框CList,編輯框CEdit,組合框CComboBox,按鈕Cbutton等。
通常,直接使用這些類(lèi)。
4.在MFC下窗口的銷(xiāo)毀
窗口對(duì)象使用完畢,應(yīng)該銷(xiāo)毀。在MFC下,一個(gè)窗口對(duì)象的銷(xiāo)毀包括HWND窗口對(duì)象的銷(xiāo)毀和MFC窗口對(duì)象的銷(xiāo)毀。一般情況下,MFC編程框架自動(dòng)地處理了這些。
?。?)對(duì)CFrameWnd和CView的派生類(lèi)
這些窗口的關(guān)閉導(dǎo)致銷(xiāo)毀窗口的函數(shù)DestroyWindow被調(diào)用。銷(xiāo)毀Windows窗口時(shí),MFC框架調(diào)用的最后一個(gè)成員函數(shù)是OnNcDestroy函數(shù),該函數(shù)負(fù)責(zé)Windows清理工作,并在最后調(diào)用虛擬成員函數(shù)PostNcDestroy。CFrameWnd和CView的PostNcDestroy調(diào)用delete this刪除自身這個(gè)MFC窗口對(duì)象。
所以,對(duì)這些窗口,如前所述,應(yīng)在堆(Heap)中分配,而且,不要對(duì)這些對(duì)象使用delete操作。
?。?)對(duì)Windows Control窗口
在它們的析構(gòu)函數(shù)中,將調(diào)用DestroyWidnow來(lái)銷(xiāo)毀窗口。如果在棧中分配這樣的窗口對(duì)象,則在超出作用范圍的時(shí)候,隨著析構(gòu)函數(shù)的調(diào)用,MFC窗口對(duì)象和它的Windows window對(duì)象都被銷(xiāo)毀。如果在堆(Heap)中分配,則顯式調(diào)用delete操作符,導(dǎo)致析構(gòu)函數(shù)的調(diào)用和窗口的銷(xiāo)毀。
所以,這種類(lèi)型的窗口應(yīng)盡可能在棧中分配,避免用額外的代碼來(lái)銷(xiāo)毀窗口。如前所述的CMainFrame的成員變量m_wndStatusBar和m_wndToolBar就是這樣的例子。
?。?)對(duì)于程序員直接從CWnd派生的窗口
程序員可以在派生類(lèi)中實(shí)現(xiàn)上述兩種機(jī)制之一,然后,在相應(yīng)的規(guī)范下使用。
評(píng)論