windows消息處理機制_第1頁
windows消息處理機制_第2頁
windows消息處理機制_第3頁
windows消息處理機制_第4頁
windows消息處理機制_第5頁
已閱讀5頁,還剩27頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、windows消息處理機制消息,就是指Windows發(fā)出的一個通知,告訴應用程序某個事情發(fā)生了。例如,單擊鼠標、改變窗口尺寸、按下鍵盤上的一個鍵都會使Windows發(fā)送一個消息給應用程序。消息本身是作為一個記錄傳遞給應用程序的,這個記錄中包含了消息的類型以及其他信息。例如, 對于單擊鼠標所產(chǎn)生的消息來說,這個記錄中包含了單擊鼠標時的坐標。這個記錄類型叫做TMsg,它 在Windows單元中是這樣聲明的: type TMsg = packed record hwnd: HWND; / /窗口句柄 message: UINT; / /消息常量標識符 wParam: WPARAM ; / 32位消息

2、的特定附加信息 lParam: LPARAM ; / 32位消息的特定附加信息 time: DWORD; / /消息創(chuàng)建時的時間 pt: TPoint; / /消息創(chuàng)建時的鼠標位置 e n d ; 消息中有什么? 是否覺得一個消息記錄中的信息像希臘語一樣?如果是這樣,那么看一看下面的解釋: hwnd 32位的窗口句柄。窗口可以是任何類型的屏幕對象,因為Win32能夠維護大多數(shù)可 視對象的句柄(窗口、對話框、按鈕、編輯框等)。 message 用于區(qū)別其他消息的常量值,這些常量可以是Windows單元中預定義的常量,也可以是自定義的常量。 wParam 通常是一個與消息有關的常量值,也可能是窗口

3、或控件的句柄。 lParam 通常是一個指向內(nèi)存中數(shù)據(jù)的指針。由于WParam、lParam和Pointer都是32位的,因此,它們之間可以相互轉換。 Windows的消息系統(tǒng)是由3個部分組成的: ? 消息隊列。Windows能夠為所有的應用程序維護一個消息隊列。應用程序必須從消息隊列中獲取 消息,然后分派給某個窗口。 ? 消息循環(huán)。通過這個循環(huán)機制應用程序從消息隊列中檢索消息,再把它分派給適當?shù)拇翱冢?后繼續(xù)從消息隊列中檢索下一條消息,再分派給適當?shù)拇翱冢来芜M行。 ? 窗口過程。每個窗口都有一個窗口過程來接收傳遞給窗口的消息,它的任務就是獲取消息然后 響應它。窗口過程是一個回調函數(shù);處理

4、了一個消息后,它通常要返回一個值給Wi ndows。 注意回調函數(shù)是程序中的一種函數(shù),它是由Windows或外部模塊調用的。 一個消息從產(chǎn)生到被一個窗口響應,其中有5個步驟: 1) 系統(tǒng)中發(fā)生了某個事件。 2) Windows把這個事件翻譯為消息,然后把它放到消息隊列中。 3) 應用程序從消息隊列中接收到這個消息,把它存放在TMsg記錄中。 4) 應用程序把消息傳遞給一個適當?shù)拇翱诘拇翱谶^程。 5) 窗口過程響應這個消息并進行處理。 步驟3和4構成了應用程序的消息循環(huán)。消息循環(huán)往往是Windows應用程序的核心,因為消息循環(huán) 使一個應用程序能夠響應外部的事件。消息循環(huán)的任務就是從消息隊列中檢索

5、消息,然后把消息傳遞給適當?shù)拇翱?。如果消息隊列中沒有消息,Windows就允許其他應用程序處理它們的消息。Windows操作系統(tǒng)最大的特點就是其圖形化的操作界面,其圖形化界面是建立在其消息處理機制這個基礎之上的。如果不理解Windows消息處理機制,肯定無法深入的理解Windows編程??上Ш芏喑绦騿T對Windows消息只是略有所聞,對其使用知之甚少,更不了解其內(nèi)部實現(xiàn)原理,本文試著一步一步向大家披露我理解的Windows消息機制??梢哉f,掌握了這一部分知識,就是掌握了Windows編程中的神兵利器,靈活運用它,將會極大的提高我們的編程能力。 編輯本段Windows窗體是怎樣展現(xiàn)在屏幕上的呢?

6、眾所周知,是通過API繪制實現(xiàn)的。Windows操作系統(tǒng)提供了一系列的API函數(shù)來實現(xiàn)界面的繪制功能,例如:2 DrawText繪制文字2 DrawEdge繪制邊框2 DrawIcon繪制圖標2 BitBlt 繪制位圖2 Rectangle繪制矩形2 再復雜的程序界面都是通過這個函數(shù)來實現(xiàn)的。那什么時候調用這些函數(shù)呢?顯然我們需要一個控制中心,用來進行“發(fā)號施令”,我們還需要一個命令傳達機制,將命令即時的傳達到目的地。這個控制中心,就是一個動力源,就像一顆心臟,源源不斷地將血液送往各處。這個命令傳達機制就是Windows消息機制,Windows消息就好比是身體中的血液,它是命令傳達的使者。Wi

7、ndows消息控制中心一般是三層結構,其頂端就是Windows內(nèi)核。Windows內(nèi)核維護著一個消息隊列,第二級控制中心從這個消息隊列中獲取屬于自己管轄的消息,后做出處理,有些消息直接處理掉,有些還要發(fā)送給下一級窗體(Window)或控件(Control)。第二級控制中心一般是各Windows應用程序的Application對象。第三級控制中心就是Windows窗體對象,每一個窗體都有一個默認的窗體過程,這個過程負責處理各種接收到的消息。如下圖所示: <!-if !vml-><!-endif->說明圖 (注:windows指windows操作系統(tǒng);窗口:即wi

8、ndows窗口;窗體:包括窗口,以及有句柄的控件;control指控件,控件本身也可能是一個window,也可能不是;Application即應用程序,應用程序也可能不會用到Windows消息機制,這里我們專門討論有消息循環(huán)的應用程序)消息是以固定的結構傳送給應用程序的,結構如下:Public Type MSGhwnd As Longmessage As LongwParam As LonglParam As Longtime As Longpt As POINTAPIEnd Type其中hwnd是窗體的句柄,message是一個消息常量,用來表示消息的類型,wParam和lParam都是32

9、位的附加信息,具體表示什么內(nèi)容,要視消息的類型而定,time是消息發(fā)送的時間,pt是消息發(fā)送時鼠標所在的位置。Windows操作系統(tǒng)中包括以下幾種消息:1、標準Windows消息:這種消息以WM_打頭。2、通知消息通知消息是針對標準Windows控件的消息。這些控個包括:按鈕(Button)、組合框(ComboBox)、編輯框(TextBox)、列表框(ListBox)、ListView控件、Treeview控件、工具條(Toolbar)、菜單(Menu)等。每種消息以不同的字符串打頭。3、自定義消息編程人員還可以自定義消息。二、 關于Windows句柄不是每個控件都能接收消息,轉發(fā)消息和繪制

10、自身,只有具有句柄(handle)的控件才能做到。有句柄的控件本質上都是一個窗體(window),它們可以獨立存在,可以作為其它控件的容器,而沒有句柄的控件,如Label,是不能獨立存在的,只能作為窗口控件的子控件,它不能繪制自身,只能依靠父窗體將它繪制來。句柄的本質是一個系統(tǒng)自動維護的32位的數(shù)值,在整個操作系統(tǒng)的任一時刻,這個數(shù)值是唯一的。但該句柄代表的窗體釋放后,句柄也會被釋放,這個數(shù)值又可能被其它窗體使用。也就是說,句柄的數(shù)值是動態(tài)的,它本身只是一個唯一性標識,操作系統(tǒng)通過句柄來識別和查找它所代表的對象。然而,并非所有的句柄都是窗體的句柄,Windows系統(tǒng)中還中很多其它類型的句柄,如

11、畫布(hdc)句柄,畫筆句柄,畫刷句柄,應用程序句柄(hInstance)等。這種句柄是不能接收消息的。但不管是哪種句柄,都是系統(tǒng)中對象的唯一標識。本文只討論窗體句柄。那為什么句柄使窗口具有了如此獨特的特性呢?實際是都是由于消息的原因。由于有了句柄,窗體能夠接收消息,也就知道了該什么時候繪制自己,繪制子控件,知道了鼠標在什么時候點擊了窗口的哪個部分,從而作出相應的處理。句柄就好像是一個人的身份證,有了它,你就可以從事各種社會活動;否則的話,你要么是一個社會看不到的黑戶,要么跟在別人后面,通過別人來證明你的存在。三、 消息的傳送1、從消息隊列獲取消息:可以通過PeekMessage或GetMes

12、sage函數(shù)從Windows消息隊列中獲取消息。Windows保存的消息隊列是以線程(Thread)來分組的,也就是說每個線程都有自己的消息隊列。2、發(fā)送消息發(fā)送消息到指定窗體一般通過以下兩個函數(shù)完成:SendMessage和PostMessage。兩個函數(shù)的區(qū)別在于:PostMessage函數(shù)只是向線程消息隊列中添加消息,如果添加成功,則返回True,否則返回False,消息是否被處理,或處理的結果,就不知道了。而SendMessage則有些不同,它并不是把消息加入到隊列里,而是直接翻譯消息和調用消息處理(線程向自己發(fā)送消息才是這樣),直到消息處理完成后才返回。所以,如果我們希望發(fā)送的消息立

13、即被執(zhí)行,就應該調用SendMessage。還有一點,就是SendMessage發(fā)送的消息由于不會被加入到消息隊列中(錯:線程向其他線程發(fā)送消息也是追加到其他線程的發(fā)送消息隊列的,即使這兩個線程在同一個進程也是如此),所以通過PeekMessage或GetMessage是不能獲取到由SendMessage發(fā)送的消息。另外,有些消息用PostMessage不會成功,比如wm_settext。所以不是所有的消息都能夠用PostMessage的。還有一些其它的發(fā)送消息API函數(shù),如PostThreadMessage,SendMessageCallback,SendMessageTimeout,Sen

14、dNotifyMessage等。四、 消息循環(huán)與窗體過程消息循環(huán)是應用程序能夠持續(xù)存在的根本原因。如果循環(huán)退出,則應用程序就結束了。我們來看一看Delphi中封裝的消息循環(huán)是怎樣的:第一步:程序開始運行(Run)Application.Initialize;/初始化Application.CreateForm(TForm1, Form1);/創(chuàng)建主窗體Application.Run;/開始運行,準備進行消息循環(huán)如果不創(chuàng)建主窗體,應用程序同樣可以存在和運行。第二步:開始調用消息循環(huán)(HandleMessage)procedure TApplication.Run;beginFRunning :=

15、 True;tryAddExitProc(DoneApplication);if FMainForm <> nil thenbegincase CmdShow ofSW_SHOWMINNOACTIVE: FMainForm.FWindowState := wsMinimized;SW_SHOWMAXIMIZED: MainForm.WindowState := wsMaximized;end;if FShowMainForm thenif FMainForm.FWindowState = wsMinimized thenMinimize elseFMainForm.Visible

16、:= True;Repeat/注:循環(huán)開始tryHandleMessage;exceptHandleException(Self);end;until Terminated;/循環(huán)結束條件end;finallyFRunning := False;end;end;第三步:消息循環(huán)中對消息的處理。procedure TApplication.HandleMessage;varMsg: TMsg;beginif not ProcessMessage(Msg) then Idle(Msg);end;function TApplication.ProcessMessage(var Msg: TMsg):

17、 Boolean;varHandled: Boolean;beginResult := False;if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) thenbeginResult := True;if Msg.Message <> WM_QUIT thenbeginHandled := False;if Assigned(FOnMessage) then FOnMessage(Msg, Handled);if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) andnot IsKeyMs

18、g(Msg) and not IsDlgMsg(Msg) thenbeginTranslateMessage(Msg);DispatchMessage(Msg);end;endelseFTerminate := True;end;end;窗體過程實際上是一個回調函數(shù)。所謂的回調函數(shù),實際上就是由Windows操作系統(tǒng)或外部程序調用的函數(shù)?;卣{函數(shù)一般都有規(guī)定的參數(shù)格式,以地址方式傳遞給調用者。窗口過程中是Windows操作系統(tǒng)調用了,在一個窗口創(chuàng)建的時候,在分配窗體句柄的時候就需要傳入回調函數(shù)地址。那為什么我們平時編程看不到這個回調函數(shù)呢?這是由于我們的編程工具已經(jīng)為我們生成了默認的窗體過程,

19、這個過程的要做的事情就是判斷不同的消息類型,然后做出不同的處理。例如可以為鍵盤或鼠標輸入生成事件等。五、 消息與事件事件本質上是對消息的封裝,是IDE編程環(huán)境為了簡化編程而提供的有用的工具。這個封裝是在窗體過程中實現(xiàn)的。每種IDE封裝了許多Windows的消息,例如: 事件 消息 OnActivate WM_ACTIVATE OnClick WM_XBUTTONDOWN OnCreate WM_CREATE OnDblClick WM_XBUTTONDBLCLICK OnKeyDown 

20、;WM_KEYDOWN OnKeyPress WM_CHAR OnKeyUp WIN_KEYUP OnPaint WM_PAINT OnResize WM_SIZE OnTimer WM_TIMER       MFC框架原理以及消息運行機制 收藏 (1)Windows程序內(nèi)部運行機制        1,windows程序設計是種事件驅動方式的程序設計,主要基于消息的

21、。當用戶需要完成某種功能時,需要調用OS某種支持,然后OS將用戶的需要包裝成消息,并投入到消息隊列中,最后應用程序從消息隊列中取走消息并進行響應。2,消息結構:typedef struct tagMSG      / msg     HWND   hwnd;     /接收消息的窗口句柄。和哪個窗口相關聯(lián)。    UINT   message;  /消息標識。消息本身是什么。  

22、0; WPARAM wParam;   /消息的附加信息。具體取決于消息本身。      LPARAM lParam;     DWORD  time;     /消息投遞時間。     POINT  pt;       /消息投遞時,光標在屏幕上的位置。 MSG;  3,消息隊列:每個應用程序OS都為它建立一個消息隊列,消息隊列是個先進先出的緩沖

23、區(qū),其中每個元素都是一個消息,OS將生成的每個消息按先后順序放進消息隊列中,應用程序總是取走當前消息隊列中的第一條消息,應用程序取走消息后便知道用戶的操作和程序的狀態(tài),然后對其處理即消息響應,消息響應通過編碼實現(xiàn)。 4,使用VC編程除了良好的C基礎外還需要掌握兩方面:一,消息本身。不同消息所代表的用戶操作和應用程序的狀態(tài)。二,對于某個特定的消息來說,要讓OS執(zhí)行某個特定的功能去響應消息。 5,Window程序入口:int WINAPI WinMain(  HINSTANCE hInstance,  / 當前事例句柄。  HINSTANCE hP

24、revInstance,  / 先前事例句柄。  LPSTR lpCmdLine,      / 命令行指針  int nCmdShow          / (窗口)顯示的狀態(tài));說明:WinMain函數(shù)是Windows程序入口點函數(shù),由OS調用,當OS啟動應用程序的時候,winmain函數(shù)的參數(shù)由OS傳遞的。 6,創(chuàng)建一個完整的窗口需要經(jīng)過下面四個操作步驟:一,設計一個窗口類;如:WNDCLASS wndcls;

25、二,注冊窗口類;    如:RegisterClass(&wndcls);三,創(chuàng)建窗口;      如:CreateWindow(),CreateWindowEX();四,顯示及更新窗口。如:ShowWindow(),UpdateWindow(); 說明:創(chuàng)建窗口的時候一定要基于已經(jīng)注冊的窗口類. 7,Windows提供的窗口類:typedef struct _WNDCLASS     UINT    style; &

26、#160;      /窗口的類型    WNDPROC lpfnWndProc;  /窗口過程函數(shù)指針(回調函數(shù))    int     cbClsExtra; /窗口類附加字節(jié),為該類窗口所共享。通常0。    int     cbWndExtra; /窗口附加字節(jié)。通常設為0。    HANDLE  hInstance;&

27、#160; /當前應用程序事例句柄。    HICON   hIcon;      /圖標句柄 LoadIcon();    HCURSOR hCursor;    /光標句柄 LoadCursor();    HBRUSH  hbrBackground; /畫刷句柄 (HBRUSH)GetStockObject();    LPCTSTR lpszMenuName;

28、  /菜單名字    LPCTSTR lpszClassName; /類的名字 WNDCLASS;  8,窗口類注冊:ATOM RegisterClass(  CONST WNDCLASS *lpWndClass   / address of structure with class                    

29、60;           / data); 9,創(chuàng)建窗口:HWND CreateWindow(  LPCTSTR lpClassName,  / pointer to registered class name  LPCTSTR lpWindowName, / pointer to window name  DWORD dwStyle,        / window sty

30、le  int x,                / horizontal position of window  int y,                / vertical position of window  int nWidth,  

31、         / window width  int nHeight,          / window height  HWND hWndParent,      / handle to parent or owner window  HMENU hMenu,       

32、;   / handle to menu or child-window identifier  HANDLE hInstance,     / handle to application instance  LPVOID lpParam        / pointer to window-creation data); 10,顯示和更新窗口窗口:BOOL ShowWindow(  HWND hWnd,  

33、;   / handle to window  int nCmdShow   / show state of window);BOOL UpdateWindow(  HWND hWnd   / handle of window); 11,消息循環(huán):MSG msg;while(GetMessage(&msg,.)    /從消息隊列中取出一條消息TranslateMessage(&msg); /進行消息(如鍵盤消息)轉換DispatchMessage(&

34、msg); /分派消息到窗口的回調函數(shù)處理,(OS調用窗口回調函數(shù)進行處理)。 其中:/*The GetMessage function retrieves a message from the calling thread's message queue and places it in the specified structure. /*If the function retrieves a message other than WM_QUIT, the return value is nonzero.If the function retrieves the WM_Q

35、UIT message, the return value is zero. If there is an error, the return value is -1.  BOOL GetMessage(  LPMSG lpMsg,         / address of structure with message  HWND hWnd,           / handle of

36、window  UINT wMsgFilterMin,  / first message  UINT wMsgFilterMax   / last message);  /The TranslateMessage function translates virtual-key messages into character messages. The character messages are posted to the calling thread's message queue, to be read the

37、next time the thread calls the GetMessage or PeekMessage function. BOOL TranslateMessage(  CONST MSG *lpMsg   / address of structure with message); /The DispatchMessage function dispatches a message to a window procedure. LONG DispatchMessage(  CONST MSG *lpmsg   /

38、 pointer to structure with message);  12,窗口過程函數(shù)(回調函數(shù))原型:The WindowProc function is an application-defined function that processes messages sent to a window. The WNDPROC type defines a pointer to this callback function. WindowProc is a placeholder(占位符) for the application-defined function n

39、ame.  LRESULT CALLBACK WindowProc(  /這里WindowProc是個代號名字。  HWND hwnd,      / handle to window  UINT uMsg,      / message identifier  WPARAM wParam,  / first message parameter  LPARAM lParam   / second messa

40、ge parameter); 說明:兩種函數(shù)調用約定(_stdcall 和 _cdecl):#define CALLBACK    _stdcall /_stdcall 標準調用預定,是PASCAL 調用約定,象DELPHI使用的就是標準調用約定#define WINAPIV     _cdecl  / _cdecl 是C 語言形式的調用約定。  主要區(qū)別:函數(shù)參數(shù)傳遞順序和對堆棧的清除上。問題:除了那些可變參數(shù)的函數(shù)調用外,其余的一般都是_stdcall約定。但 C/C+編譯默然的是

41、_cdecl約定。所以如果在VC等環(huán)境中調用_stdcall約定的函數(shù),必須要在函數(shù)聲明的時加上 _stdcall 修飾符,以便對這個函數(shù)的調用是使用_stdcall約定(如使用DELPHI編寫的DLL時候)。(VC中可通過這途徑修改:project|settings.|c/c+|.)  在窗口過程函數(shù)中通過一組switch語句來對消息進行處理:如:LRESULT CALLBACK WindowProc(    HWND hwnd,  UINT uMsg,  WPARAM wParam,  LPARAM lParam

42、0;  )    switch(uMsg)    case WM_PAINT:  .  break;case .  break;case WM_CLOSE:  /DestroyWindow(hwnd);   /銷毀窗口,并發(fā)送WM_DESTROY消息。  break;case WM_DESTROY:  /PostQuitMessage(0);  /發(fā)送WM_QUIT消息到消息隊列中,請求終止。   

43、0;     /GetMessage()取到WM_QUIT消息后,返回0,退出消息循                /   環(huán),從而終止應用程序。  break;default:  return DefWindowProc(hwnd,uMsg,wParam,lParam);/用缺省的窗口過程處理我們不感興趣的消息(其它消息)。/這是必須的。  &#

44、160; /switchreturn 0;/WindowProc 13,DestroyWindow()函數(shù)和PostQuitMessage()函數(shù)原型:/*The DestroyWindow function destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages。 BOOL DestroyWindow(  HWND hWnd   / handle to window to destroy); /*The PostQu

45、itMessage function indicates to the system that a thread has made a request to terminate (quit). It is typically used in response to a WM_DESTROY message. /*The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates(預

46、示,通知) to the system that the thread is requesting to quit at some time in the future.  When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system. VOID PostQuitMessage(  int nExitCode   / exit code);

47、 14,關于DC句柄獲取:a)使用BeginPaint(),EndPaint()對。注意只能在響應WM_PAINT消息時使用。b)使用GetDc(),ReleaseDC()對。注意他們不能在響應WM_PAINT中使用。 (2)C+ 1,c語言中,結構體struct中不能包括函數(shù)的,而在C+中struct中可以包括函數(shù)。2,C+中結構體和類可以通用,區(qū)別主要表現(xiàn)在訪問控制方面:struct中默認是public,而 class中默認的是private。3,構造函數(shù)最重要的作用是創(chuàng)建對象的本身,C+中每個類可以擁有多個構造函數(shù),但必須至少有一個構造函數(shù),當一個類中沒有顯

48、式提供任何構造函數(shù),C+編輯器自動提供一個默認的不帶參數(shù)的構造函數(shù),這個默認的構造函數(shù)只負責構造對象,不做任何初始化工作。但在一個類中只要自己定義一個構造函數(shù),不管帶參不帶參,編輯器不再提供默認的不帶參的構造函數(shù)了。構造函數(shù)沒有返回值。4,析構函數(shù)當一個對象生命周期結束時候被調用來回收對象占用的內(nèi)存空間。一個類只需有一個析構函數(shù)。析構函數(shù)沒有返回值也不的帶參數(shù)。5,析構函數(shù)的作用與構造函數(shù)相反,對象超出起作用范圍對應的內(nèi)存空間被系統(tǒng)收回,或被程序用delete刪除的時候,對象的析構函數(shù)被調用。6,函數(shù)的重載條件:函數(shù)的參數(shù)類型、個數(shù)不同,才能構成函數(shù)的重載。重載是發(fā)生在同一個類中。7,類是抽象

49、的,不占用具體物理內(nèi)存,只有對象是實例化的,是占用具體物理內(nèi)存的。8,this指針是隱含指針,指向對象本身(this指針不是指向類的),代表了對象的地址。所有的對象調用的成員函數(shù)都是同一代碼段,但每個對象都有自己的數(shù)據(jù)成員。當對象通過調用它的成員函數(shù)來訪問它的數(shù)據(jù)成員的時候,成員函數(shù)除了接收實參外,還接收了對象的地址,這個地址被一個隱藏的形參this所獲取,通過這個this指針可以訪問對象的數(shù)據(jù)成員和成員函數(shù)。9,對象中public屬性的成員在外部和子類中都可以被訪問;protected屬性的成員在外部不能被訪問,在子類中是可以訪問的;private屬性在子類中和外部都不能被訪問。10,類的繼

50、承訪問特性:(public,protected,private)a)基類中private屬性成員,子類無論采用那種繼承方式都不能訪問。b)采用public繼承,基類中的public,protected屬性的成員訪問特性在子類中仍然保持一致。c)采用protected繼承,基類中的public,protected屬性成員訪問特性在子類中變?yōu)閜rotected.d)采用private繼承,基類中的public,protected屬性成員訪問特性在子類中變?yōu)閜rivate.11,子類和基類的構造函數(shù)或析構函數(shù)調用順序:當調用子類的構造函數(shù)時候先調用基類的構造函數(shù)(如果沒有指明,則調用基類卻省那個不帶

51、參數(shù)的構造函數(shù);如果要指明則在子類構造函數(shù)名后加":基類名(參數(shù))")。析構函數(shù)則相反,先調用子類析構函數(shù),后調用基類的析構函數(shù)。12,函數(shù)的覆蓋:函數(shù)的覆蓋是發(fā)生在發(fā)生父類和子類之間的。(函數(shù)的重載是發(fā)生在同一個類中)當子類中重寫了父類的某些成員函數(shù)后,子類中的成員函數(shù)覆蓋了父類的對應同名成員函數(shù)。13,用父類指針訪問子類對象成員時候,只能訪問子類從父類繼承來的那部分。(這時候外部不可以訪問父類中保護和私有的部分,子類中不可訪問父類私有部分。)14,多態(tài)性:在基類的的成員函數(shù)前加virturl變成虛函數(shù),當用子類對象調用該功能的成員函數(shù)時候,子類有的就調用子類的,子類沒有

52、的就調用基類的。當C+編譯器在編譯的時候,發(fā)現(xiàn)被調用的成員函數(shù)在基類中定義的是虛函數(shù),這個時候C+就會采用遲綁定技術(late binding),在運行的時候,依據(jù)對象的類型來確定調用的哪個函數(shù),子類有調用子類的,子類沒有的就調用基類的。如果基類中的成員函數(shù)不是虛函數(shù),則這時候的綁定是早期綁定,在編譯的時候就已經(jīng)確定該調用哪個函數(shù)。15,純虛函數(shù):在類中定義時 eg: virtual void func1()=0;純虛函數(shù)沒有函數(shù)體,含有純虛函數(shù)的類叫做抽象類,抽象類不能實例化對象。當子類從抽象類的基類中派生出來時候,如果沒有實現(xiàn)基類中的純虛函數(shù),則子類也是個抽象類,也不能實例化對象。純虛函數(shù)

53、被標名為不具體實現(xiàn)的虛成員函數(shù),純虛函數(shù)可以讓類只具有操作的名稱而不具有具體的操作的內(nèi)容,讓派生類在繼承的時候再給出具體的定義。如果派生類沒有給出基類的純虛函數(shù)的具體定義的時候,派生類也為一個抽象類,也不能實例化對象。16,引用:變量的別名。引用需要在定義的時候用一變量或對象初始化自己。引用一旦在定義的時候初始化,就維系在一個特定的變量或對象上。引用不占用物理內(nèi)存(與定義引用的目標共用同一內(nèi)存)。指針變量需要占用物理內(nèi)存,用來存儲地址。 (3)MFC程序框架的剖析 1,尋找WinMain人口:在安裝目錄下找到MFC文件夾下的SRC文件夾,SRC下是MFC源代碼。路徑:MFC

54、|SRC|APPMODUL.CPP:_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) / call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);注意:(#define _tWinMain   WinMain)2,對于全局對象或全局變量來說,在程序運行即WINMAIN函數(shù)加載的時候,已經(jīng)為全

55、局對象或全局變量分配了內(nèi)存和賦初值。所以:CTEApp theApp;->CTEApp :CTEApp()->_tWinMain()說明:每一個MFC程序,有且只有一個從WinApp類派生的類(應用程序類),也只有一個從應用程序類所事例化的對象,表示應用程序本身。在WIN32程序當中,表示應用程序是通過WINMAIN入口函數(shù)來表示的(通過一個應用程序的一個事例號這一個標識來表示的)。在基于MFC應用程序中,是通過產(chǎn)生一個應用程序對象,用它來唯一的表示了應用程序。3,通過構造應用程序對象過程中調用基類CWinApp的構造函數(shù),在CWinApp的構造函數(shù)中對程序包括運行時一些初始化工作

56、完成了。CWinApp構造函數(shù):MFC|SRC|APPCORE.CPPCWinApp:CWinApp(LPCTSTR lpszAppName)./帶參數(shù),而CTEApp構造函數(shù)沒有顯式向父類傳參,難道CWinApp()有默認參數(shù)?見下:(在CWinApp類定義中, CWinApp(LPCTSTR lpszAppName = NULL); )注意:CWinApp()函數(shù)中:pThreadState->m_pCurrentWinThread = this;pModuleState->m_pCurrentWinApp = this(this指向的是派生類CTEApp對象,即theApp)

57、調試:CWinApp:CWinApp();->CTEApp theApp;(->CTEApp :CTEApp())->CWinApp:CWinApp()->CTEApp :CTEApp()->_tWinMain()4,_tWinMain函數(shù)中通過調用AfxWinMain()函數(shù)來完成它要完成的功能。(Afx*前綴代表這是應用程序框架函數(shù),是一些全局函數(shù),應用程序框架是一套輔助生成應用程序的框架模型,把一些類做一些有機的集成,我們可根據(jù)這些類函數(shù)來設計自己的應用程序)。AfxWinMain()函數(shù)路徑:MFC|SRC|WINMAIN.CPP:在AfxWinMain(

58、)函數(shù)中:CWinApp* pApp = AfxGetApp();說明:pApp存儲的是指向WinApp派生類對象(theApp)的指針。/_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()/ return afxCurrentWinApp; 調用pThread->InitInstance()說明:pThread也指向theApp,由于基類中virtual BOOL InitApplication()定義為虛函數(shù),所以調用pThread->InitInstance()時候,調用的是派生類CTEApp的InitInstance()函數(shù)。nReturn

59、Code = pThread->Run();說明:pThread->Run()完成了消息循環(huán)。5,注冊窗口類:AfxEndDeferRegisterClass();AfxEndDeferRegisterClass()函數(shù)所在文件:MFC|SRC|APPCORE.CPPBOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister).說明:設計窗口類:在MFC中事先設計好了幾種缺省的窗口類,根據(jù)不同的應用程序的選擇,調用AfxEndDeferRegisterClass()函數(shù)注冊所選擇的窗口類。調試:CWinApp:CWinApp();-&

60、gt;CTEApp theApp;(->CTEApp :CTEApp())->CWinApp:CWinApp()->CTEApp :CTEApp()->_tWinMain()/進入程序->AfxWinMain();->pApp->InitApplication();->pThread->InitInstance()/父類InitInstance虛函數(shù);->CTEApp:InitInstance()/子類實現(xiàn)函數(shù);->AfxEndDeferRegisterClass(LONG fToRegister)/注冊所選擇的窗口類(出于文檔

61、管理,注冊提前,正常的應在PreCreateWindow中進行注冊)/之后進入創(chuàng)建窗口階段(以下再不做調試)6,PreCreateWindow():/主要是注冊窗口類BOOL CMainFrame:PreCreateWindow(CREATESTRUCT& cs) if( !CFrameWnd:PreCreateWindow(cs) )  return FALSE; return TRUE;說明:CFrameWnd:PreCreateWindow()函數(shù)所在文件:MFC|SRC|WINFRM.CPPBOOL CFrameWnd:PreCreateWindo

62、w(CREATESTRUCT& cs) if (cs.lpszClass = NULL)   VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);   /判斷AFX_WNDFRAMEORVIEW_REG型號窗口類是否注冊,如果沒有注冊則注冊  cs.lpszClass = _afxWndFrameOrView;  / COLOR_WINDOW background   /把注冊后的窗口類名賦給cs.lpszClass  if

63、 (cs.style & FWS_ADDTOTITLE) && afxData.bWin4)  cs.style |= FWS_PREFIXTITLE; if (afxData.bWin4)  cs.dwExStyle |= WS_EX_CLIENTEDGE; return TRUE;其中:virtual BOOL PreCreateWindow(CREATESTRUCT& cs);/PreCreateWindow()是個虛函數(shù),如果子類有則調用子類的。#define VERIFY(f)   

64、       ASSERT(f)#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)define AFX_WNDFRAMEORVIEW_REG          0x00008const TCHAR _afxWndFrameOrView = AFX_WNDFRAMEORVIEW;/WINCORE.CPP文件中,定義為全局數(shù)組。/#define AFX_WNDF

65、RAMEORVIEW  AFX_WNDCLASS("FrameOrView")7,創(chuàng)建窗口:Create()函數(shù)路徑:MFC|SRC|WINFRM.CPP:CFrameWnd:Create(.) . CreateEx(.);/從父類繼承來的,調用CWnd:CreateEx(). .CWnd:CreateEx()函數(shù)路徑:MFC|SRC|WINCORE.CPPBOOL CWnd:CreateEx(.) . if (!PreCreateWindow(cs)/虛函數(shù),如果子類有調用子類的。   PostNcDestroy();  return FALSE;  . HWND hWnd = :CreateWindowEx(cs.dwExStyle, cs.lpszClass,  cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,  cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCr

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論