日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MFC 学习的基本概念

發布時間:2025/4/5 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MFC 学习的基本概念 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

這些都是由于WINDOWS具有的事件驅動的屬性造成的。比如說當你按下鍵盤的字符鍵的時候,消息隊列就會向程序發送WM_CHAR的消息,如果你所寫的程序中含有處理這個消息的函數,程序就會執行它(比如在屏幕上顯示出來)。 為了更好的了解WINDOWS編程,這里Gilbert要總結幾個基本的概念: 1.句柄: 它是WINDOWS編程的基礎。一個句柄是指WINDOWS在內存中使用的一個唯一的整數質,是一個4個字節長的數值,用于標識應用程序中不同對象和相同對象的不同實例。 幾種WINDOWS常用的句柄: HWND: 標示窗口句柄 HINSTANCE:標示當前實例句柄 HCOURSOR:標示光標句柄 HFONT: 標示字體句柄 HPEN:標示畫筆句柄 HBRUSH:標示畫刷句柄 HDC:標示設備環境句柄 HBITMP:標示位圖句柄 HICON:標示圖標句柄 HMENU:標示菜單句柄 HFILE:標示文件句柄

說的確切一點,句柄實際上是一種指向某種資源的指針,但與指針又有所不同:指針對應著一個數據在內存中的地址,得到了指針就可以自由地修改該數據。 Windows并不希望一般程序修改其內部數據結構,因為這樣太不安全。所以Windows給每個使用GlobalAlloc等函數聲明的內存區域指定一個句柄(本質上仍是一個指針,但不要直接操作它),平時你只是在調用API函數時利用這個句柄來說明要操作哪段內存。當你需要對某個內存進行直接操作時,可以使用GlobalLock鎖住這段內存并獲得指針來直接進行操作。

?

2.消息: 由于WINDOWS應用程序利用WINDOWS消息來與其它的WINDOWS應用程序及WINDOWS系統進行消息交換。所以消息是一個十分重要的對象,它的結構如下: typedef struct { HWND hwnd; //檢索消息的窗口句柄 UNIT message; //代表一個消息的消息質 WPARAM wParam; //消息附加信息的字參數 LPARAM lParam; //消息附加信息的長字參數 DWORD time; //消息入隊時間 POINT pt; //消息發送時鼠標的位置 point.x;point.y; } tagMSG; VC 中消息用不同的前綴標示消息所屬的分類,一些前綴為: BM表示按鈕控制消息 CB表示組合框控制消息 DM表示默認下壓式按鈕控制消息 EM表示編輯控制消息 LB表示列表框控制消息 SBM表示滾動條控制消息 WM表示窗口消息 對常用的窗口消息進行說明: WM_LBUTTONDOWN: 單擊鼠標左鍵時產生 WM_LBUTTONUP: 放開鼠標左鍵時產生 WM_RBUTTONUP: 放開鼠標右鍵時產生 WM_LBUTTONBLCLK: 雙擊鼠標左鍵時產生 WM_RBUTTONBLCLK: 雙擊鼠標右鍵時產生 WM_KEYDOWN: 按下了一個非系統鍵時產生的消息 WM_CHAR: 同上 WM_CREATE: 由CreateWindow函數發出的消息 WM_DESTROY: 消除窗口時發出的消息 WM_QUIT: 退出程序時發送的消息 WM_PAINT: 做任何移動操作時發出的消息 3.WinMain WINDOWS API 程序的由入口函數WinMain和窗口函數是WINDOWS應用程序的主體。 一個基本的WinMain函數應該具有以下的功能: 1.注冊窗口類,建立窗口及執行其他必要的初始化工作 2.進入消息循環,根據從應用程序消息隊列接受的消息,調用相應的處理過程 3.當消息循環檢索到WM_QUIT消息時中止程序運行 WinMain函數有三個基本組成部分:函數說明、初始化和消息循環。 (1)函數說明 int WINAPI WinMain { HINSTANCE hThisInst, //應用程序當前實例句柄 HINSTANCE hPrevInst, //應用程序其它實例句柄 LPSTR lpszCmdLine, //指向程序命令行參數的指針 int nCmdShow //應用程序開始執行時窗口顯示方式的整數值標示 } (2)初始化 初始化包括窗口類的定義、注冊、創建窗口實例和顯示窗口四部分。 (3)消息循環 WINDOWS應用程序的運行是以消息為核心的。WINDOWS將產生的消息放入應用程序的消息隊列中,而應用程序的WinMain函數從消息循環提取隊列中的消息,并將其傳遞給窗口函數的相應過程處理。 它的基本寫法如下: MSG Meg;//定義消息 //(...)省略了一些內容 while (GetMessage(&Meg,NULL,0,0) { TranslanteMessage(&Meg);//將虛擬鍵消息轉換為字符消息 DispatchMessage(&Meg);//該函數調度一個消息給窗口程序Wndproc() } 4.簡述下windows消息處理機制: 首先系統(也就是windows)把來自硬件(鼠標, 鍵盤等消息)和來自應用程序的消息放到一個系統消息隊列中去. 而應用程序需要有自己的消息隊列, 也就是線程消息隊列, 每一個線程有自己的消息隊列, 對于多線程的應用程序就有和線程數目相等的線程消息隊列. windows消息隊列把得到的消息發送到線程消息隊列, 線程消息隊列每次取出一條消息發送到指定窗口,不斷循環直到程序退出.這個循環就是靠消息環(while(GetMessage()) TranslateMessage(); DispatchMessage();)實現的. GetMessage()只是從線程消息中取出一條消息,而DispatchMessage將消息傳遞給窗口函數Wndproc, 窗口函數就會對照事先由程序編寫好的消息對照表調用對應的方法來處理消息, Wndproc里大致是這樣的:
? LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM)
{ //使用SWITCH語句將各種消息分開 switch(uMessageType) { case(WM_PAINT): doYourWindow(...);//在窗口需要重新繪制時進行輸出 break; case(WM_LBUTTONDOWN): doYourWork(...);//在鼠標左鍵被按下時進行處理 break; default: callDefaultWndProc(...);//對于其它情況就讓系統自己處理 break; } } 為什么這么麻煩?因為這樣windows就可以知道你的程序運行到什么情況了,windows來調用你的窗口,這樣你的窗口返回的時候windows就知道你已經處理過一個消息了,如果沒有新的消息進入消息隊列windows就不再會給你的進程分配時間片如果是你自己寫switch的話,windows就不可能這樣靈活的分配時間資源利用率就會降低。那么還要消息循環干什么,windows直接把消息發給窗口不就可以了嗎? 因為你要在消息循環里把KEY_DOWN和KEY_UP組合成WM_CHAR,還可以直接屏蔽掉許多對你來說無用的消息,加快速度。 5.MFC機制 CWinApp和CFrameWnd分別代替了WIN32 APPLICATION編程中的WinMain和WndProc兩個函數。CWinApp類封裝了與應用程序啟動,消息循環和程序結束等相關功能;CFrameWnd 類封裝了窗口創建,消息處理和窗口銷毀等功能。

單從概念上講,句柄指一個對象的標識,而指針是一個對象的首地址。從實際處理的角度講,即可以把句柄定義為指針,又可以把它定義為同類對象數組的索引,這兩種處理方法都有優缺點,至于選用哪種方式,完全應該看實際需要,這可以說是一種程序設計上的技巧。那種單純認為句柄是指針或索引的想法都是機械的、不確切的。

  其實,在Windows中類似的處理是很多的、很靈活的。再舉個相似的例子:

  我們知道,在Windows中有個函數叫做CallWindowProc。顧名思義,它的作用就是向指定的窗口過程傳遞一個消息。你也許會想,既然我已經有了窗口過程的指針,為什么我不可以直接通過這個指針調用該函數(這是C語言的內建功能)?事實上,在Win16中確實可以這么做,因為GetWindowLong返回的確實是該函數的指針。但在Win32下,GetWindowLong返回的并不是該函數的指針,而是一個包含函數指針的數據結構的指針(MSDN上說返回的是一個窗口函數地址或它的句柄,就是指的這種情況)。該數據結構是可變的,但只要你使用CallWindowProc來調用的話是不會出錯的。這里我們又看到使用句柄處理帶來的好處。(補充說明一點:微軟在這里之所以這么處理,是為了解決16位/32位以及ANSI/UNICODE的轉化問題)

編輯本段解疑

定義

  句柄是什么?

  在windows中,句柄是和對象一一對應的32位無符號整數值。對象可以映射到唯

  一的句柄,句柄也可以映射到唯一的對象。

用途

  為什么我們需要句柄?

  更準確地說,是windows需要句柄。windows需要向程序員提供必要地編程接口

  ,在這些接口中,允許程序員訪問、創建和銷毀對象。但是,出于封裝地考慮,wi

  ndows并不想向程序員返回指針。指針包含了太多的信息。首先指針給出了對象存儲

  的確切位置;其次,要操作一個指針,程序員必須知道指針所指對象的內部結構特

  征,也即,windows必須向程序員暴露相應的數據結構,而這些數據結構也許是操作

  系統想向程序員隱藏的。

  如果說COM技術向用戶隱藏了數據,只暴露了接口并只允許按接口定義的方法操

  作數據的話,句柄這種方式則允許你按自己的方式直接操作數據,但windows又不向

  你直接暴露數據。直接操作數據是程序員需要的,不暴露數據是windows所需要的,

  句柄封裝方式實現了各取所需。

映射

  句柄如何與對象映射

  封裝背后,必須有一個地方可以實現解碼,以實現句柄和對象的相互轉換。在

  windows中,存在兩種映射方式:

  a. 全等映射。也即,句柄本身就是一個指針。映射在這里只是類型轉換而已。

  這種情況有,進程實例句柄或模塊句柄,以及資源句柄等等。

  b. 基于表格的映射。這是對象指針與句柄之間最普通的映射機制。操作系統創

  建表格,并保存所有要考慮的對象。需要創建新對象時,要先在表格中找到空入口

  ,然后把表示對象的數據添入其中。當對象被刪除時,它的數據成員和其在表中的

  入口被釋放。

實現

  句柄的定義和實現

  我們以GDI對象為例進行討論。創建了GDI對象,就會得到該對象的句柄。句柄

  的對象可能是HBRUSH、HPEN、HFONT或HDC中的一種,這依賴于你創建 的GDI對象類

  型。但是最普通的GDI對象類型是HGDIOBJ。HGDIOBJ被定義成空指針。

  HPEN的實際編譯類型定義隨編譯時間宏STRICT的不同而不同。如果STRCIT已經

  被定義了,HPEN是這樣的:

  struct HPEN__ {int unused};

  typedef struct HPEN__ HPEN;

  如果STRICT沒有定義,HPEN是這樣定義的:

  typedef void HANDLE;

  typedef HANDLE HPEN;

  上面這段代碼是一個注重細節的程序員最接近句柄的地方,因此我們重點分析

  一下。這里有一點點技巧。如果定義了STRICT宏,HPEN是指向有單個未使用字段的

  結構的指針,否則HPEN是空指針。C/C++編譯器允許把任何類型的指針作為空指什傳

  遞,反之則不可以。兩個不同類型的非空指針是互不兼容的。在STRICT版本中,編

  譯對GDI對象句柄的不正確混用將給出警告,對于非GDI句柄,如HWND、HMENU的不正

  確混用也會給出警告,從而使程序在編譯器得到更STRICT的檢查。

  接下來的分析可能不那么令你感興趣,但它更深刻地揭示了句柄。對GDI句柄來

  說,盡管windows頭文件把它定義成指針,但如果你仔細檢查這些句柄的值,它根本

  就不像指針,這也是為什么我說它只是一個32位無符整數值的原因。對句柄就是指

  針的情況,這句話也仍然適用。讓我們隨意地生成一些句柄,比如你用GetStockOb

  ject()以得到一些句柄,你會發現,它們的值總在區間0x01900011到0xba040389。

  前者指向用戶區中的未分配的無效區域,后者指向內核地址空間。另外你可能發現

  ,兩個句柄之間的值可能只差數值1,這也說明GDI句柄不是指針。

  和多數人想象的不一樣,句柄也不是一個單純的索引值。對GDI對象句柄來說,

  GDI句柄由8位 、1位堆對象標記(表明對象是否創建在堆中)、7位對象類型信息和

  高4位為0的16位索引組成,如:

  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0

  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0

  | 8 位引用計數 |堆 | 對象類型7 | 16位索引 |

  標

  記

  在這里你可以看到,對GDI來說,它只使用了16位作為索引。這意味著一個進程最多只

  可以創建小于64K個句柄,實際上受其他一些限制,整個Windows系統中大概可以容納約

  16384(0x4000)個GDI對象。

轉載于:https://blog.51cto.com/lscheng/629979

總結

以上是生活随笔為你收集整理的MFC 学习的基本概念的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。