找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3521|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

MFC相關(guān)理解

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:60266 發(fā)表于 2014-8-18 01:10 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
                        為了進(jìn)行繪圖操作,必須獲得一個(gè)設(shè)備描述表(或設(shè)備上下文)DC,當(dāng)構(gòu)造了一個(gè)GDI對(duì)象后,該對(duì)象并不會(huì)立即生效,必須選入設(shè)備描述表DC,它才會(huì)在以后的繪制操作中生效;利用SelectObject函數(shù)可以實(shí)現(xiàn)把GDI對(duì)象選入設(shè)備描述表DC中,并且該函數(shù)會(huì)返回指向先前被選對(duì)象的指針,這個(gè)指針主要是為了在完成當(dāng)前的繪制操作后,還原設(shè)備描述表用的。一般情況下,在完成繪圖操作后,要利SelectObject函數(shù)把先前的GDI對(duì)象選入設(shè)備描述表,以便使其恢復(fù)到先前的狀態(tài);
GDI  圖形設(shè)備接口(GDI:Graphics DeviceInterface)是Windows的子系統(tǒng),它負(fù)責(zé)在視訊顯示器和打印機(jī)上顯示圖形。正如您所認(rèn)為的那樣,GDI是Windows非常重要的部分。不只您為Windows編寫(xiě)的應(yīng)用系統(tǒng)在顯示視覺(jué)信息時(shí)使用GDI,就連Windows本身也使用GDI來(lái)顯示使用者接口對(duì)象,諸如菜單、滾動(dòng)條、圖標(biāo)和鼠標(biāo)光標(biāo)。
GDI是C++中常用的一種圖形圖像工具,VB、Delphi等語(yǔ)言也移植了GDI ,.net的諸多語(yǔ)言甚至完全采用GDI作為繪制其界面。在Windows系統(tǒng)下,幾乎所有的API都是直接針對(duì)C語(yǔ)言的,除C/C++可直接使用這些API外,其它各種語(yǔ)言都必須移植這些API方法,而唯獨(dú)GDI,微軟提供的Gdiplus頭文件,從類(lèi)型定義到方法接口,都是針對(duì)C++寫(xiě)的,這就使得C語(yǔ)言沒(méi)法使用這些面向?qū)ο蟮姆椒ǎ词故荊DI提供的原始API,如果不重新定義其參數(shù)中眾多的數(shù)據(jù)類(lèi)型,C語(yǔ)言也是沒(méi)法使用的。
也許是因?yàn)镃語(yǔ)言不適合編寫(xiě)Windows界面應(yīng)用程序,所以至今沒(méi)有發(fā)現(xiàn)GDI的C版本(可能有,但沒(méi)發(fā)現(xiàn))。GDI沒(méi)C版本的一個(gè)可能的原因是:C版本中的眾多的重載函數(shù),缺省參數(shù),用C來(lái)寫(xiě)卻是頭都大了,不知道用什么函數(shù)名才好(考慮GDI使用了這些年,新的函數(shù)名不應(yīng)與原函數(shù)名偏離太遠(yuǎn))。

void CDrawView::OnLButtonUp(UINT nFlags,  CPoint point){    CPen pen(PS_SOLID, 1,  RGB(255,0,0));    CClientDC  dc(this);    CPen  *pOldPen  = dc.SelectObject(&pen);    dc.MoveTo(m_ptOrigin);   dc.LineTo(point);   dc.SelectObject(pOldPen);   CView::OnLButtonUp(nFlags, point);}
void CDrawView::OnLButtonUp( UINT nFlags, CPoint point){    HDC hdc;   hdc = ::GetDC(m_hWnd);//獲取該窗口的設(shè)備描述表(上下文)   MoveToEx(hdc, m_ptOrigin.x,  m_ptOrigin.y, NULL);//移動(dòng)到線條的起點(diǎn)  LineTo(hdc, point.x, point.y); //通過(guò)hdc畫(huà)線 ::ReleaseDC(m_hWnd, hdc);//用后一定要釋放,因?yàn)镚etDC里面是申請(qǐng)了資源的}
在MFC中,所有的控件類(lèi)都是由CWnd類(lèi)派生的,因此控件實(shí)際上也是窗口;實(shí)際上,控件通常是作為對(duì)話框的子窗口而創(chuàng)建的。對(duì)話框的種類(lèi):對(duì)話框可分為:1.模態(tài)(Modal)對(duì)話框 2.非模態(tài)對(duì)話框(Modeless)模態(tài)(Modal)對(duì)話框:模態(tài)對(duì)話框是指當(dāng)其顯示時(shí),程序會(huì)暫停執(zhí)行,直到關(guān)閉這個(gè)模態(tài)對(duì)話框后,才能繼續(xù)執(zhí)行程序中其他人;模態(tài)對(duì)話框壟斷了用戶(hù)的輸入,當(dāng)一個(gè)模態(tài)對(duì)話框打開(kāi)時(shí),用戶(hù)只能與該對(duì)話框進(jìn)行交互,而其他用戶(hù)界面對(duì)象接收不到輸入信息;我們平時(shí)所遇到的大部分對(duì)話框都是模態(tài)對(duì)話框;非模態(tài)對(duì)話框(Modeless):當(dāng)非模態(tài)對(duì)話框(Modeless)顯示時(shí),允許轉(zhuǎn)而執(zhí)行程序中其他的任務(wù),而不用關(guān)閉這個(gè)對(duì)話框。典型的例子是Windows提供的記事本程序中的“查找”對(duì)話框,該對(duì)話框不會(huì)壟斷用戶(hù)的輸入,打開(kāi)“查找”對(duì)話框后,仍可以與其他用戶(hù)界面對(duì)象進(jìn)行交互,用戶(hù)可以一邊查找,一邊修改文章,這樣就大大方便了使用。
MFC為我們提供一個(gè)設(shè)備描述表的封裝類(lèi)CDC,該類(lèi)封裝了所有與繪圖相關(guān)的操作;該類(lèi)提供了一個(gè)數(shù)據(jù)成員m_hDC,用來(lái)保存與CDC類(lèi)相關(guān)的DC句柄。CDC是MFC的DC【設(shè)備上下文/設(shè)備描述表】的一個(gè)類(lèi);CDC中所有MFC的DC的基類(lèi).常用的CClientDC dc(this);就是CDC的子類(lèi)(或稱(chēng)派生類(lèi)).CDC等設(shè)備上下分類(lèi),都含有一個(gè)類(lèi)的成員變量:m_nHdc;即HDC類(lèi)型的句柄.記住下面的一句話,會(huì)有助于你的理解:MFC的類(lèi),是在用window API語(yǔ)句開(kāi)發(fā)出來(lái)的有一定功能的小程序.(也可稱(chēng)為類(lèi)).使用它的默認(rèn)方法,就是,記住它的名字與參數(shù)(可以用筆記,代替腦記).DC(設(shè)備上下文):設(shè)備上下文是一種包含有關(guān)某個(gè)設(shè)備(如顯示器或打印機(jī))的繪制屬性信息的 Windows數(shù)據(jù)結(jié)構(gòu)。所有繪制調(diào)用都通過(guò)設(shè)備上下文對(duì)象進(jìn)行,這些對(duì)象封裝了用于繪制線條、形狀和文本的 Windows API。設(shè)備上下文允許在Windows 中進(jìn)行與設(shè)備無(wú)關(guān)的繪制。設(shè)備上下文可用于繪制到屏幕、打印機(jī)或者圖元文件。

設(shè)備上下文是一種包含有關(guān)某個(gè)設(shè)備(如顯示器或打印機(jī))的繪制屬性信息的Windows 數(shù)據(jù)結(jié)構(gòu)。所有繪制調(diào)用都通過(guò)設(shè)備上下文對(duì)象進(jìn)行,這些對(duì)象封裝了用于繪制線條、形狀和文本的Windows API。設(shè)備上下文允許在 Windows 中進(jìn)行與設(shè)備無(wú)關(guān)的繪制。設(shè)備上下文可用于繪制到屏幕、打印機(jī)或者圖元文件。
CPaintDC 對(duì)象將 Windows 的常見(jiàn)固定用語(yǔ)進(jìn)行封裝,調(diào)用 BeginPaint 函數(shù),然后在設(shè)備上下文中繪制,最后調(diào)用EndPaint 函數(shù)。CPaintDC 構(gòu)造函數(shù)為您調(diào)用BeginPaint,析構(gòu)函數(shù)則調(diào)用EndPaint。該簡(jiǎn)化過(guò)程將創(chuàng)建 CDC 對(duì)象、繪制和銷(xiāo)毀 CDC 對(duì)象。在框架中,甚至連這個(gè)過(guò)程的大部分也是自動(dòng)的。具體說(shuō)來(lái),框架給OnDraw 函數(shù)傳遞(通過(guò) OnPrepareDC)準(zhǔn)備好的CPaintDC,您只需繪制到 CPaintDC 中。根據(jù)調(diào)用 OnDraw 函數(shù)的返回,CPaintDC 被框架銷(xiāo)毀并且將基礎(chǔ)設(shè)備上下文釋放給Windows。
CClientDC對(duì)象封裝對(duì)一個(gè)只表示窗口工作區(qū)的設(shè)備上下文的處理。CClientDC 構(gòu)造函數(shù)調(diào)用GetDC 函數(shù),析構(gòu)函數(shù)調(diào)用 ReleaseDC函數(shù)。CWindowDC 對(duì)象封裝表示整個(gè)窗口(包括其框架)的設(shè)備上下文。
CMetaFileDC 對(duì)象將繪制封裝到 Windows 圖元文件中。與傳遞給OnDraw 的 CPaintDC 相反,在這種情況下您必須自己調(diào)用 OnPrepareDC。
設(shè)備上下文(Device Context)DC
DC實(shí)際上是GDI內(nèi)部保存的數(shù)據(jù)結(jié)構(gòu)。
DC與特定的顯示設(shè)備(如顯示器或打印機(jī))相關(guān)。
對(duì)于顯示器,DC總是與顯示器上的特定視窗相關(guān)。
DC中的有些值是圖形「屬性」,這些屬性定義了GDI繪圖函數(shù)工作的細(xì)節(jié)。
例如,對(duì)於TextOut,DC的屬性確定了文字的顏色、文字的背景色、x坐標(biāo)和y坐標(biāo)映射到視窗的顯示區(qū)域的方式,以及顯示文字時(shí)Windows使用的字體。
MSDN的解釋:一個(gè)DC是一個(gè)結(jié)構(gòu),它定義了一系列圖形對(duì)象的集合以及它們相關(guān)的屬性,以及影響輸出效果的一些圖形模式。這些圖形對(duì)象包括一個(gè)畫(huà)線的筆,一個(gè)填充和painting的畫(huà)刷,一個(gè)用來(lái)向屏幕拷貝的位圖,一個(gè)定義了一系列顏色集合的調(diào)色板,一個(gè)用來(lái)剪裁等操作的區(qū)域,一個(gè)做painting和drawing操作的路徑。
一個(gè)應(yīng)用程序從不直接地訪問(wèn)(access)dc,常見(jiàn)的取得dc的方式有以下幾種:
SDK's way:
1. BeginPaint
case WM_PAINT: HDC hdc = BeginPaint(hwnd, &ps);EndPaint(hwnd, &ps);
MSDN的解釋: BeginPaint函數(shù)自動(dòng)地設(shè)置dc的剪裁區(qū)域,這個(gè)剪裁區(qū)域,剪裁的是由InvalidateRect或 InvalidateRgn 函數(shù)觸發(fā)的窗口無(wú)效區(qū)域,或者是系統(tǒng)給出的無(wú)效區(qū)域,當(dāng)窗口被sizing,moving, creating, scrolling, or any other operation that affectsthe client area.
一個(gè)應(yīng)用程序從不調(diào)用BeginPaint,除了在收到一個(gè)WM_PAINT消息的時(shí)候;每一BeginPaint調(diào)用之后,需要調(diào)用EndPaint函數(shù)。
2.GetXXXDC
GetDC取得與窗口客戶(hù)區(qū)相關(guān)的dc,GetWindowDC取得與整個(gè)窗口(包括客戶(hù)區(qū)和非客戶(hù)區(qū))相關(guān)的dc。
還有一類(lèi)重要的dc,內(nèi)存DC,是一個(gè)虛擬的內(nèi)存設(shè)備上下文,我們對(duì)它進(jìn)行繪圖等操作,不會(huì)顯示在屏幕或打印機(jī)上,而我們可以在它完成之后,拷貝到屏幕上或打印機(jī)上來(lái)輸出,這樣我們可以避免因?yàn)椴僮鞫o屏幕帶來(lái)的閃爍,對(duì)于打印機(jī)而言,打印只能是從上往下打,而我們?cè)贛EMDC中,可以隨意進(jìn)行操作,這樣可以輸出直接在打印機(jī)上輸出所達(dá)不到的效果.
在窗口上貼圖一般總是要用到內(nèi)存DC,將所有的繪制工作先繪制在內(nèi)存DC上,然活一次性拷貝到屏幕DC上,就是這樣了。
這里是使用mfc進(jìn)行的說(shuō)明,對(duì)hdc進(jìn)行了封裝,但是道理是一樣的。
1.創(chuàng)建內(nèi)存DC
CDC m_MenDC; //聲明內(nèi)存DC
CDC m_MenDC2; //聲明內(nèi)存DC
CBitmap m_Bitmap1; //聲明一個(gè)位圖
m_MenDC.CreateCompatibleDC(GetDC());//創(chuàng)建內(nèi)存DC
m_MenDCMap.CreateCompatibleDC(GetDC());//創(chuàng)建內(nèi)存DC
m_Bitmap1.CreateCompatibleBitmap(GetDC(),1024,768);//創(chuàng)建一個(gè)兼容位圖,這是一個(gè)空的位圖,我們可以把它想象成一個(gè)屏幕,可以在上面畫(huà)線,輸出文字等,自己制作一個(gè)簡(jiǎn)單的位圖。
m_hbmpBK =(HBITMAP)::LoadImage(AfxGetInstanceHandle(),path+"Bk4.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
//我們也可以從硬盤(pán)導(dǎo)入一張位圖。
2,為內(nèi)存DC選入一張位圖,或兼容位圖。
m_MenDC.SelectObject(m_hbmpBK);
m_MenDC2.SelectObject(m_Bitmap1);
注意,想要在內(nèi)存dc上作圖,必須先為它選入一張位圖,或兼容位圖。想想前面,不管BeginPaint還是getDC都有一個(gè)相關(guān)的區(qū)域。這里的位圖就是相關(guān)區(qū)域。
3.接著我們就可以像在窗口上作圖一樣,使用gdi函數(shù)(drawline,textout...)在內(nèi)存dc上作圖了。同時(shí)也可以從一個(gè)內(nèi)存dc拷貝位圖到另一個(gè)內(nèi)存dc。
m_MenDC2.BitBlt(0,0,1024,768,&m_MenDC,0,0,SRCCOPY);
4,繪制結(jié)果的顯示,將這些東西拷到屏幕DC(getdc取得的dc)上
// 所謂的雙緩沖就是把所有的繪制工作都做在一個(gè)內(nèi)存DC上。
// 最后一次拷到屏幕DC上,只能有一次
dc.BitBlt(0,0,1024,768,&m_MenDC2,0,0,SRCCOPY);//這里的dc是通過(guò)getdc取得的屏幕或者某個(gè)窗口的dc。
這里所強(qiáng)調(diào)的“一次”;是不要連續(xù)將幾個(gè)內(nèi)存DC的內(nèi)容都拷到屏幕DC上,這樣沒(méi)有起到雙緩沖的效果。如果你搞了很多個(gè)內(nèi)存DC,想把這些東西都顯示出來(lái),那你應(yīng)該先把這多個(gè)內(nèi)存DC的內(nèi)容同時(shí)拷到另外一個(gè)內(nèi)存DC上,再把這個(gè)內(nèi)存DC的內(nèi)容拷到屏幕DC上。

CPaintDC dc(this);MFC的CPaintDC類(lèi)是從MFC的CDC類(lèi)派生的,CDC類(lèi)封裝了Windows設(shè)備環(huán)境,以及包含了繪制到屏幕、打印機(jī)和其他設(shè)備的幾十個(gè)成員函數(shù)
在MFC程序中,我們并不經(jīng)常直接調(diào)用Windows API,而是從MFC類(lèi)創(chuàng)建對(duì)象并調(diào)用屬于這些對(duì)象的成員函數(shù).也就是說(shuō)MFC封裝了Windows API 你說(shuō)你喜歡C++而MFC換一種說(shuō)法就是一個(gè)用C++寫(xiě)的一個(gè)函數(shù)庫(kù) 然后你來(lái)調(diào)用 只不過(guò)這個(gè)類(lèi)不是你寫(xiě)的
           MFC提供數(shù)百個(gè)類(lèi),最重要的、也是編寫(xiě)任何VC++應(yīng)用程序都必不可少的兩個(gè)類(lèi)CWinApp和CFrameWnd,這兩個(gè)類(lèi)是編寫(xiě)復(fù)雜龐大應(yīng)用程序的基石。
1>封裝特性:構(gòu)成MFC框架的是MFC類(lèi)庫(kù)而MFC類(lèi)庫(kù)又是C++的一個(gè)類(lèi)庫(kù)。這些類(lèi)封裝WIN32應(yīng)用程序編程接口,OLE(Object Link Embed 對(duì)象鏈接嵌入)特性,ODBC和DAO數(shù)據(jù)訪問(wèn)的功能。
2>繼承特性:MFC抽象出了眾多類(lèi)的共同特性,并設(shè)計(jì)出一些基類(lèi)作為實(shí)現(xiàn)其他類(lèi)的基礎(chǔ),這些類(lèi)中最重要的類(lèi)是CObject類(lèi)和CCmdTarget類(lèi),程序員可以從適當(dāng)?shù)腗FC類(lèi)中派生出自己的類(lèi),實(shí)現(xiàn)特定的功能達(dá)到編程的目的。
3>虛擬和消息映射:MFC是以C++為基礎(chǔ),當(dāng)然支持虛函數(shù),但作為一個(gè)編程框架必須要解決的是效率問(wèn)題:如果MFC僅僅通過(guò)虛函數(shù)來(lái)支持動(dòng)態(tài)約束必然會(huì)產(chǎn)生大量的虛函數(shù)表這樣編程框架過(guò)于臃腫而且消耗更多的內(nèi)存。但是MFC建立了消息映射機(jī)制這樣降低了內(nèi)存的使用卻大大提高了效率
消息映射是一個(gè)將消息和成員函數(shù)相互關(guān)聯(lián)的表,當(dāng)應(yīng)用程序的框架窗口接收到一個(gè)消息時(shí),MFC將搜索該窗口的消息映射,如果存在一個(gè)處理消息的處理程序,那么就調(diào)用該處理程序.
它通過(guò)宏來(lái)實(shí)現(xiàn)消息到成員函數(shù)的映射,而且這些函數(shù)不必是虛擬的成員函數(shù),這樣不需要為消息映射函數(shù)生成一個(gè)很大的虛擬函數(shù)表(V表),節(jié)省內(nèi)存。
MFC消息映射機(jī)制:
將消息與消息處理函數(shù)聯(lián)系起來(lái),形成一一對(duì)應(yīng)的機(jī)制。
消息映射宏
聲明: DECLARE_MESSAGE_MAP
定義:
        BEGIN_MESSAGE_MAP
   ON_COMMAND
   ON_CONTROL
   ON_MESSAGE
       END_MESSAGE_MAP
MFC主要組成部分:類(lèi)、宏和全局函數(shù)。
類(lèi)是MFC中最主要的內(nèi)容。MFC類(lèi)是以層次結(jié)構(gòu)方式組織起來(lái)的。MFC中的類(lèi)分成兩部分,除了一些輔助類(lèi),大多數(shù)的MFC類(lèi)是直接或間接從根類(lèi)CObject派生而來(lái)。
MFC宏主要功能:消息映射、運(yùn)行時(shí)對(duì)象類(lèi)型服務(wù)、診斷服務(wù)、異常處理。
MFC約定:全局函數(shù)以“Afx”為前綴,全局變量以“afx”為前綴
MFC類(lèi)的層次關(guān)系
CObject項(xiàng)目類(lèi))->CCmdTarget(消息響應(yīng)類(lèi))->
{
CWinThread(線程類(lèi))->CWinApp(Window應(yīng)用程序類(lèi))
CDocument(文檔類(lèi))
CWnd(窗體類(lèi))->[
              CFrameWnd(框架類(lèi))
              CView(視圖類(lèi))
              ]
}

CObject類(lèi)由于MFC中大部分類(lèi)是從CObject類(lèi)繼承而來(lái)的,CObject類(lèi)描述了幾乎所有的MFC類(lèi)的一些公共特性,CObject類(lèi)為程序員提供了對(duì)象診斷、運(yùn)行時(shí)類(lèi)型識(shí)別和序列化等功能。
CCmdTarget類(lèi)由CObject類(lèi)直接派生而來(lái),它負(fù)責(zé)將消息發(fā)送到能夠響應(yīng)這些消息的對(duì)象。它是所有能進(jìn)行消息映射的MFC類(lèi)的基類(lèi)。
CWinApp類(lèi)在任何MFC應(yīng)用程序中有且僅有一個(gè)CWinApp派生類(lèi)的對(duì)象,它代表了程序中運(yùn)行的主線程,也代表了應(yīng)用程序本身。 CWinApp類(lèi)取代了WinMain()主函數(shù)在SDK應(yīng)用程序中的地位。傳統(tǒng)SDK應(yīng)用程序WinMain()函數(shù)完成的工作。現(xiàn)在由類(lèi)CWinApp的InitApplication(),InitInstance()和Run()三個(gè)成員函數(shù)承擔(dān)。
CWnd類(lèi)由CCmdTarget類(lèi)直接派生而來(lái),該類(lèi)及其派生類(lèi)的實(shí)例是一個(gè)窗口。CWnd類(lèi)代表了MFC中最基本的GUI對(duì)象,它是一個(gè)功能最完善、成員函數(shù)最多的MFC類(lèi)。
CFrameWnd類(lèi)是CWnd類(lèi)的派生類(lèi),主要用來(lái)掌管一個(gè)窗口,它取代了SDK應(yīng)用程序中窗口函數(shù)WndProc()的地位。CFrameWnd類(lèi)的對(duì)象是一個(gè)框架窗口,包括邊框、標(biāo)題欄、菜單、最大化按鈕、最小化按鈕和一個(gè)激活的視圖。
CDocument類(lèi)在應(yīng)用程序中作為用戶(hù)文檔類(lèi)的基類(lèi),它代表了用戶(hù)存儲(chǔ)或打開(kāi)的一個(gè)文件。
CView類(lèi)是MFC中一個(gè)很基本的類(lèi),它作為其它MFC視圖類(lèi)和用戶(hù)視圖派生類(lèi)的基類(lèi)。
從API編程到MFC編程的過(guò)渡:
WinMain()
{  初始化WNDCLASS
    注冊(cè)窗體結(jié)構(gòu)
    創(chuàng)建窗口           ->>>>>>>>應(yīng)用程序類(lèi)CWinApp
    顯示窗口
    消息循環(huán)
}

WndProc()
{ switch(…)            
           ->>>>>>>>>框架窗口類(lèi)CFrameWnd
}

MFC Object和Windows Object的對(duì)應(yīng)關(guān)系:
描述                 Windows句柄       MFC Object
窗口                  HWND                    CWnd
設(shè)備上下文        HDC                      CDC
菜單                   HMENU                CMenu
筆                       HPEN                   CPen
刷子                   HBRUSH              CBrush
字體                   HFONT                 CFont
位圖                    HBITMAP            CBitmap
套接字                SOCKET              CSocket

三、手工創(chuàng)建一個(gè)MFC應(yīng)用程序:
注意:創(chuàng)建MFC程序,要?jiǎng)?chuàng)建一個(gè)Win32空項(xiàng)目,并要選擇項(xiàng)目屬性中的”在共享DLL文件中使用MFC,然后新建我們的文件
例子:在”hello.h”頭文件中添寫(xiě)如下代碼:
class CMyApp:public CWinApp
{
public:
virtual BOOL InitInstance();//虛函數(shù)
};
class CMainWindow:public CFrameWnd
{
public:
CMainWindow();
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP();//聲明消息映射
};
在”hello.cpp”源文件中添寫(xiě)如下代碼:
#include
#include “hello.h"
CMyApp myApp;
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMainWindow;

      m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()       //消息映射
CMainWindow::CMainWindow() //構(gòu)造函數(shù)初始化
{
    Create(NULL,“我的第一個(gè)MFC應(yīng)用程序”);//創(chuàng)建窗體
}
void CMainWindow::OnPaint()
{  CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
  dc.DrawText("Hello MFC",-1,&rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
}
CWinApp是應(yīng)用程序類(lèi),在MFC應(yīng)用程序中必須從這個(gè)類(lèi)派生出一個(gè)類(lèi),該派生類(lèi)是MFC應(yīng)用程序的入口
必須定義這個(gè)派生類(lèi)的對(duì)象,并且只能有一個(gè)這個(gè)對(duì)象代表整個(gè)應(yīng)用程序。
成員函數(shù):InitInstance()
功能:初始化應(yīng)用程序?qū)嵗痛翱趯?shí)例,
虛函數(shù)CWinApp::InitInstance必須在派生類(lèi)中重寫(xiě)。在InitInstance函數(shù)中,編寫(xiě)初始化代碼,如:
創(chuàng)建一個(gè)窗口
顯示一個(gè)窗口
CFrameWnd類(lèi)
作用:為應(yīng)用程序提供一個(gè)窗口,同時(shí)實(shí)現(xiàn)消息處理功能。
成員函數(shù): Create()
功能:創(chuàng)建窗體,將之賦于CFrameWnd對(duì)象上。
BOOL Create(窗口類(lèi)型, 窗口標(biāo)題,顯示風(fēng)格,顯示區(qū)域,符窗口句柄,菜單,擴(kuò)展顯示風(fēng)格,上下文對(duì)象)共有8個(gè)參數(shù),前兩個(gè)必須給出,后6個(gè)可以默認(rèn)。
MFC應(yīng)用程序的核心就是基于CWinApp類(lèi)的應(yīng)用程序?qū)ο?CWinApp提供了消息循環(huán)來(lái)檢索消息并將消息調(diào)度給應(yīng)用程序的窗口.我們?cè)诰帉?xiě)MFC應(yīng)用程序時(shí),要包含afxwin.h,
一個(gè)MFC應(yīng)用程序可以有且僅有一個(gè)應(yīng)用程序?qū)ο?對(duì)象必須聲明為在全局范圍內(nèi)有效(也就是全局對(duì)象),以便它在程序開(kāi)始時(shí)即在內(nèi)存中被實(shí)例化
我們的Hello MFC的應(yīng)用程序類(lèi)被命名為CMyApp,它在hello.cpp中用如下語(yǔ)句進(jìn)行了實(shí)例化:
CMyApp myApp;
CMyApp的類(lèi)聲明在hello.h中代碼如下:
class CMyApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
CMyApp沒(méi)有聲明任何的數(shù)據(jù)成員,只是重寫(xiě)了一個(gè)從CWinApp類(lèi)中繼承來(lái)的函數(shù),在應(yīng)用程序的生存期內(nèi)InitInstance的調(diào)用比較早,是在應(yīng)用程序開(kāi)始運(yùn)行以后而窗口創(chuàng)建之前,除非InitIstance創(chuàng)建一個(gè)窗口,否則應(yīng)用程序是不會(huì)有窗口,這正是為什么即使最小的MFC應(yīng)用程序也必須從CWinApp派生出一個(gè)類(lèi)并重寫(xiě)CWinApp::InitIstance的原因
InitInstance函數(shù):CWinApp::InitInstance是一個(gè)虛函數(shù),其默認(rèn)操作僅包含一條語(yǔ)句:return TRUE;
InitInstance是用來(lái)執(zhí)行程序每次開(kāi)始時(shí)都需要進(jìn)行的初始化工作最好的地方
在hello.cpp中,CMyApp的InitInstance通過(guò)實(shí)例化hello的CMainWindow類(lèi)來(lái)創(chuàng)建hello窗口,語(yǔ)句:
m_pMainWnd = new CMainWindow;

構(gòu)造了一個(gè)CMainWindow對(duì)象指針,并將其地址復(fù)制到了應(yīng)用程序?qū)ο蟮膍_pMainWnd數(shù)據(jù)成員中,窗口創(chuàng)建以后,InitInstance就會(huì)通過(guò)CMainWindow指針調(diào)用ShowWindow和UpdateWindow函數(shù)顯示它:

m_pMainWnd->ShowWindow(m_nCmdShow);

m_pMainWnd->UpdateWindow();
ShowWindow和UpdateWindow是所有窗口對(duì)象共用的CWnd成員函數(shù)其中包括CFrameWnd類(lèi)的對(duì)象,CMainWindow就是從CFrameWnd派生出來(lái)的.
要從MFC程序調(diào)用一個(gè)常規(guī)的Windows API函數(shù),需要在函數(shù)名稱(chēng)前添加一個(gè)全局運(yùn)算符:: 例如:::UpdateWindow();
通過(guò)生成窗口對(duì)象并調(diào)用其Create函數(shù),MFC應(yīng)用程序可以創(chuàng)建一個(gè)窗口,在CMyApp::InitInstance中,hello創(chuàng)建了一個(gè)CMainWindow對(duì)象,CMainWindow的構(gòu)造函數(shù)生成在屏幕上看到的窗口:
Create(NULL,”我的第一個(gè)MFC應(yīng)用程序”);
CPaintDC dc(this);
MFC的CPaintDC類(lèi)是從MFC的CDC類(lèi)派生的,CDC類(lèi)封裝了Windows設(shè)備環(huán)境,以及包含了繪制到屏幕、打印機(jī)和其他設(shè)備的幾十個(gè)成員函數(shù)

在MFC中如何處理消息呢?
在SDK中我們利用的是消息循環(huán)和窗口過(guò)程函數(shù)對(duì)消息進(jìn)行消息處理.
在MFC中我們用的是消息映射機(jī)制.
下面是將消息映射添加到一個(gè)類(lèi)中需要做的全部工作.
1>通過(guò)將DECLARE_MESSAGE_MAP語(yǔ)句添加到類(lèi)聲明中,聲明消息映射.
2>通過(guò)放置標(biāo)識(shí)消息的宏來(lái)執(zhí)行消息映射,相應(yīng)的類(lèi)將在對(duì)BEGIN_MESSAGE_MAP和END_MESSAGE_MAP的調(diào)用之間處理消息
3>添加成員函數(shù)來(lái)處理消息
1、構(gòu)造CWinApp派生類(lèi)的對(duì)象
2、系統(tǒng)調(diào)用WinMain()
3、WinMain調(diào)用InitInstance,在該函數(shù)中創(chuàng)建CFrameWnd派生類(lèi)對(duì)象,調(diào)用Create函數(shù)創(chuàng)建窗口、調(diào)用ShowWindow函數(shù)顯示窗口。
4、之后內(nèi)部機(jī)制調(diào)用Run,接受用戶(hù)的消息,并將消息導(dǎo)向默認(rèn)的處理函數(shù)。當(dāng)接收到WM_QUIT消息時(shí),Run內(nèi)部調(diào)用ExitInstance,退出程序。
MFC采用消息映射(Message Map)機(jī)制取代C/C++語(yǔ)言中的switch-case結(jié)構(gòu)來(lái)處理消息。
消息映射:在MFC中把消息處理函數(shù)和它所要處理的特定的消息連接起來(lái)的一種機(jī)制。
它通過(guò)宏來(lái)實(shí)現(xiàn)消息到成員函數(shù)的映射,而且這些函數(shù)不必是虛擬的成員函數(shù),這樣不需要為消息映射函數(shù)生成一個(gè)很大的虛擬函數(shù)表(V表),節(jié)省內(nèi)存。
MFC消息映射機(jī)制包括一組消息映射宏。一條消息映射宏把一個(gè)Windows消息和其消息處理函數(shù)聯(lián)結(jié)起來(lái)。
MFC應(yīng)用程序框架提供了消息映射功能。
在類(lèi)的實(shí)現(xiàn)源文件中用BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()宏來(lái)定義消息映射。
在類(lèi)定義的結(jié)尾用DECLARE_MESSAGE_MAP()宏來(lái)聲明使用消息映射。
Hello的CmainWindow類(lèi)只處理一種消息類(lèi)型—WM_PAINT,因此其消息映射的實(shí)現(xiàn)如下所示:
BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd);
ON_WM_PAINT()
END_MESSAGE_MAP()
BEGIN_MESSAGE_MAP開(kāi)始了消息映射,并標(biāo)識(shí)了消息映射所屬的類(lèi)和該類(lèi)的基類(lèi)
END_MESSAGE_MAP()結(jié)束消息映射.
ON_WM_PAINT()在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP()之間,稱(chēng)做消息條目,在MFC為100多種Window消息提供了宏.
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
afx_msg 醒目地暗示OnPaint是一個(gè)消息處理程序,
DECLARE_MESSAGE_MAP()聲明消息映射
MFC把消息主要分為三大類(lèi):
(1)、標(biāo)準(zhǔn)Windows消息(WM_XXX)
使用宏:ON_WM_XXX()          特點(diǎn):有默認(rèn)的消息處理函數(shù)
(2)、命令消息:(WM_COMMAND)
來(lái)自于菜單、工具條、按鈕等的消息
使用宏: ON_COMMAND(命令按鈕標(biāo)識(shí)符ID,消息處理函數(shù))
特點(diǎn):由用戶(hù)指定消息處理函數(shù)
3、”Notification消息” (通知消息) 由控件產(chǎn)生:
BOOL    布爾值,取值為T(mén)RUE或者FALSE
BSTR     32為字符指針
BYTE      8位整數(shù)無(wú)符號(hào)的
COLORREF     32位數(shù)值代表一個(gè)顏色值
DWORD    32位整數(shù)無(wú)符號(hào)的
LONG     32位整數(shù)帶符號(hào)的
LPCTSTR   32位指針,指向一個(gè)常字符串
LPVOID    32位指針,指向一個(gè)為指定類(lèi)型的數(shù)據(jù)
MFC特有的數(shù)據(jù)類(lèi)型:
1>POSITION :一個(gè)數(shù)值,代表數(shù)組或者鏈表中元素的位置,在MFC中常用于數(shù)據(jù)處理類(lèi)
2>LPRECT:32位指針,指向一個(gè)不變的矩形區(qū)域結(jié)構(gòu)

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表