天天看點

MFC基礎類及其層次結構

從類CCmdTarget派生出絕大多數MFC中的類,其層次結構如下圖:

從根類Cobject層層派生出絕大多數MFC中的類,層次結構如下圖:

MFC中重點類:

CObject類是MFC的絕大部分類的基類。該類完成動态空間的配置設定與回收,支援一般的對象診斷、運作時類型辨別,出錯資訊處理和文檔序列化等。

      (1)對象診斷:利用成員函數AssertValid進行對象有效性檢查;利用成員函數Dump輸出對象的資料成員的值,診斷資訊以文本形式放入一個資料流中,用于調試器的輸出視窗資訊顯示。(隻能用于Debug版的應用程式)

      (2)運作時類型識别:GetRuntimeClass根據對象的類傳回一個相關聯的指向CRuntimeClass結構的指針,它包含了一個類的運作資訊;函數IsKindOf用于測試對象與給定類的關系。

      (3)通過與Carchive相結合,CObject類為其派生類提供了序列化功能。要建立一個支援序列化的派生類,必須将DECLARE_SERIAL宏添加到類定義中,将IMPLEMENT_SERIAL添加到類的實作檔案中。

  

  CCmdTarget:由CObject類直接派生,所有能實行消息映射MFC類的基類。将系統事件和視窗事件發送給響應這些事件的對象,完成消息發送、等待和派遣(排程)等工作,實作應用程式的對象之間協調運作,功能如下:

  (1)消息發送:MFC應用程式為每個CCmdTarget派生類建立一個稱為消息映射表的靜态資料結構,可将消息映射到對象所對應的消息處理函數上。

  (2)設定光标:程式正在進行某種操作:BeginWaitCursor()将光标改為沙漏形狀;操作完成:EndWaitCursor()将光标改回到之前的形狀;處于等待狀态時由于某些操作改變了光标形狀後,RestoreWaitCursor()用于将光标還原為等待狀态。

  (3)支援自動化:CCmdTarget類支援程式通過COM接口進行互動操作,自動翻譯COM接口的方法。方法是調用EnableAutomation()、FromIDispatch()、GetIDispatch()、IsResultExpected()和 OnFinalRelease()。

  CWinThread類:

  由CCmdTarget派生,主要工作是建立和處理消息循環。

  CWinApp: 從CWinThread類派生而來。CWinThread類用來完成對線程的控制,包括線程的建立,運作,終止和挂起等。成員函數InitApplication()、InitInstance()、Run()。

在MFC應用程式中有且僅有一個CWinApp派生類的對象,代表程式運作的主線程,代表應用程式本身。

  CDocument: 文檔類,包含了應用程式在運作期間所用到的資料。從CCmdTarget派生,作為使用者文檔的基類,代表了使用者存儲或打開一個檔案。主要功能是把對資料的處理從對使用者的界面進行中分離出來,同時提供一個與視圖類互動的接口。常用的成員函數有:

OnNewDocument():建立新文檔。

OnOpenDocument():打開一個文檔。

  CWnd: 通用的視窗類,用來提供windows中所有的通用特性。由CCmdTarget類直接派生,是MFC中最基本的GUI對象。公共變量m_hWnd用于存放供API函數調用的視窗句柄。CWnd類和消息映射機制隐藏了視窗函數WndProc。一個Windows消息通過消息映射發送到相應的CWnd類OnMessage成員函數,可以重載。

  CView: 用于讓使用者通過視窗來通路文檔以及負責文檔内容的顯示。文檔視圖結構中的使用者操作區。

  CFrameWnd: 從CWnd繼承來的,并實作了标準的架構應用程式。主要用來掌管一個視窗。其對象是一個架構視窗,包括邊界、标題欄、菜單、最大化按鈕、最小化按鈕和一個激活的視圖。

  其常用成員函數:

    GetActiveDocument():得到目前文檔的指針。

    GetActiveView():得到目前視圖的指針。

    SetActiveView():激活一個視圖。

    GetTitle():得到架構視窗的标題。

    SetTitle():設定架構視窗的标題。

    SetMessageText():設定狀态欄文本。

  CDialog: 用來控制對話框視窗。

  CMDIFrameWnd和CMDIChildWnd: 分别用來多文檔應用程式的主架構視窗和文檔子視窗的顯示和管理。

  CMiniFrameWnd:一種簡化的架構視窗,沒有最大化和最小化視窗按鈕,也沒有視窗系統菜單,很少用。

        WinApp封裝了程式的主入口WinMain,WinMain就和C語言的main函數地位一樣,是Win32程式的入口。在MFC的封裝中,一個程式啟動,Windows調用WinMain,這個WinMain函數現在由MFC事先寫好藏好了,你不能也不需要修改,在這個預定義的WInMain裡面會調用CWinApp的IniInInstance函數。在InitInstance函數,CMainFrame的對象被建立,文檔模闆被建立,主視窗通過ShowWindow(SW_SHOW)被顯示出來。

  CMainFrame是個架構,是你整個應用程式的主視窗,負責管理應用程式的菜單,工具欄,狀态欄等。中間的區域是客戶區,由View類來管理,View類也是一個視窗,是MainFrame的子視窗。OnDraw函數負責繪制客戶區的内容,你調用View類的UpdateWindow,或者在Document類中調用UPdateAllViews等等,MFC會自動調用OnDraw。他還會被Window調用,Windows在需要重新整理視窗的時候發送給視窗WM_PAINT消息,MFC事先預定義了,在響應WM_PAINT消息的時候會調用OnDraw。 那麼什麼時候視窗會發送WM_PAINT消息呢,比如視窗從最小化還原,比如視窗被使用者改變了大小等等。

  程式在進入WinMain函數之前做很多事情,初始化DOS頭,配置設定函數表,初始化全局變量,之後才進入WinMain。

  MFC對Windows API進行封住請。MFC編譯器連結器把源檔案編譯成PE檔案格式,存儲在磁盤上。程式執行的時候,從PE檔案頭開始執行,在進入Winmain函數之前,進行一系列的必備的初始化。

  MFC對這個過程進行封裝,提供給程式設計人員的第一個裸露程式入口就是CWinApp的InitInstance(),其實程式的入口依然是WinMain()函數。

  每個程式都有一個程序,每個程序至少有一個線程就是主線程。CWinThread類是MFC用來封裝線程的。這個主線程就是在WinMain函數中建立的,包括UI線程和工作者線程。是以每個MFC程式至少使用一個CWinThread派生類。被MFC程式員熟知的CWinApp應用類就從這裡派生。

  InitInstance是CWinThread的一個虛函數,它是在執行個體建立時首先被調用的。應用程式總是要重載這個虛函數,進行系統設定,建立運作環境。主視窗一定要在InitInstance()中建立,因為該函數退出後就進入該線程的消息循環。

  MFC執行流程:_tWinMain(WinMain别名)-》AfxWinMain-》初始化線程,調用InitInstance初始化視窗,調用Run函數進入消息循環。

  MFC中DoDataExchange的作用:将界面上的控件與一個變量或對象關聯。

程式入口和執行流程

1) WIN32 API程式當中,程式入口為WinMain函數,在這個函數當中我們完成注冊視窗類,建立視窗,進入消息循環,最後由作業系統根據發送到程式視窗的消息調用程式視窗函數。而在MFC程式當中我們找不到類似WinMan這樣的程式入口,取而代之的是一系列派生類的聲明和定義以及一個從CWinApp類派生而來的類的全局對象。CWinApp類被稱為應用程式對象,在一個MFC程式中隻允許有一個應用程式對象。由于CWinApp的派生類對象是全局的,是以這個對象的構造函數會在所有的其他代碼運作之前調用,而由于CWinApp類當中包含了HWND、HINSTANCE等句柄的存在,其構造函數就執行了對這些成員資料的初始化操作。

2) 調用往CWinApp的構造函數後,AfxWinMain函數被調用,而這個函數可以被看做MFC程式的入口函數。在這個函數當中調用全局AfxGetApp()函數獲得應用程式對象,這時将調用AfxInit全局函數,功能是使用作業系統傳遞給AfxWinMain函數的參數初始化應用程式對象當中的相關句柄資料成員。

3) AfxWinMain函數調用CWinApp::InitApplication()成員函數,初始化應用程式對象當中的關于文檔部分的内容

4) AfxWinMain函數調用CWinApp::InitInstance成員函數,函數中,用new在堆上聲明一個架構視窗對象,架構視窗對象的構造函數被調用,構造函數當中調用Create函數來建立視窗,而調用的create函數一般将WNDCLASS參數設定成NULL,,這樣就由MFC内部調用PreCreateWindow函數,在這個函數當中由MFC注冊幾個預設的WNDCLASS供架構視窗的Create使用。這時程式控制權交還給CWinApp::InitInstance成員函數内部,由這個函數調用CWnd::ShowWindow顯示視窗并且調用CWnd::UpdateWindow向視窗發送WM_PAINT消息。調用完CWinApp::InitInstance成員函數後由AfxWinMain函數調用CWinApp::Run成員函數,并由這個函數來建立和處理消息循環,并且在沒有消息的時候處理OnIdle空閑處理。至此整個程式的建立過程完成。

5)在程式的運作過程當中,由作業系統源源不斷的發送消息給應用程式,并且由CWinApp::Run當中的消息循環處理并且分發給相關的視窗對象的DefWindowProc成員函數,并由這個成員函數查詢視窗對象的消息映射表,如果查到對應項,則由登記在消息映射表當中的類成員函數處理,否則則按照Message Route當中的順序象父層類發送。

6)在消息運作結束,使用者按下關閉按鈕後,作業系統向程式發送WM_CLOSE消息,預設狀況下程式調用DestoryWindow并且發送WM_DESTORY消息,應用程式接受到這個消息以後的預設操作是調用PostQuitMessage函數,由這個函數發送WM_QUIT消息。當程式對象接受到WM_QUIT消息後消息循環結束,由AfxWinMain函數調用AfxTerm函數清理程式使用過的資源并且結束整個程式。

消息機制

1 消息機制的要點:

  消息隊列:先進先出

  消息循環:通過循環while,不斷的從消息隊列中取得隊首消息,并分發消息。

  消息處理:根據不同的消息類型做不同的處理

  事件:事件響應函數

2 消息機制

_tWinMain

{

// 注冊視窗類

if(!AppRegisterClass(hInstance)) // hInstance 是應用程式句柄,把這個和winproc注冊上。

return (FALSE);

}

// 初始化應用程式視窗

if (!InitInstance (hInstance, nCmdShow)) // 注冊之後開始初始化應用視窗(createWindow得到g_hWnd ;ShowWindow(); UpdateWIndow)_)

return FALSE;

// 消息循環

MSG msg;

while (GetMessage(&msg, NULL, 0, 0))

TranslateMessage(&msg);

DispatchMessage(&msg);

return (int) msg.wParam;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) //定義消息處理函數

wndProc會根據message類型調用對應的事件響應函數。

onDraw () // 每次重新整理的時候都會重新繪制。

對于每一個正在執行的Windows應用程式,系統為其建立一個"消息隊列",也就是應用程式隊列

DispatchMessage會将消息傳遞給視窗函數,也就是WndProce函數。

WndProc是一個回調函數,在注冊視窗時通過wcex.lpfnWndProc将其傳遞給了OS,是以DispatchMessage分發消息後,OS會調用

Wndproc去處理。

消息的定義和類型:

windows消息都以WM_為字首,WM_PAINT. 

typedef struct tagMsg

HWND hwnd; //接受該消息的視窗句柄

UINT message; //消息常量辨別符,也就是我們通常所說的消息号

WPARAM wParam; //32位消息的特定附加資訊,确切含義依賴于消息值

LPARAM lParam; //32位消息的特定附加資訊,确切含義依賴于消息值

DWORD time; //消息建立時的時間

POINT pt; //消息建立時的滑鼠/光标在螢幕坐标系中的位置

}MSG;

消息主要有3種類型:

A: 指令消息:

B: 标準視窗消息:

C: Notification:

隊列消息和非隊列消息: 按照是否需要放入隊裡

POSMessage 與 SendMessage:

POSMessage:發送到消息對列

SendMessage:非對列消息。直接發送視窗,等待執行結束。

常見面試題

1:應用程式類

CTestOneApp::InitInstance

可以看做是MFC程式的入口函數,main函數隐藏在這個函數中。實際開發中一般不需要對這個類進行操作,但如果要在建立主對話框之前處理一些資料或者準備工作,就可以把代碼添加到這個函數中,主對話框顯示之前。

這裡有兩個比較典型的應用:

1)啟動界面之前彈出個登入界面。

2)啟動界面之前,彈出一個項目配置界面。

2:對話框類

// CTestOneDlg 對話框類,繼承自CDialogEx類。對話框類負責與使用者互動,處理使用者消息,接收使用者輸入。

class CTestOneDlg : public CDialogEx

public:

// 标準構造函數

CTestOneDlg(CWnd* pParent = NULL);

// 對話框資料

enum { IDD = IDD_TESTONE_DIALOG }; 

protected:

// 動态資料交換,負責控件與變量之間的關聯

virtual void DoDataExchange(CDataExchange* pDX); 

//應用程式句柄

HICON m_hIcon;

//重載初始化對話框

virtual BOOL OnInitDialog();

//定義消息WM_SYSCOMMAND處理函數

afx_msg void OnSysCommand(UINT nID, LPARAM lParam);

//定義消息WM_PAINT處理函數

afx_msg void OnPaint();

//定義消息ON_WM_QUERYDRAGICON處理函數

afx_msg HCURSOR OnQueryDragIcon();

//消息映射

DECLARE_MESSAGE_MAP()

};

這個類看出以下幾點:

(1)控件與資料關聯,可以簡單的交給架構

(2)在MFC架構上開發主要是針對消息處理機制

添加一個button,并且添加一個事件後:會有如下變化

PUSHBUTTON "Button1",IDC_BTN_TEST,151,57,50,14 // RC 檔案拿這個ID作為控件的标示

#define IDC_BTN_TEST 1001 /resource.h 定義一個ID号。

afx_msg void OnBnClickedBtnTest(); // 事件響應函數

BEGIN_MESSAGE_MAP(CTestOneDlg, CDialogEx)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

ON_BN_CLICKED(IDC_BTN_TEST, &CTestOneDlg::OnBnClickedBtnTest) // 把事件,響應函數, 行為三者綁定到一起

END_MESSAGE_MAP()

void CTestOneDlg::OnBnClickedBtnTest() //事件響應函數

// TODO: 在此添加控件通知處理程式代碼

3 SendMessage和 postMessage 差別

SendMessage : 同步, 傳回值表示處理消息後的傳回值。

postMessage: 異步,隻是把消息放入隊列,傳回值僅表示post是否正确。

同一個線程内:PostMessage隻把消息放入隊列,然後通過消息循環Dispatch到達視窗。SendMessage發送消息時,系統直接調用目标視窗的消息處理程式,并将結果傳回。

不同線程:最好用PostThreadMessage代替PostMessage。 SendMessage發送消息到目标視窗所屬線程的消息隊列,然後發送的線程等待,直 到處理完。

4 onpaint() 和 ondraw()

視窗改變後,産生無效區域,需要重繪,windows會發送WM_PAINT通知客戶區變化,客戶區的重繪需要自己完成。

CVIew派生自CWnd, 而OnPaint()是CWnd 的類成員,同時負責響應WM_PAINT消息。OnDraw()是CVIEW的成員,沒有響應消息功能。

要想在螢幕上繪圖,首先要建立裝置環境DC,DC是一個資料結構,包含輸出裝置的繪圖屬性的描述。MFC提供了CPaintDC 類和CWindowDC 類

實時響應,CPaintDC支援重畫。

當視圖無效時(大小,移動,被遮蓋)Windows将WM_PAINT消息發送給它。 該視圖的OnPaint處理函數通過建立CPaintDC類的DC對象來響應

該消息并調用視圖的OnDraw成員函數,通常不用重寫ONpaint函數。

void CView::OnPaint()

CPaintDC dc(this);

OnPreparDC(&dc);

OnDraw(&dc); //調用了OnDraw

OnPaint最後也要調用OnDraw,是以我們一般會在OnDraw函數中進行繪制。

void CMyView::OnDraw( CDC* pDC )

CMyDoc* pDoc = GetDocument(); 

CString s = pDoc->GetData(); // Returns a CString

CRect rect;

GetClientRect( &rect ); 

pDC->SetTextAlign( TA_BASELINE | TA_CENTER ); 

pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() );

5 強制重畫視窗

InvalidateRect(&Rect) :使得指定的區域無效。

Invalidate():使得整個視窗無效,形成無效矩形。

UpdateWindow(): 立即發送WM_PAINT,不過在它發送前,先調用GetUpdateRect(hWnd,NULL,TRUE)看有無可 繪制區域,如果沒有則不發送消息。

RedrawWindow()是具有Invalidate()和UpdateWindow()的雙特性。聲明視窗的狀态為無效,并立即更新視窗,立即調用WM_PAINT消息處理。

6  CView 與 CDcoument關系

CVIew 有一個成員變量CDocument, 指向相關的Document.

CView 與 Document交談的過程:

A:使用者在View做動作,取得Document指針,更改資料内容。

B: View調用Document的UpdatedAllViews.

C: 其他的view的onUpdate() 被調用, 各種view的畫面就更新了。

D:CVIew:Onupdate()被調用,代表通知他:document的内容已經改變了,你更新畫面吧。 也可以用一種低效率的方式: invaalidate(TRUE),把視窗

整個設為重繪區,産生WM_paint,再讓Cview::OnDraw()。 

7 你熟悉預編譯指令麼?條件編譯是用來做什麼的?你會寫麼?

預編譯指令: 在編譯之前做一些事。

#include : 檔案包含

#define: 宏替換

# if, #ifndef, #ifdef, #endif, #undef : 條件編譯。

#pragma :布局控制。 主要是設定編譯器的狀态。 #pragma once                #pragma pack(n)

8  C++ 中的string/WString

string就是*char, wstring wchar_t, 用來進行中文,是寬字元。

9 MFC用的是Unicode

10 stdafx.h   頭檔案預編譯

把一個工程中使用的一些MFC标準頭檔案(windows.h Afxwin.h)預先編譯,以

後該工程編譯時,不再編譯這部分頭檔案。

11 MFC包含幾種類型程式?其中MFC應用程式又包含哪幾類

單文檔(畫圖),多文檔(vs 2015), 對話框.

12 MFC的消息機制

MFC使用一種消息映射機制來處理消息,一個消息與消息處理函數一一對應的消息映射表,以及消息處理

函數的聲明和實作代碼。當視窗接收到消息的時候,會到消息映射表中查找消息的處理函數,然後消息處理函數進行

處理

13 消息映射

Windows程式都維護有自己的消息隊列,保持隊列消息(當然也有非隊列消息,他們直接發給視窗),并用消息循環

對消息進行處理。

消息循環首先通過GetMessage取得消息并從隊列中移除,對于加速鍵,會調用TranslateAccelerator函數,對其進行

翻譯和處理,如果處理成功就不在調用translateMessge. 

否則進行消息的轉換和派發。讓目的視窗的視窗過程來處理消息。

while (GetMessage(&msg, NULL, 0, 0)) 

if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 

TranslateMessage(&msg); 

DispatchMessage(&msg); 

真正處理消息的是所謂的視窗過程(LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)),這個函數的參數記錄了過程對應的視窗、消息的ID以及參數,在其内部開發者可以實作。

14 自定義消息

A、自定義消息号:#define WM_CCTRY_MSG (WM_USER+100)

B、在頭檔案中添加消息響應函數的聲明:afx_msg LRESULT OnCcTryMsg(WPARAM wParam, LPARAM lParam);

C、在CPP檔案中添加消息響應函數的實作:

LRESULT CXXXDlg::OnCcTryMsg(WPARAM wParam, LPARAM lParam) {

//相關代碼;

D、在 BEGIN_MESSAGE_MAP 與 END_MESSAGE_MAP 之間加入消息的映射代碼:ON_MESSAGE(WM_CCTRY_MSG, &CDlgTestDlg::OnCcTryMsg)

然後在想觸發消息的地方:sendMessage(),就可以。

15. MFC的對話框的種類,各自怎麼使用?及相關函數。

模态對話框和非模态對話框。

模态對話框:工作時其父視窗無效。 DoModal();

非模态對話框: dlg.Create(;)

15 程序間通信

管道(匿名): 半雙工。隻适合父子程序之間通信。傳輸的是流。是以程序間通信必須約定好資料格式。建立管道時,

        配置設定一個頁面作為資料緩沖區,程序對緩沖區進行讀寫。

有名管道:非父子程序也可以通信,有傳輸格式。

消息隊列:放在核心中的消息連結清單,

信号量:

共享記憶體:配置設定一塊能被其他程序通路的記憶體。共享的記憶體被映射到兩個程序的虛拟空間。但是需要自己提供同步機制。

信号量,互斥鎖都可以。

這個效率最高,管道和消息隊列需要在核心和使用者空間資料拷貝。

16 MFC程式的初始化:http://www.jizhuomi.com/software/267.html

建立MFC視窗很容易,隻用兩步:

從CWinApp派生一個應用程式,然後建立應用程式對象。initInstance()裡面建立視窗就行。

WinMain()函數:

InitInstance 是程式入口點,是虛函數,應用程式初始化(其實也winmain函數調用它的)

注意: 全局變量的的構造函數在main函數之前執行。

基本流程:

注冊視窗:注冊後才能從系統中找到它,獲得句柄,然後向視窗發送消息。

建立視窗:

顯示更新視窗:show, update()

消息循環:

回調函數:

17  消息映射機制的原理及實作。

在每個能接收和處理消息的類中,定義一個消息和消息函數靜态對照表,将消息與消息處理函數綁定。當處理消息的時候到這個表中去查就行了。

BEGIN_MESSAGE_MAP() 宏中定義。

18  ASSERT() ,是函數還是宏 

預處理宏, assert(expr), 先計算表達式expr, 如果為假,那麼它會輸出資訊并終止程式執行。

如果用if else實作同樣功能的話,就會從函數開始括到函數尾。

assert是宏不是函數,定義在cassert頭檔案中。

使用assert的缺點是,頻繁的調用會極大的影響程式的性能,增加額外的開銷;

完成調試後,不必從源代碼中删除assert()語句,因為宏NDEBUG有定義時,宏assert()的定義為空,

即可以通過在包含#include assert.h>或#include< csaaert >的語句之前插入 #define NDEBUG 來禁用assert調用:

assert隻有在Debug版本中才有效,如果編譯為Release版本則被忽略(程式一般分為Debug 版本和Release 版本,

Debug 版本用于内部調試,Release 版本發行給使用者使用);

assert用法注意:

A:不要一起判斷多個條件,否則不知道是哪個有問題。

B:不能改變變量的值、

C: assert語句後面空一行。

19 MFC消息三種類型

      在MFC應用程式中傳輸的消息有三種類型:視窗消息、指令消息和控件通知。  

(1)視窗消息:WM_XXX,除WM_COMMAND之外,所有以WM_開頭的消息

      視窗消息(Window Message)一般與視窗的内部運作有關,如:建立視窗、繪制視窗和銷毀視窗等。通常,消息是從系統發送到視窗,或從視窗發送到視窗。  

(2)指令消息:WM_COMMAND

      指令消息一般與處理使用者請求相關,當使用者單擊一個菜單項或工具欄時,指令消息産生,并被發送到能處理該請求的類對象(如:裝載檔案、編輯文本和儲存選項等)。  

(3)控件通知:有多種格式

      通常,控件通知在某些重要事件發生時,由控件視窗發送到父視窗,如打開一個組合框。控件通知為父視窗進一步控制子視窗提供了機會。例如,打開一個組合框時,父視窗可以用組合框初建時得不到的消息填充它。  

      BN_XXXX是CButton産生的消息,EN_XXXX是CEdit産生的消息,等等。

現在就可以知道為什麼有ON_MESSAGE ,ON_COMMAND, , ON_NOTIFY了。

ON_MESSAGE是處理所有的Windows的消息的,因為所有的消息都以相同的格式傳送,也就是ID, WPARAM, LPARAM.

ON_COMMAND是專門處理WM_COMMAND消息的,這樣我們就不用自己解開WM_COMMAND中wParam和lParam中傳送的控件ID, 事件種類…(所有的都在MFC内部解決了:),當然友善了。

ON_NOTIFY更是不用說了,看看他的處理函數,是不是把NMHDR解出來了。

20 MFC繪圖有哪幾類DC?各自的類名,及差別

   裝置描述表(DC)是Windows中的一種資料結構,它包含GDI需要的所有關于顯示界面情況的描述字段,包括相連的實體裝置和各種各樣的狀态資訊。進而提供了應用程式設計的平台無關性。

HDC:裝置上下文句柄(可以了解為指向DC結構的指針),它指向一塊描述裝置的相關的内容的記憶體塊。

CDC:是MFC裡面的一個類,且這類封裝了幾乎所有關于HDC的操作,由于類的内部包含一個m_hWnd的句柄,

是以,CDC封裝的操作(函數)與SDK平台中與關于HDC的操作都缺少一個指向裝置上的句柄(不是沒有,而是這個句柄在被封裝起來)。

(1)、HDC到CDC的轉換:

方法一: 此方法在裝置結束時不會銷毀原來的資源(即:hDC,hBitmap)

CDC *pDC = CDC::FromHandle(hDC);

方法二:此方法在裝置結束時會銷毀原來的資源(即:hDC,hBitmap)

CDC dc;

dc.Attach(hDC);

(2)、CDC到HDC的轉換:

   CDC  dc;

   HDC  hDC;

   hDC = dc.GetSafeHdc();

CPaintDC:

CClientDC:

CWindowDC:

21:  MFC的線程有哪幾類?互相有什麼差別?各自的建立方法是什麼

 兩種:界面線程:有消息循環,能響應使用者的界面操作,必須繼承自CWinThread.

            工作線程:

  AfxBeginThread(RUNTIME_CLASS(MyThread));   二者的參數有差別。

22 MFC常用控件?通用對話框?

23 MFC的檔案類?檔案查找類?

繼續閱讀