動(dòng)態(tài)鏈接庫(kù)編程_第1頁(yè)
動(dòng)態(tài)鏈接庫(kù)編程_第2頁(yè)
動(dòng)態(tài)鏈接庫(kù)編程_第3頁(yè)
動(dòng)態(tài)鏈接庫(kù)編程_第4頁(yè)
動(dòng)態(tài)鏈接庫(kù)編程_第5頁(yè)
已閱讀5頁(yè),還剩56頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、動(dòng)態(tài)鏈接庫(kù)編程第1頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一1.概論 先來(lái)闡述一下DLL(Dynamic Linkable Library)的概念,你可以簡(jiǎn)單的把DLL看成一種倉(cāng)庫(kù),它提供給你一些可以直接拿來(lái)用的變量、函數(shù)或類(lèi)。在倉(cāng)庫(kù)的發(fā)展史上經(jīng)歷了“無(wú)庫(kù)靜態(tài)鏈接庫(kù)動(dòng)態(tài)鏈接庫(kù)”的時(shí)代。 對(duì)動(dòng)態(tài)鏈接庫(kù),需建立如下概念: 第2頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一(1)與具體的編程語(yǔ)言及編譯器無(wú)關(guān) 只要遵循約定的DLL接口規(guī)范和調(diào)用方式,用各種語(yǔ)言編寫(xiě)的DLL都可以相互調(diào)用。譬如Windows提供的系統(tǒng)DLL(其中包括了Windows的API),在任何開(kāi)發(fā)環(huán)境中

2、都能被調(diào)用,不在乎其是Visual Basic、Visual C+還是Delphi。 第3頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一(2)動(dòng)態(tài)鏈接庫(kù)隨處可見(jiàn) 在Windows目錄下的system32文件夾中會(huì)看到kernel32.dll、user32.dll和gdi32.dll,windows的大多數(shù)API都包含在這些DLL中。kernel32.dll中的函數(shù)主要處理內(nèi)存管理和進(jìn)程調(diào)度;user32.dll中的函數(shù)主要控制用戶界面(MessageBox函數(shù));gdi32.dll中的函數(shù)則負(fù)責(zé)圖形方面的操作。 第4頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一 (3)

3、VC動(dòng)態(tài)鏈接庫(kù)的分類(lèi)Visual C+支持三種DLL,它們分別是非MFC動(dòng)態(tài)庫(kù)、MFC規(guī)則DLL、MFC Extension DLL。 非MFC動(dòng)態(tài)庫(kù)不采用MFC類(lèi)庫(kù)結(jié)構(gòu),其導(dǎo)出函數(shù)為標(biāo)準(zhǔn)的C接口,能被非MFC或MFC編寫(xiě)的應(yīng)用程序所調(diào)用;MFC規(guī)則DLL 包含一個(gè)繼承自CWinApp的類(lèi),但其無(wú)消息循環(huán);MFC擴(kuò)展DLL采用MFC的動(dòng)態(tài)鏈接版本創(chuàng)建,它只能被用MFC類(lèi)庫(kù)所編寫(xiě)的應(yīng)用程序所調(diào)用。 第5頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一第6頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一第7頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一2.靜態(tài)鏈接庫(kù)

4、 在VC+6.0中new一個(gè)名稱為libTest的static library工程,并新建lib.h和lib.cpp兩個(gè)文件,lib.h和lib.cpp的源代碼如下: /文件:lib.h #ifndef LIB_H #define LIB_H extern C int add(int x,int y);/聲明為C編譯、連接方式的外部函數(shù) #endif /文件:lib.cpp #include lib.h int add(int x,int y) return x + y; 第8頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一#include #include .lib.h #prag

5、ma comment( lib, .debuglibTest.lib ) /指定與靜態(tài)庫(kù)一起連接 int main(int argc, char* argv) printf( 2 + 3 = %d, add( 2, 3 ) ); 第9頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一選擇tools、options、directories、library files菜單或選項(xiàng),填入庫(kù)文件路徑 第10頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一4.非MFC DLL 第11頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一在建立的工程中添加lib.h及l(fā)ib.cpp文件

6、,源代碼如下:/* 文件名:lib.h*/#ifndef LIB_H#define LIB_Hextern C int _declspec(dllexport)add(int x, int y);#endif/* 文件名:lib.cpp*/#include lib.hint add(int x, int y)return x + y;第12頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一dllCall #include #include typedef int(*lpAddFun)(int, int); /宏定義函數(shù)指針類(lèi)型int main(int argc, char *argv)

7、 HINSTANCE hDll; /DLL句柄 lpAddFun addFun; /函數(shù)指針 hDll = LoadLibrary(.DebugdllTest.dll); if (hDll != NULL) addFun = (lpAddFun)GetProcAddress(hDll, add); if (addFun != NULL) int result = addFun(2, 3); printf(%d, result); FreeLibrary(hDll); return 0;第13頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一DLL的調(diào)用和靜態(tài)鏈接庫(kù)的調(diào)用有較大差異 首先

8、,語(yǔ)句typedef int ( * lpAddFun)(int,int)定義了一個(gè)與add函數(shù)接受參數(shù)類(lèi)型和返回值均相同的函數(shù)指針類(lèi)型。隨后,在main函數(shù)中定義了lpAddFun的實(shí)例addFun;其次,在函數(shù)main中定義了一個(gè)DLL HINSTANCE句柄實(shí)例hDll,通過(guò)Win32 Api函數(shù)LoadLibrary動(dòng)態(tài)加載了DLL模塊并將DLL模塊句柄賦給了hDll;再次,在函數(shù)main中通過(guò)Win32 Api函數(shù)GetProcAddress得到了所加載DLL模塊中函數(shù)add的地址并賦給了addFun。經(jīng)由函數(shù)指針addFun進(jìn)行了對(duì)DLL中add函數(shù)的調(diào)用;最后,應(yīng)用工程使用完DL

9、L后,在函數(shù)main中通過(guò)Win32 Api函數(shù)FreeLibrary釋放了已經(jīng)加載的DLL模塊。第14頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一聲明導(dǎo)出函數(shù) DLL中導(dǎo)出函數(shù)的聲明有兩種方式:一種為給出的在函數(shù)聲明中加上_declspec(dllexport);一種方式是采用模塊定義(.def) 文件聲明;第15頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一在DLL中想要export的函數(shù)和數(shù)據(jù)定義前添加_declspec(dllexport)關(guān)鍵字(對(duì)于函數(shù)和變量定義,加在最前面;對(duì)于class定義,加在class關(guān)鍵字后);_declspec(dllexpor

10、t) void ShowDlg(void)class _declspec(dllexport) class_name /導(dǎo)出類(lèi) 這樣該函數(shù)和數(shù)據(jù)就會(huì)被添加到ET中。使用這種方法函數(shù)將按名字export。_declspec(dllexport)第16頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一(.def) 文件聲明為DLL創(chuàng)建一個(gè).DEF文件(模塊定義文件),并在build該DLL時(shí)使用這個(gè).DEF文件。使用這種方法使你可以將函數(shù)按序號(hào)export。在LINK選項(xiàng)卡中假如: /def:lib.def將lib.def加入到工程中。第17頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19

11、分,星期一lib.def; lib.def : 導(dǎo)出DLL函數(shù)LIBRARY dllTestEXPORTSadd 1.def文件的規(guī)則為:(1)LIBRARY語(yǔ)句說(shuō)明.def文件相應(yīng)的DLL;(2)EXPORTS語(yǔ)句后列出要導(dǎo)出函數(shù)的名稱??梢栽?def文件中的導(dǎo)出函數(shù)名后加n,表示要導(dǎo)出函數(shù)的序號(hào)為n(在進(jìn)行函數(shù)調(diào)用時(shí),這個(gè)序號(hào)將發(fā)揮其作用);(3).def 文件中的注釋由每個(gè)注釋行開(kāi)始處的分號(hào) (;) 指定,且注釋不能與語(yǔ)句共享一行。第18頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一庫(kù)的調(diào)試與查看 動(dòng)態(tài)鏈接庫(kù)中的導(dǎo)出接口可以使用Visual C+的Depends工具進(jìn)行查看,

12、用Depends打開(kāi)系統(tǒng)目錄中的MouseHook.dll .第19頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一第20頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一第21頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一DLL的調(diào)用方式 隱式調(diào)用:將DLL工程生成的.lib文件和.dll文件拷入當(dāng)前工程所在的目錄,并在*.cpp文件(的頂部添加:#pragma comment(lib,RegularDll.lib) OR第22頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一動(dòng)態(tài)調(diào)用特點(diǎn):是完全由編程者用 API 函數(shù)加載和卸載 DLL,程序員可以決定

13、 DLL 文件何時(shí)加載或不加載,顯式鏈接在運(yùn)行時(shí)決定加載哪個(gè) DLL 文件。第23頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一dllTest.dll 在建立的工程中添加lib.h及l(fā)ib.cpp文件,源代碼如下:/* 文件名:lib.h*/#ifndef LIB_H#define LIB_Hextern C int _declspec(dllexport)add(int x, int y);#endif/* 文件名:lib.cpp*/#include lib.hint add(int x, int y)return x + y;第24頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)1

14、9分,星期一調(diào)用 dllTest.dll #include #include typedef int(*lpAddFun)(int, int); /宏定義函數(shù)指針類(lèi)型int main(int argc, char *argv) HINSTANCE hDll; /DLL句柄 lpAddFun addFun; /函數(shù)指針hDll = LoadLibrary(.DebugdllTest.dll);if (hDll != NULL) addFun = (lpAddFun)GetProcAddress(hDll, add);if (addFun != NULL)int result = addFun(2

15、, 3);printf(%d, result);FreeLibrary(hDll); 第25頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一DLL的Export和Import DLL的export是指將DLL中的函數(shù)和數(shù)據(jù)輸出到其它程式中,以供其使用。DLL的import是指使用DLL的程式引入DLL中的函數(shù)和數(shù)據(jù)。DLL的export DLL中包含有一個(gè)表,稱為export table(以下簡(jiǎn)稱ET),其中包含了DLL中可以被外部程式使用的所有函數(shù)和數(shù)據(jù)的名字。只有記錄在ET中的函數(shù)和數(shù)據(jù)才可以被外部程式所使用(如果沒(méi)有.DEF文件的話),其它所有沒(méi)有記錄在ET中的函數(shù)和數(shù)據(jù)都被視

16、為是DLL私有的。第26頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一DllMain函數(shù) Windows在加載DLL的時(shí)候,需要一個(gè)入口函數(shù),就如同控制臺(tái)或DOS程序需要main函數(shù)、WIN32程序需要WinMain函數(shù)一樣。在前面的例子中,DLL并沒(méi)有提供DllMain函數(shù),應(yīng)用工程也能成功引用DLL,這是因?yàn)閃indows在找不到DllMain的時(shí)候,系統(tǒng)會(huì)從其它運(yùn)行庫(kù)中引入一個(gè)不做任何操作的缺省DllMain函數(shù)版本,并不意味著DLL可以放棄DllMain函數(shù)。 第27頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一BOOL APIENTRY DllMain( HA

17、NDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) DllMain函數(shù)在DLL被加載和卸載時(shí)被調(diào)用,在單個(gè)線程啟動(dòng)和終止時(shí),DLLMain函數(shù)也被調(diào)用;ul_reason_for_call指明了被調(diào)用的原因。原因共有4種,即PROCESS_ATTACH、PROCESS_DETACH、THREAD_ATTACH和THREAD_DETACH,以switch語(yǔ)句列出。第28頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一DLL導(dǎo)出變量 /* 文件名:lib.h*/#ifndef LIB_H#define LIB_Hexter

18、n int dllGlobalVar;#endif/* 文件名:lib.cpp */#include lib.h#include int dllGlobalVar;BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) dllGlobalVar = 100; /在dll被加載時(shí),賦全局變量為100 return TRUE;文件名:lib.def;在DLL中導(dǎo)出變量LIBRARY dllTestEXPORTSdllGlobalVar DATA 第29頁(yè),共61頁(yè),2022年,5月20日,

19、15點(diǎn)19分,星期一在主函數(shù)中引用DLL中定義的全局變量:#include #pragma comment(lib,dllTest.lib)extern int _declspec(dllimport) dllGlobalVar; /用_declspec(dllimport)導(dǎo)入int main(int argc, char *argv)printf(%d , dllGlobalVar);dllGlobalVar = 1; printf(%d , dllGlobalVar);return 0;第30頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一特別要注意用extern int dl

20、lGlobalVar聲明所導(dǎo)入的并不是DLL中全局變量本身,而是其地址,應(yīng)用程序必須通過(guò)強(qiáng)制指針轉(zhuǎn)換來(lái)使用DLL中的全局變量。這一點(diǎn),從*(int*)dllGlobalVar可以看出。因此在采用這種方式引用DLL全局變量時(shí),千萬(wàn)不要進(jìn)行這樣的賦值操作:dllGlobalVar = 1;第31頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一MFC規(guī)則DLL MFC規(guī)則DLL的概念體現(xiàn)在兩方面:它是MFC的 “是MFC的”意味著可以在這種DLL的內(nèi)部使用MFC;它是規(guī)則的 “是規(guī)則的”意味著它不同于MFC擴(kuò)展DLL,在MFC規(guī)則DLL的內(nèi)部雖然可以使用MFC,但是其與應(yīng)用程序的接口不能是

21、MFC。而MFC擴(kuò)展DLL與應(yīng)用程序的接口可以是MFC,可以從MFC擴(kuò)展DLL中導(dǎo)出一個(gè)MFC類(lèi)的派生類(lèi)。Regular DLL能夠被所有支持DLL技術(shù)的語(yǔ)言所編寫(xiě)的應(yīng)用程序調(diào)用,當(dāng)然也包括使用MFC的應(yīng)用程序。 第32頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一Regular DLL分為兩類(lèi):(1)靜態(tài)鏈接到MFC 的規(guī)則DLL靜態(tài)鏈接到MFC的規(guī)則DLL與MFC庫(kù)(包括MFC擴(kuò)展 DLL)靜態(tài)鏈接,將MFC庫(kù)的代碼直接生成在.dll文件中。在調(diào)用這種DLL的接口時(shí),MFC使用DLL的資源。因此,在靜態(tài)鏈接到MFC 的規(guī)則DLL中不需要進(jìn)行模塊狀態(tài)的切換。使用這種方法生成的規(guī)則

22、DLL其程序較大,也可能包含重復(fù)的代碼。(2)動(dòng)態(tài)鏈接到MFC 的規(guī)則DLL動(dòng)態(tài)鏈接到MFC 的規(guī)則DLL 可以和使用它的可執(zhí)行文件同時(shí)動(dòng)態(tài)鏈接到 MFC DLL 和任何MFC擴(kuò)展 DLL。在使用了MFC共享庫(kù)的時(shí)候,默認(rèn)情況下,MFC使用主應(yīng)用程序的資源句柄來(lái)加載資源模板。這樣,當(dāng)DLL和應(yīng)用程序中存在相同ID的資源時(shí)(即所謂的資源重復(fù)問(wèn)題),系統(tǒng)可能不能獲得正確的資源。因此,對(duì)于共享MFC DLL的規(guī)則DLL,必須進(jìn)行模塊切換以使得MFC能夠找到正確的資源模板。第33頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一MFC規(guī)則DLL的創(chuàng)建 automation(自動(dòng)化)技術(shù) 是否支

23、持Windows Sockets 第34頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一在MFC應(yīng)用程序中CWinApp取代了SDK程序中WinMain的地位,SDK程序WinMain所完成的工作由CWinApp的三個(gè)函數(shù)完成:virtual BOOL InitApplication( );virtual BOOL InitInstance( );virtual BOOL Run( ); /傳說(shuō)中MFC程序的“活水源頭”第35頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一MFC規(guī)則DLL接口函數(shù)#include StdAfx.h #include DllDialog.h_

24、declspec(dllexport) void ShowDlg(void)或extern C _declspec(dllexport) void ShowDlg(void) CDllDialog dllDialog; dllDialog.DoModal();分析:這個(gè)接口并不使用MFC,但是在其中卻可以調(diào)用MFC擴(kuò)展類(lèi)CdllDialog的函數(shù),這體現(xiàn)了“規(guī)則”的概類(lèi)。與非MFC DLL完全相同,可以使用_declspec(dllexport)聲明或在.def中引出的方式導(dǎo)出MFC規(guī)則DLL中的接口。第36頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一MFC規(guī)則DLL的調(diào)用 第3

25、7頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一#pragma comment(lib,RegularDll.lib)_declspec(dllexport) void ShowDlg(void)void ShowDlg(void); 或extern C _declspec(dllexport) void ShowDlg(void)extern C void ShowDlg(void); void CRegularDllCallDlg:OnCalldllButton() ShowDlg();第38頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一MFC擴(kuò)展 DLL MFC擴(kuò)

26、展DLL與MFC規(guī)則DLL的相同點(diǎn)在于在兩種DLL的內(nèi)部都可以使用MFC類(lèi)庫(kù),其不同點(diǎn)在于MFC擴(kuò)展DLL與應(yīng)用程序的接口可以是MFC的。MFC擴(kuò)展DLL的含義在于它是MFC的擴(kuò)展,其主要功能是實(shí)現(xiàn)從現(xiàn)有MFC庫(kù)類(lèi)中派生出可重用的類(lèi)。MFC擴(kuò)展DLL使用MFC 動(dòng)態(tài)鏈接庫(kù)版本,因此只有用共享MFC 版本生成的MFC 可執(zhí)行文件(應(yīng)用程序或規(guī)則DLL)才能使用MFC擴(kuò)展DLL。一般使用MFC擴(kuò)展DLL來(lái)包含一些MFC的增強(qiáng)功能,譬如擴(kuò)展MFC的CStatic、CButton等類(lèi)使之具備更強(qiáng)大的能力。第39頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一三種DLL對(duì)DllMain入口函數(shù)

27、的不同處理方式: DLL類(lèi)型 入口函數(shù) 非 MFC DLL 編程者提供DllMain函數(shù) MFC規(guī)則 DLL CWinApp對(duì)象的InitInstance 和 ExitInstance MFC擴(kuò)展 DLL MFC DLL向?qū)蒁llMain 函數(shù) 第40頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一宏宏為DLL和應(yīng)用程序的編寫(xiě)提供了方便。像AFX_EXT_CLASS、AFX_EXT_API、AFX_EXT_DATA在DLL和應(yīng)用程序中將具有不同的定義,這取決于_AFXEXT宏是否被定義。這使得在DLL和應(yīng)用程序中,使用統(tǒng)一的一個(gè)宏就可以表示出輸出和輸入的不同意思。在DLL中,表示

28、輸出(因?yàn)開(kāi)AFXEXT被定義,通常是在編譯器的標(biāo)識(shí)參數(shù)中指定/D_AFXEXT);在應(yīng)用程序中,則表示輸入(_AFXEXT沒(méi)有定義)。 第41頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一AFX_CLASS_IMPORT _declspec(dllexport) AFX_API_IMPORT _declspec(dllexport) AFX_DATA_IMPORT _declspec(dllexport) AFX_CLASS_EXPORT _declspec(dllexport) AFX_API_EXPORT _declspec(dllexport) AFX_DATA_EXPOR

29、T _declspec(dllexport) 第42頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一AFX_EXT_CLASS #ifdef _AFXEXT AFX_CLASS_EXPORT #else AFX_CLASS_IMPORT AFX_EXT_API #ifdef _AFXEXT AFX_API_EXPORT #else AFX_API_IMPORT AFX_EXT_DATA #ifdef _AFXEXT AFX_DATA_EXPORT #else AFX_DATA_IMPORT 第43頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一class AFX_EXT_C

30、LASS CExtDialog : public CDialog *#include .ExtDialog.h #pragma comment( lib, ExtDll.lib ) 而“調(diào)用DLL”按鈕的單擊事件的消息處理函數(shù)為: void CLoadExtDllDlg:OnDllcallButton() CExtDialogextDialog; extDialog.DoModal(); 第44頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一Win32系統(tǒng)鉤子技術(shù)APIHOOK技術(shù)應(yīng)用廣泛,常用于屏幕取詞、網(wǎng)絡(luò)防火墻、病毒木馬、加殼軟件、串口紅外通信、游戲外掛、Internet通信等

31、領(lǐng)域。HOOK的中文意思就是鉤子,APIHOOK就是鉤住API,對(duì)API進(jìn)行預(yù)處理,先執(zhí)行我們的函數(shù)。 第45頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一APIHOOK技術(shù)鉤子的本質(zhì)是一段用以處理系統(tǒng)消息的程序,通過(guò)系統(tǒng)調(diào)用,把它掛入系統(tǒng)。鉤子的種類(lèi)很多,每種鉤子可以截獲并處理相應(yīng)的消息,每當(dāng)特定的消息發(fā)出,在到達(dá)目的窗口之前,鉤子程序先行截獲該消息、得到對(duì)此消息的控制權(quán)。此時(shí)鉤子函數(shù)可以對(duì)截獲的消息進(jìn)行加工處理,甚至可以強(qiáng)制結(jié)束消息的傳遞。這有點(diǎn)類(lèi)似與MFC中的PreTranslateMessage函數(shù),所不同的是該函數(shù)只能用于攔截本進(jìn)程中的消息,而對(duì)系統(tǒng)消息則無(wú)能為力。 第4

32、6頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一Win32系統(tǒng)鉤子的實(shí)現(xiàn) 每種類(lèi)型的鉤子均由系統(tǒng)來(lái)維護(hù)一個(gè)鉤子鏈,最近安裝的鉤子位于鏈的開(kāi)始,擁有最高的優(yōu)先級(jí),而最先安裝的鉤子則處在鏈的末尾。要實(shí)現(xiàn)Win32的系統(tǒng)鉤子,首先要調(diào)用SDK中的API函數(shù)SetWindowsHookEx來(lái)安裝這個(gè)鉤子函數(shù),其原型是: 第47頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId); 其中:第一個(gè)參數(shù)是鉤子的類(lèi)型,常用的有W

33、H_MOUSE、WH_KEYBOARD、WH_GETMESSAGE等;第二個(gè)參數(shù)是鉤子函數(shù)的地址,當(dāng)鉤子鉤到任何消息后便調(diào)用這個(gè)函數(shù);第三個(gè)參數(shù)是鉤子函數(shù)所在模塊的句柄;第四個(gè)參數(shù)是鉤子相關(guān)函數(shù)的ID用以指定想讓鉤子去鉤哪個(gè)線程,為0時(shí)則攔截整個(gè)系統(tǒng)的消息此時(shí)為全局鉤子。如果指定確定的線程,即為線程專(zhuān)用鉤子。 第48頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一全局鉤子函數(shù)必須包含在DLL(動(dòng)態(tài)鏈接庫(kù))中,而線程專(zhuān)用鉤子則可包含在可執(zhí)行文件中。得到控制權(quán)的鉤子函數(shù)在處理完消息后,可以調(diào)用另外一個(gè)SDK中的API函數(shù)CallNextHookEx來(lái)繼續(xù)傳遞該消息。也可以通過(guò)直接返回TR

34、UE來(lái)丟棄該消息,阻止該消息的傳遞。第49頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一使用全局鉤子函數(shù)時(shí)需要以DLL為載體,VC6中有三種形式的MFC DLL可供選擇,即標(biāo)準(zhǔn)靜態(tài)鏈接MFC DLL、標(biāo)準(zhǔn)動(dòng)態(tài)鏈接MFC DLL以及擴(kuò)展MFC DLL)。第一種DLL在編譯時(shí)把使用的MFC代碼鏈接到DLL中,執(zhí)行程序時(shí)不需要其他MFC動(dòng)態(tài)鏈接類(lèi)庫(kù)的支持,但體積較大;第二種DLL在運(yùn)行時(shí)動(dòng)態(tài)鏈接到MFC類(lèi)庫(kù),因而體積較小,但卻依賴于MFC動(dòng)態(tài)鏈接類(lèi)庫(kù)的支持;這兩種DLL均可被MFC程序和Win32程序使用。第三種DLL的也是動(dòng)態(tài)連接,但做為MFC類(lèi)庫(kù)的擴(kuò)展,只能被MFC程序使用。 第50

35、頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一Win32 DLL BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved);其中:第一個(gè)參數(shù)表示DLL的實(shí)例句柄;第三個(gè)參數(shù)系統(tǒng)保留;第二個(gè)參數(shù)指明了當(dāng)前調(diào)用該動(dòng)態(tài)連接庫(kù)的狀態(tài),它有四個(gè)可能的值:DLL_PROCESS_ATTACH(進(jìn)程載入)、DLL_THREAD_ATTACH(線程載入)、DLL_THREAD_DETACH(線程卸載)、DLL_PROCESS_DETACH(進(jìn)程卸載)。第51頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19

36、分,星期一DLL的共享問(wèn)題由于在Win32環(huán)境下,所有進(jìn)程的空間都是相互獨(dú)立的,這減少了應(yīng)用程序間的相互影響,但大大增加了編程的難度。當(dāng)進(jìn)程在動(dòng)態(tài)加載DLL時(shí),系統(tǒng)自動(dòng)把DLL地址映射到該進(jìn)程的私有空間;而且也復(fù)制該DLL的全局?jǐn)?shù)據(jù)的一份拷貝到該進(jìn)程空間,每個(gè)進(jìn)程所擁有的相同的DLL的全局?jǐn)?shù)據(jù)其值卻并不一定是相同的。當(dāng)DLL內(nèi)存被映射到進(jìn)程空間中,每個(gè)進(jìn)程都有自己的全局內(nèi)存拷貝,加載DLL的每一個(gè)新的進(jìn)程都重新初始化這一內(nèi)存區(qū)域,也就是說(shuō)進(jìn)程不能再共享DLL。第52頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一全局共享數(shù)據(jù)的實(shí)現(xiàn) 在Win32環(huán)境下要想在多個(gè)進(jìn)程中共享數(shù)據(jù),就必須進(jìn)

37、行必要的設(shè)置。一種方法便是把這些需要共享的數(shù)據(jù)單獨(dú)分離出來(lái),放置在一個(gè)獨(dú)立的數(shù)據(jù)段里,并把該段的屬性設(shè)置為共享,建立一個(gè)內(nèi)存共享的DLL。 第53頁(yè),共61頁(yè),2022年,5月20日,15點(diǎn)19分,星期一#pragma data_seg用#pragma data_seg建立一個(gè)新的數(shù)據(jù)段并定義共享數(shù)據(jù),其具體格式為: #pragma data_seg (shareddata) HWND sharedwnd=NULL;/共享數(shù)據(jù) #pragma data_seg() 所有在data_seg pragmas語(yǔ)句之間聲明的變量都將在shareddata段中。僅定義一個(gè)數(shù)據(jù)段還不能達(dá)到共享數(shù)據(jù)的目的,還要告訴編譯器該段的屬性,有兩種方法可以實(shí)現(xiàn)該目的(其效果是相同的),

溫馨提示

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

評(píng)論

0/150

提交評(píng)論