最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

【滴水基礎(chǔ)】5.MFC(3)

2023-06-04 20:54 作者:沙漠里的鯨  | 我要投稿

第十:GDI基礎(chǔ)概念和MFC的CDC類

#GDI圖形設(shè)備(Graphics Device InterFace)

---和Win32Api類似,為應(yīng)用程序提供了可調(diào)用的多種服務(wù),這些服務(wù)構(gòu)成了強大、通用的圖形編程語言

#DC圖形描述表(同時表示設(shè)備上下文)

---Windows程序在屏幕、打印機、其它輸出設(shè)備上畫圖時,并不是將像素直接輸出到設(shè)備上

---而是將圖先繪制到設(shè)備描述表(內(nèi)存設(shè)備dc)表示的邏輯意義上的顯示平面上去

---它是Windows中的一種數(shù)據(jù)結(jié)構(gòu),包含了GDI需要的所有有關(guān)于顯示平面情況的描述

---早期的圖形開發(fā),是針對具體的設(shè)備開發(fā)(如:根據(jù)打印機廠家提供的不同接口開發(fā)不同的代碼),需要適配不同的顯卡,造成開發(fā)者困難

---Windows通過驅(qū)動管理,將設(shè)備接口細節(jié)隱藏在OS內(nèi)部,我們只需要針對一個:公有的虛擬設(shè)備DC

#MFC不同場景下的DC類

---MFC的CDC類,將DCHDC(句柄:可以操作所有DC有關(guān)的GDI函數(shù))的GDI函數(shù)封裝到了一起,派生了四個不同場景的DC類,以下是常用的3個

---注意:OnPaintON_WM_PAINT消息的響應(yīng)函數(shù),當(dāng)窗口進行某些特定操作引起窗口重繪時,會發(fā)送WM_PAINT消息

---系統(tǒng)會在多個不同的時機發(fā)送WM_PAINT消息:當(dāng)?shù)谝淮蝿?chuàng)建一個窗口時,當(dāng)改變窗口的大小時,當(dāng)把窗口從另一個窗口背后移出時,當(dāng)最大化或最小化窗口時等等

---大多數(shù)的時候應(yīng)用也需要能夠主動引發(fā)窗口中的繪制操作,比如當(dāng)窗口顯示的數(shù)據(jù)改變的時候,這一般是通過InvalidateRect和InvalidateRgn函數(shù)來完成的。

---ON_WM_PAINT可以捕獲此消息,并自己調(diào)用OnPaint()函數(shù)來實現(xiàn)對某些要素圖形的重新繪制

---當(dāng)然,視頻里面省略了一個

#在消息響應(yīng)函數(shù)的基礎(chǔ)上,區(qū)分Win32Api和MFC

---如果是傳統(tǒng)的Win32Api的調(diào)用,分為設(shè)備對象(窗口),設(shè)備上下文(內(nèi)存),圖形對象

---通過設(shè)備對象獲取窗口的設(shè)備上下文,然后自定義圖形對象

---最后,將圖形對象和設(shè)備上下文關(guān)聯(lián),調(diào)用WinApi進行繪圖

---繪制圖形如下(這個只能顯示一次,而窗口是不停的繪制、渲染)
---這也是為什么上面MFC要利用dc對象來進行畫圖

#MFC的窗口句柄

---哪如何獲得窗口類的自己的句柄呢?有如下方法:
---1、this->m_hWnd; ????????????//成員變量
---2、GetSafeHwnd(); ????????????//成員方法
---3、AfxGetMainWnd()->m_hWnd;

#在MFC里面模擬Win32Api的調(diào)用

---Hello.h

---hello.cpp:為什么OnPaint()里面調(diào)用:BeginPaint(m_hWnd,&ps)和EndPaint(m_hWnd,&ps)?

---BeginPaint函數(shù)的作用是告訴Windows系統(tǒng),要開始向顯示卡輸出內(nèi)容了,把這次顯示的操作請求放到系統(tǒng)顯示隊列里。

---由于系統(tǒng)上的顯示卡往往只有一個,那么這種資源是獨占的,所以操作系統(tǒng)會讓顯示操作線性化,保證每個窗口的顯示是獨立進行的,而不是A窗口顯示一部份,或者B窗口顯示一部份,而是A窗口顯示完成后再讓B窗口顯示

---因此,BeginPaint函數(shù)就是跟操作系統(tǒng)說,我需要顯示了,你安排好吧。當(dāng)BeginPaint返回時,就獲取到系統(tǒng)的顯示資源句柄,這樣就可以調(diào)GDI一大堆函數(shù)來操作了

---顯示完成后,一定要記得調(diào)用函數(shù)EndPaint,因為使用BeginPaint函數(shù)請求了獨占的顯示資源后,如果不釋放回去,就會讓其它程序永遠獲取不到顯示資源了,這樣系統(tǒng)就死鎖了

---應(yīng)用程序除了響應(yīng)WM_PAINT消息外,不應(yīng)該調(diào)用BeginPaint

---效果如下

---點擊鼠標(biāo)左鍵

---上面是Win32Api進行的操作,如果替換為MFC封裝的DC類

---效果如下

#設(shè)備描述表的屬性(重要)

---例如,修改字體的顏色

---效果如下

#鼠標(biāo)左鍵點擊,畫一個黃色的矩形

---pen(1,2,3)相當(dāng)于CreatePen(1,2,3)

---代碼如下

---效果如下

---總結(jié)

第十一:WindowsGDI

#GDI的映射模式

---映射模式是設(shè)備描述表的屬性,用于確定邏輯坐標(biāo)值(內(nèi)存)到設(shè)備坐標(biāo)值(顯示屏)的轉(zhuǎn)換(設(shè)備坐標(biāo)值:窗口中相對應(yīng)的像素位置

---傳遞給CDC(CDC封裝了HDC和DC有關(guān)的函數(shù))輸出函數(shù)的邏輯坐標(biāo)值,然后被轉(zhuǎn)換為設(shè)備坐標(biāo)值

---通過CDC::SetMapMode來進行設(shè)置邏輯設(shè)備到設(shè)備坐標(biāo)的映射方式

#映射模式的nMapMode取值與含義

符號常量 ????????????????數(shù)字常量 ????????????x方向 ????????? y方向 ????????邏輯單位的大小
MM_TEXT ????????????????????1 ????????????向右(默認(rèn))向下(默認(rèn)) ??? ??????? 像素
MM_LOMETRIC ?????????? 2 ?????????????????? 向右 ????????? 向上 ????????????????????0.1 mm
MM_HIMETRIC ????????????3 ?????????????????? 向右 ????????? 向上 ????????????????????0.01 mm
MM_LOENGLISH ???????? 4 ?????????????????? 向右 ????????? 向上 ????????????????????0.01 in
MM_HIENGLISH ????????? 5 ?????????????????? 向右 ????????? 向上 ????????????????????0.001 in
MM_TWIPS ????????????????? 6 ????????????????????向右???????????? 向上 ????????????????1/1440 in ?
MM_ISOTROPIC ????????? 7 ????????????????????自定義 ????? 自定義 ????????????????????自定義
MM_ANISOTROPIC ???? 8 ????????????????????自定義 ????????自定義 ????????????????? 自定義

#設(shè)備空間下的坐標(biāo)

---1.客戶區(qū)坐標(biāo) 2.屏幕坐標(biāo) 3.全窗口坐標(biāo)

#GDI坐標(biāo)空間

---Windows程序利用坐標(biāo)空間轉(zhuǎn)換來對圖形輸出進行縮放、旋轉(zhuǎn)、平移、斜切、反射等

---坐標(biāo)空間是一個平面的空間,通過互相垂直的XY軸來定位二維對象

#Win32Api使用4種坐標(biāo)空間

---在窗口的ON_WM_PAINT()消息的響應(yīng)函數(shù)OnPaint()中

---繪制圓形

---這里的映射模式是默認(rèn)的以像素為映射:MM_TEXT

---如果將映射模式設(shè)置為:MM_LOMETRIC(修改的是邏輯坐標(biāo)的單位)

---一個邏輯單位:0.1毫米,x和y軸方向:x+y-

---效果如下

---映射模式的修改優(yōu)點:與物理設(shè)備無關(guān)如顯示器,不同的屏幕具有不同的分辨率

---獲取客戶區(qū)的邏輯坐標(biāo),使得圓形鋪滿整個窗口

---圓形可以鋪滿整個窗口,但是一旦放大窗口,就會變成橢圓

---可以通過修改映射模式進行自適應(yīng),發(fā)現(xiàn)放大了之后,圓也不會變成橢圓

---將映射模式改為:MM_ANISOTROPIC,發(fā)現(xiàn)邏輯單位還是1個像素點,但是放大之后,就會變成橢圓

---通常情況下SetWindowExt()函數(shù)和SetViewportExt()函數(shù)成對調(diào)用(我這里在網(wǎng)上找了一個例子)

---在X軸方向,每個邏輯單位有 1024 / 10240 個像素,

---而在Y軸方向,每個邏輯單位有 768 / 7680 個像素

#總結(jié)

#對應(yīng)鼠標(biāo)左鍵點擊消息ON_WM_LBUTTONDOWN()對應(yīng)的響應(yīng)函數(shù):OnLButtonDown(UINT nFlags,CPoint point)

---這里就是在以鼠標(biāo)點擊的點為源點(設(shè)備坐標(biāo)),然后畫矩形

---效果如下

---我們設(shè)置映射模式,將原本的默認(rèn)的映射,改為:MM_LOMETRIC

---:一個邏輯單位=0.1毫米,x軸y軸方向:X+Y-

---效果如下:

#先設(shè)置CMianWindow主窗口的范圍(0,0,515,540)

---發(fā)現(xiàn)畫一個(0,0,500,500)的圓形正好在中間

---現(xiàn)在更改窗口的原點,改為邏輯坐標(biāo)的(100,100)

#窗口和視口的繪圖

---窗口中的坐標(biāo)都是邏輯坐標(biāo),視口中的坐標(biāo)都是設(shè)備坐標(biāo)。我們的繪圖語句(dc的成員函數(shù))中用的坐標(biāo)都是邏輯坐標(biāo)

---這里窗口的原點,變成了邏輯坐標(biāo)的(100,100),截取了一個小正方形,并且會補充一部分的空白

--而窗口到視口的映射方式?jīng)]有變化,所以顯示是部分的圓

---如果改為

---效果如下圓形直接顯示完全

---背后的原理如下:先創(chuàng)建窗口,然后在窗口中繪制(100,100,500,500)的圓形

---在邏輯坐標(biāo)畫好之后,截?。?00,100)為原點的部分

---更改視口

---效果如下:

---原理分析:將窗口的映射到視口上,由于在邏輯坐標(biāo)上,窗口是完整的,所以圓形不會缺失(大?。?00,500)

---但是視口上,只有(400,400)來接受映射會舍棄一部分,所以視口原點在原來的視口基礎(chǔ)上,變成了原來視口的坐標(biāo)位置的(100,100)開始

---總結(jié):

---要更改 窗口/視口 原點,就在原來 窗口/視口 坐標(biāo)系的基礎(chǔ)上,進行 窗口/視口原點定位

---然后進行投影,沒有投影到的部分,就是空白區(qū)域

#頁面控件到設(shè)備空間的轉(zhuǎn)換

---根據(jù)映射方式來確定繪圖操作單位大小的一種度量轉(zhuǎn)換

第十二:GDI繪圖

#常用的繪圖函數(shù)

---:MoveTo:在畫線前設(shè)定當(dāng)前的位置(指定起始)

---:LineTo:從當(dāng)前位置畫1條線到指定位置(指定指定終止)

---:Polyline:將一系列的點用線段連接起來(無需指定起始位置)

---:PolylineTo:從當(dāng)前位置開始,將一系列點用線段連接起來(需要指定起始位置)

---:Elipse:畫圓或者畫橢圓

---:Rectangle:畫一個帶直角的矩形

---:FillRect:用指定畫刷填充矩形

---:Draw3dRect:實現(xiàn)3D立體感

---效果如下

---也可以通過Polyline將一系列的點進行連接

---當(dāng)然也可以PolylineTo函數(shù),需要設(shè)定起始位置,但是和Polyline沒有本質(zhì)的區(qū)別

---效果如下

---系統(tǒng)中的畫刷、畫筆、字體等,可以自己創(chuàng)建并設(shè)計,也可以使用系統(tǒng)內(nèi)置的

---CreateStockObject表示使用系統(tǒng)內(nèi)置,LTGRAY_BRUSH是一個內(nèi)置宏

---Windows的系統(tǒng)預(yù)定義的畫刷如下

---CreateStockObject的優(yōu)點:無需用dc.SelectObject()去更換畫刷對象

---效果如下:

#如果鼠標(biāo)點擊在矩形內(nèi),就修改窗口名稱

---效果如下,點擊矩形內(nèi),窗口名改為:yes,點擊其它區(qū)域,窗口名:no

---如果想改變矩形邊框的顏色,風(fēng)格,可以使用pen

---對于畫筆、畫刷等圖形對象,在MFC中GDI的函數(shù)中可以使用:SelectObject()函數(shù)加載,并且返回了原來的圖形對象,可以在后面加載原來的圖形對象

---為什么要保存原來的圖形對象:因為GDI沒有異常機制,載入自定義的pen之后,在退出的時候,先調(diào)用的默認(rèn)pen的析構(gòu)函數(shù),再調(diào)用dc的析構(gòu)函數(shù)

---但是dc里面存在的是自定義的pen,而默認(rèn)的pen已經(jīng)優(yōu)先釋放了,所以會產(chǎn)生異常

---設(shè)置字體的大小,風(fēng)格

---效果如下

---更大范圍的更改字體:通過LOGFONT結(jié)構(gòu)體來進行更大范圍的字體的傳參

---效果如下:

---帶陰影的字體:

---效果如下

#作業(yè)

---用GDI繪制一個excel: Draw3dRect; FillRect; 填充之后畫像

---注意我的主窗口大小

---思路:先兩點連線,畫出表格

---然后自定義畫筆,畫刷,填充橫軸、縱軸的區(qū)域

---效果如下:

第十三:鼠標(biāo)消息

#Windows鼠標(biāo)消息

---Windows有20多種不同的消息,用來報告與鼠標(biāo)有關(guān)的輸入事件

---這些消息分為:客戶消息非客戶消息,我們只需要關(guān)注客戶消息(知識點:理解客戶消息和非客戶消息)

#客戶區(qū)域的鼠標(biāo)消息

#按下鼠標(biāo)左鍵輸出鼠標(biāo)點擊的坐標(biāo)(注意:point是物理的設(shè)備坐標(biāo)

---效果如下:

#鼠標(biāo)移動并且按下鼠標(biāo)左鍵才能顯示坐標(biāo)

---定義的鼠標(biāo)消息

---定義消息映射

---定義移動鼠標(biāo)的消息響應(yīng)函數(shù)

---效果如下:需要同時按3個鍵盤

#窗口的非客戶區(qū)消息

---定義非客戶區(qū)域的消息映射

---重寫映射函數(shù)

---效果如下:只有在非客戶區(qū)域才能接受消息

---自定義部分非客戶區(qū)的消息處理

---只有點擊系統(tǒng)菜單,才改變窗口的名字

#窗口在接收到客戶、非客戶區(qū)消息之前,先接受到:光標(biāo)的屏幕坐標(biāo)(很重要)

---通過 ON_WM_NCHITTEST() 確定光標(biāo)在客戶區(qū) or 不在客戶區(qū)

---在BEGIN_MESSAGE_MAP中添加ON_WM_HITTEST(),

---然后添加頭文件,重寫相應(yīng)的響應(yīng)函數(shù)

---發(fā)現(xiàn)可以像非客戶區(qū)域一樣,拖動客戶區(qū)區(qū)域

#鼠標(biāo)位置畫直線(注意不能和上面的將客戶區(qū)改為非客戶區(qū)的一起,不然只能拖到窗口)

---注意,在兩個消息處理函數(shù)之間,需要通過全局的CPoint來傳遞鼠標(biāo)的位置

---然后通過OnLButtonDown來進行初始坐標(biāo)的傳輸

---通過SetCapture/GetCapture來確保鼠標(biāo)的位置被當(dāng)前窗口捕獲(即使在窗口之外)

---利用OnLButtonUp來進行繪圖操作

---效果如下

---作業(yè)1:鼠標(biāo)畫一條紅色的直線(思路:自定義畫筆)

---效果如下

---作業(yè)2:Ctrl+鼠標(biāo)左鍵畫一個矩形

---效果如下:特點是鼠標(biāo)在窗口外面,任然可以畫

---作業(yè)3:鼠標(biāo)右鍵畫一條黃色的線條(非直線)

---思路:捕獲鼠標(biāo)光標(biāo)滑動的地址,然后將這些點通過直線連接起來,從宏觀上來看就是曲線

---思路是這樣,但是好像原點都是按下的初始點

---但是我記得LineTo之后,原點是會改變的,不知道為啥不行

第十四:鍵盤消息

---通過給擁有輸入焦點的窗口發(fā)送:WM_KEYDOWNWM_KEYUP 消息

---來報告按鈕是按下還是松開的事件,這些被稱為按擊鍵消息

---除了 ALT F10 以外的所有按鍵都產(chǎn)生按下/抬起的消息

---而 Alt F10系統(tǒng)鍵,對 Window 具有特殊的意義

#鍵盤消息

---在BEGIN_MESSAGE_MAP中,添加: ON_WM_KEYDOWN()

---部分的虛擬鍵代碼(VK_CANCEL代碼是一個虛擬鍵碼,它包括同時按下兩個鍵(Ctrl-Break))

---Backspace、Tab、Enter、Esc和空格——通常用于Windows程序。不過,Windows一般用字元訊息(而不是鍵盤訊息)來處理這些鍵

---Windows程序通常不需要監(jiān)視Shift、Ctrl或Alt鍵的狀態(tài)

---重寫消息響應(yīng)函數(shù)

---通過調(diào)試模式運行,發(fā)現(xiàn)Ctrl對應(yīng)的十進制代碼,以及之前的狀態(tài)都是抬起

---但是一直按卻沒有1的出現(xiàn)

---在DeBugView中一直按下Ctrl也沒有出現(xiàn)1,奇怪

#獲取區(qū)分大小寫的鍵盤消息,在消息映射中添加:ON_WM_CHAR()

---重寫映射函數(shù)

---效果如下:

# ON_WM_CHARON_WM_KEYDOWN 的區(qū)別

---ON_WM_CHAR是通過TranslateMessage翻譯之后,轉(zhuǎn)換為ASCII碼

---不經(jīng)過翻譯是無法識別按鍵的大小寫

---當(dāng)然,也可以判斷Shift鍵的狀態(tài)來判斷大小寫

---視頻里面'VK_A'不加''的話編譯不通過,但是加了''在調(diào)試的時候看不到輸出。不知道問題出在哪里?

#設(shè)置鍵盤消息的鉤子函數(shù):SetWindowsHookEx

#鉤子函數(shù)的定義

---鉤子(Hook),是Windows消息處理機制的一個平臺,應(yīng)用程序可以在上面設(shè)置子程以監(jiān)視指定窗口的某種消息,而且所監(jiān)視的窗口可以是其他進程所創(chuàng)建的

---當(dāng)消息到達后,在目標(biāo)窗口處理函數(shù)之前處理它。鉤子機制允許應(yīng)用程序截獲處理window消息或特定事件。

----鉤子實際上是一個處理消息的程序段,通過系統(tǒng)調(diào)用,把它掛入系統(tǒng)。每當(dāng)特定的消息發(fā)出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,

---這時鉤子函數(shù)即可以加工處理(改變)該消息,也可以不作處理而繼續(xù)傳遞該消息,還可以強制結(jié)束消息的傳遞

#鉤子函數(shù)的原理

---每一個Hook都有一個關(guān)聯(lián)的指針列表,稱之為鉤子鏈表

---這個列表的指針指向鉤子的各個處理子程序

----當(dāng)與指定的Hook類型關(guān)聯(lián)的消息發(fā)生時,系統(tǒng)就把這個消息傳遞到Hook子程

---最近安裝的鉤子放在鏈的開始,而最早安裝的鉤子放在最后,后加入的先獲得控制權(quán)

---SetWindowsHookEx()函數(shù)的最后一個參數(shù)決定了此鉤子是系統(tǒng)鉤子還是線程鉤子

----線程鉤子用于監(jiān)視指定線程的事件消息,一般在當(dāng)前線程或者當(dāng)前線程派生線程內(nèi)---

---系統(tǒng)鉤子監(jiān)視系統(tǒng)中的所有線程的事件消息。因為系統(tǒng)鉤子會影響系統(tǒng)中所有的應(yīng)用程序,所以鉤子函數(shù)必須放在獨立的動態(tài)鏈接庫(DLL)

---系統(tǒng)自動將包含“鉤子回調(diào)函數(shù)”的DLL映射到受鉤子函數(shù)影響的所有進程的地址空間中,即將這個DLL注入了那些進程

---幾點說明:

(1)如果對于同一事件(如鼠標(biāo)消息)既安裝了線程鉤子又安裝了系統(tǒng)鉤子,那么系統(tǒng)會自動先調(diào)用線程鉤子,然后調(diào)用系統(tǒng)鉤子。

(2)對同一事件消息可安裝多個鉤子處理過程,這些鉤子處理過程形成了鉤子鏈。當(dāng)前鉤子處理結(jié)束后應(yīng)把鉤子信息傳遞給下一個鉤子函數(shù)。

(3)鉤子特別是系統(tǒng)鉤子會消耗消息處理時間,只有在必要的時候才安裝鉤子,在使用完畢后要及時卸載

#掛一個全局的鍵盤鉤子(系統(tǒng)鉤子

---選擇靜態(tài)鏈接庫(VC6的版本太老了,只能選擇靜態(tài)鏈接庫)

---生產(chǎn)的靜態(tài)鏈接庫的HOOK函數(shù)如下

#思路:1.做一個導(dǎo)出函數(shù)StartHook(),由HelloMFC調(diào)用2.安裝一個鼠標(biāo)Hook,將鼠標(biāo)消息再傳輸給主程序

---在HelloMFC的hello.cpp的OnKeyDown消息響應(yīng)函數(shù)中,調(diào)用SetWindowsHookEx()函數(shù),截獲發(fā)送給鍵盤消息響應(yīng)函數(shù)的鍵盤按下消息

---在HOOKDLL.cpp中設(shè)置具體的鉤子的子程序

---設(shè)置鉤子的類型為低水平的鍵盤鉤子:WH_KEYBOAD_LL,可以看到右邊是對應(yīng)的鉤子的處理函數(shù)地址LowLevelKeyboardProc

---WH_KEYBOAD_LL的處理函數(shù)如下:

---如果 nCode 小于零,則掛鉤過程必須返回 CallNextHookEx 返回的值
---如果 nCode 大于或等于零,建議調(diào)用 CallNextHookEx 并返回返回的值

---在CallNextHookEx的功能:可以將鉤子信息傳遞到當(dāng)前鉤子鏈中的下一個子程,一個鉤子程序可以調(diào)用這個函數(shù)之前或之后處理鉤子信息。

---在HOOKDLL.cpp文件中,設(shè)定導(dǎo)出函數(shù)StartHook()

---1.先獲取窗口句柄 2.創(chuàng)建鍵盤HOOK,定義HOOK處理函數(shù) 3.在HOOK處理函數(shù)中,將hook后的信息,傳遞給鉤子鏈的下一個子鉤子

---在HOOKDLL.def將定義的StartHook函數(shù)進行導(dǎo)出

---將HOOKDLL.dll拷貝到HelloMFC的根目錄(這里是動態(tài)鏈接庫)

---在HelloMFC中,對按下F2的鍵盤消息,設(shè)置鍵盤鉤子

---在hello.h中定義函數(shù)StartHook()

---自定義Hook函數(shù),本質(zhì)是調(diào)用DLL中的StartHook函數(shù)

---傳入當(dāng)前窗口的句柄(MFC封裝了,但是源代碼封裝了m_hWnd

---在鍵盤按下消息響應(yīng)函數(shù),按下F2鍵,就調(diào)用HOOK鍵盤的消息

---HOOK成功就修改窗口名稱

---效果如下

----但是我在消息響應(yīng)函數(shù)里面彈窗,發(fā)現(xiàn)沒有報錯,但是F2沒有進行彈窗

---而且視頻里面也是在HOOKDLL.dll的hook處理函數(shù)進行判斷的(不知道為什么不能再消息響應(yīng)函數(shù)里面進行MessageBox)

---視頻里面是之間在Hook的處理函數(shù)里面LowLevelKeyboardProc函數(shù),存在3個參數(shù)

---不管HOOK成功與否,都將調(diào)用CallNextHookEx將消息傳遞給鉤子鏈的下一個HOOK

---KBDLLHOOKSTRUCT的內(nèi)容如下

---修改HOOK處理函數(shù),對攔截的消息進行預(yù)先處理

---將更新后的HOOKDLL.dll重新復(fù)制到HelloMFC,并且運行

---emmm,我這里還是沒有消息彈窗,難受

#通過自定義消息,如果HOOK成功,向主窗口發(fā)送自定義消息,然后主窗口處理

---在HelloMFC中使用:ON_MESSAGE自定義消息,傳參為自定義的消息類型,消息的響應(yīng)函數(shù)

---然后窗口接到了消息,根據(jù)第一個wParam參數(shù),判斷是否為鍵盤按下消息,如果是的話就彈窗

---我這里存在彈窗不能出現(xiàn)的問題,猜測是W11是不支持吧,建議開個虛擬機在Xp上運行VC6

---效果如下


第十五:MFC對話框

---MFC的對話框就是一個窗口,不僅可以接受消息,還可以被移動和關(guān)閉,還可以在它的客戶區(qū)域進行繪圖

---我們可以把它看成是一個大容器,在上面能夠放置各種各樣的控件,使得程序的支持用戶輸入的手段更加的豐富。

---創(chuàng)建一個MFC的exe文件

---選擇Dialog框(基本對話框)

---去掉所有的添加,只創(chuàng)建一個基本的Dialog框(基本對話框)

---不生成源文件備注,使用靜態(tài)的DLL

---默認(rèn)生成以下文件

---在#include "stdafx.h"之前的默認(rèn)都不編譯,所以111不會報錯

---也就是說:#include "stdafx.h"是MFC的編譯的第一行

---我們可以看到:theApp就是之前全局變量CMyApp

---InitInstance就是之前的WinMain主函數(shù)

---在里面也可以看到消息映射

---點擊DialogTest.rc是一個資源腳本

---可以在rc里面添加一些版本信息等

---可以在項目的目錄下面查看DiaLogTest.rc的部分具體代碼

---可以看到IDD_DIALOGTEST_DIALOG 的風(fēng)格、標(biāo)題、字體、消息等等

---有兩個按鈕,確定、取消“在這里設(shè)置對話控制”

---點擊IDD_DIALOGTEST_DIALOG右邊的窗口圖,然后查看屬性

---發(fā)現(xiàn)對應(yīng)的DiaLogTest.rc的內(nèi)容在這里凸顯

---向Dialog框,添加一個控件

---發(fā)現(xiàn)在DiaLogTest.rc里面也添加了一行按鈕的代碼

---在DiaLogTestDlg.cpp文件中,存在著DoDataExchange()的函數(shù)

---這個是添加相應(yīng)按鈕的響應(yīng)函數(shù),這個函數(shù)是一種動態(tài)綁定技術(shù),

---什么是動態(tài)綁定技術(shù)?

---添加一個名為:IDC_EDIT1的編輯框

---添加按鈕的消息響應(yīng)函數(shù),使得按下按鈕,改變編輯框里面的值

---代碼如下

---發(fā)現(xiàn)編輯框的內(nèi)容發(fā)生了改變

---也可以在:類向?qū)?> 成員變量 > IDC_EDIT1 (控件ID) >添加成員變量

---相當(dāng)于原來是通過GetDlgItem(IDC_EDIT1)來獲取IDC_EDIT1的函數(shù)地址(指針)

---現(xiàn)在通過給Dialog框的控件創(chuàng)建成員變量,進而更好的調(diào)用方法

---通過成員變量,調(diào)用方法來改變編輯框的值

---效果如下

---可以看到,這里的動態(tài)綁定,添加了控件的綁定:IDC_EDIT1和m_edit1進行綁定

---我們操作m_edit1就會改變IDC_EDIT1的控件

---在類向?qū)Ю锩娴某蓡T變量,刪除IDC_EDIT1的成員變量

---添加成員變量和m_edit1綁定,添加Value(之前是Control),Value的類似是CString(字符串?dāng)?shù)組)

---定義m_edit的長度為255

---發(fā)現(xiàn)動態(tài)綁定的地方發(fā)生了改變

---在OnButton1控件的映射函數(shù)修改m_edit1的值,賦值為一個字符串

---發(fā)現(xiàn)編輯框控件的值同樣發(fā)生了改變,之前相當(dāng)于獲取了IDC_EDIT1函數(shù)地址(指針),然后調(diào)用方法修改編輯框的值

---這里是將medit1數(shù)組和IDC_EDIT1關(guān)聯(lián),然后更新編輯框控件的值

---UpdateData(FALSE)和UpdateData(TRUE)的區(qū)別

---例如,在初始化的時候?qū)⒖臻g的內(nèi)容傳遞給edit1

---在顯示的時候,不點擊Button1,IDC_EDIT1編輯框也會顯示test

---在DoModal()里面:就是一個模態(tài)對話框

---在DoModal()里面實現(xiàn)了Dialog框的繪制,輸出、消息循環(huán)

---并且默認(rèn)了兩個按鈕:確認(rèn)取消,分別對應(yīng)下面的IDOKIDCANCEL

---在int nResponse = dlg.DoModal();處下斷點,然后點擊確定,發(fā)現(xiàn)nResponse的值為1

---同樣,點擊取消,nResponse的值為2

---可以看到不同的按鈕對應(yīng)不同的值

---為確定按鈕添加消息響應(yīng)函數(shù)

---發(fā)現(xiàn)確定按鈕調(diào)用的是CDialog::OnOK();,在這里下斷點進去查看

---注意,這里是先進入BOOL CDiaLogTestApp::InitInstance()

---然后在??? int nResponse = dlg.DoModal();創(chuàng)建、顯示Dialog框,并設(shè)置消息循環(huán)

---然后再按下確定按鈕,根據(jù)nResponse的值,來調(diào)用CDiaLogTestDlg::OnOK()

---發(fā)現(xiàn)CDiaLogTestDlg::OnOK()的本質(zhì)是調(diào)用EndDialog(IDOK);方法

---如果是CDiaLogTestDlg::IDCANCEL()就調(diào)用EndDialog(IDCANCEL);

---模態(tài)對話框(就是Dialog框)會造成一個結(jié)果:對話框卡在屏幕,雙擊rc

---插入一個新的Dialog框

---新建的Dialog框創(chuàng)建一個名為CDialog1的新類

---然后發(fā)現(xiàn)CDialog1類里面存在2各確定和取消的按鈕

---而且在FileView路徑下

---在DiaLogTest.cpp中,#include "Dialog1.h"

---然后在OnButton1()的響應(yīng)函數(shù)里面

---發(fā)現(xiàn)帶點擊OnButton1,就會彈出第二個Dialg對話框

---而且只能將模態(tài)對話框關(guān)閉之后,才能進行主窗口的操作(可以當(dāng)作驗證,如果不能通過密碼驗證,就不能使用主窗口)

---如果是非模態(tài)對話框,就不能通過DoModal函數(shù)

---但是這樣創(chuàng)建的窗口,只會一閃而過(原因是在void CDiaLogTest2Dlg::OnButton1()
函數(shù)結(jié)束之后,dlg對象就會被釋放掉)

---解決方法:采用在堆中創(chuàng)建對象(new一個對象)

---但是存在問題:new了對象,但是沒有釋放對象

#解決方法1

---在Dialog的取消控件,添加響應(yīng)函數(shù)

---將原來的CDialog::OnCancel();刪除,替換為銷毀窗口

---為什么要改寫呢?是因為:這里原本的方法是對應(yīng)的DoModal的模態(tài)對話框

---這里是非模態(tài)對話框,所以需要重寫取消的函數(shù),刪除對話框

---為Dialog1的PostNCDestroy(在視圖窗口關(guān)閉時最后調(diào)用的成員函數(shù),即刪除視圖對象)消息添加消息響應(yīng)函數(shù)

---由于DestroyWindow();最后會產(chǎn)生PostNcDestroy()消息

---重寫PostNcDestroy()消息,在這里添加銷毀堆內(nèi)存中new的對象

#解決方法2(更簡潔):

---在CDiaLogTest2Dlg.h中,首先#include "Dialog1.h",其次CDialog1* dlg;

---OnButton1() 的消息響應(yīng)函數(shù)不需要聲明CDialog1的指針

---在CDiaLogTest2Dlg的DestroyWindow消息中,建立消息響應(yīng)函數(shù)

---銷毀窗口

---DestroyWindow和PostNcDestroy的區(qū)別

---綜合以上:先調(diào)用DestroyWindow,在此間會有OnDestroy消息,接著窗口被銷毀

---于是DestroyWindow返回TRUE,

---然后是OnNcDestroy消息,之后再調(diào)用PostNcDestroy

#模態(tài)對話框:

---產(chǎn)生一個窗口卡在前一個窗口,用dlg.DoModual返回參數(shù)

---根據(jù)參數(shù)的返回值來判斷是按下確定還是取消

#非模態(tài)對話框

---不能直接調(diào)用局部變量調(diào)用,需要new一個對象

---然后去創(chuàng)建、顯示,以及手動的釋放對象


【滴水基礎(chǔ)】5.MFC(3)的評論 (共 條)

分享到微博請遵守國家法律
石渠县| 武穴市| 砚山县| 石楼县| 保定市| 青海省| 泰兴市| 抚松县| 泾源县| 尉氏县| 武宁县| 南皮县| 泽库县| 阿图什市| 天镇县| 大渡口区| 那曲县| 西吉县| 铜陵市| 青冈县| 娱乐| 淮阳县| 兴义市| 同心县| 崇州市| 岚皋县| 天津市| 泰来县| 金秀| 惠来县| 洛扎县| 武平县| 大埔县| 岱山县| 河源市| 井冈山市| 胶南市| 洞口县| 宁都县| 洛川县| 栾川县|