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);
protected:
//應用程序句柄
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的文件類?文件查找類?