欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

动态链接库

程序员文章站 2022-06-25 18:44:30
...

一、DLL种类

不使用MFC的win32 DLL和使用MFC的MFC DLL


MFC DLL三种开发方式
1.使用静态链接MFC类库的常规DLL
2.使用动态链接MFC类库的常规DLL
3.MFC扩展DLL。现有MFC类库中的类派生而来的可以重复使用的类。扩展DLL使用MFC的动态链接库版本构建




二、DLL文件组成

DEF文件模块定义语句
1.文件的第一条语句必须是LIBRARY语句。语句后写入DLL名称。
2.文件中的EXPORTS语句用于列出导出的函数名称和为其分配序号值。格式是函数名称后写入@符号和序号值
3.DESCRIPTION语句描述DLL的功能
4.所有以分号开头的行都是注释行



;MFCDLL1.def:Declares the module parameters for the DLL.
LIBRARY "MFCDLL1"
DESCRIPTION "MFCDLL1 windows Dynamic Link Library"
EXPORTS 
Writelog @1



三.函数介绍

1.DLLMain 入口函数

BOOL WINAPI DLLMain(
HINSTANCE hinstDll,//Dll模块的句柄
DWORD fdwReason,//调用函数的来源
LPVOID lpvReserved//预留
);
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
//根据调用DLL的来源完成相应的工作
case DLL_PROCESS_ATTACH:
	//对于每个新进程,初始化一次,如果DLL装载失败,则返回false
case DLL_THREAD_ATTACH:
	//执行线程指定初始化
case DLL_THREAD_DETACH:
	//执行线程指定的清除工作
case DLL_PROCESS_DETACH
	//执行任何需要的清除工作
break;
}
return true;//进程装载入口函数成功完成
}



2.LoadLibrary

DLL映射到进程地址空间
HMODULE LoadLibrary(PCTSTR pszDLLPathName);




3.LoadLibraryEx

https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx


HMODULE LoadLibraryEx(PCTSTR pszDLLPathName,HANDLE hFile,DWORD dwFlags);


4.FreeLibrary

将DLL从进程地址空间中卸载


BOOL FreeLibrary( HMODULE  hInstDll );

5.FreeLibraryAndExitThread

从进程地址空间卸载某DLL的功能,还能退出调用线程
   VOID FreeLibraryAndExitThread(HMODULE hInstDll,DWORD dwExitCode)

6.GetModuleFileName

返回执行文件包含的指定模块的完整路径和文件名
DWORD GetModuleFileName(
HMODULE hModule,//要获取文件名的模块句柄
LPTSTR lpFilename,//接收模块路径的缓冲区的指针
DWORD nSize//缓冲区的大小
);

7.GetModuleHandle

返回模块的模块句柄
HMODULE GetModuleHandle(
LPCTSTR lpModuleName)//要获取句柄的模块的名称地址


8.GetProcAddress

返回导出的DLL函数的地址
FARPROC GetProcAddress(
HMODULE hModule,//DLL模块的句柄
LPCSTR lpProcName);//函数名


四.从动态库中获取位图资源

LoadLibraryEx() 函数加载动态库,EnumResourceNames函数枚举指定类型的资源。


BOOL EnumResourceNames(
HINSTANCE hModule,//指定要枚举资源的可执行文件的模块句柄
LPCTSTR lpszType,//指定要枚举的资源类型
ENUMRESNAMEPROC lpEnumFunc,//指定查找到每个资源后都要执行的回调函数
LONG lParam);//传递给回调函数的用户自定义参数值


回调函数
BOOL CALLBACK EnumResNameProc(
HANDLE hModule,//枚举函数 正在枚举的资源所在的可执行文件的句柄
LPCTSTR lpszType,//正在枚举创建当前进程的模块的资源
LPTSTR lpszName,//当前枚举项的资源名称
LONG lParam);//EnumResourceNames函数LParam参数传进来的用户自定义参数值


DLLAppSampleDlg.cpp:
// 枚举位图
void CDLLAppSampleDlg::OnButtonGetbitmap() 
{
	m_iconList.ShowWindow(SW_HIDE);
	if( (hLibrary = LoadLibraryEx( "MORICONS.DLL", NULL, LOAD_LIBRARY_AS_DATAFILE )) == NULL )
	{
		WriteLog("文件载入错误!");
		return;
	}


	if(!EnumResourceNames(hLibrary,RT_BITMAP,(ENUMRESNAMEPROC)EnumBitmapProcedure,(LPARAM)GetSafeHwnd()))
		WriteLog("列举位图资源停止!");
	FreeLibrary(hLibrary);
}


//显示位图
LRESULT CDLLAppSampleDlg::OnBitmapMessage(WPARAM wParam,LPARAM lParam)
{	
	CStatic* m_Bitmap = (CStatic*)GetDlgItem(IDC_STATIC_BITMAP);
	m_Bitmap->SetBitmap((HBITMAP)wParam);
	WriteLog((const char*)&lParam);
    return 1;
}


DLLAppSample.cpp:
BOOL CALLBACK EnumBitmapProcedure(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
{
	HBITMAP bitmap = LoadBitmap((HINSTANCE)hModule,lpszName);
	if (true)
	{
		SendMessage((HWND)lParam, WM_BITMAP_MESSAGE, (LPARAM)bitmap, (WPARAM)lpszName);	
		return FALSE;
	}
}




五.枚举模块中的所有图标

DLLAppSampleDlg.cpp:
// 枚举图标
void CDLLAppSampleDlg::OnButtonGetallicon() 
{
	ResetContent();	
	HINSTANCE  hLibrary;
	if( (hLibrary = LoadLibraryEx( "MORICONS.DLL", NULL, LOAD_LIBRARY_AS_DATAFILE )) == NULL )
	{
		WriteLog("文件载入错误!");
		return;
	}


	if(!EnumResourceNames(hLibrary,RT_GROUP_ICON,(ENUMRESNAMEPROC)EnumIconProcedure,(LPARAM)GetSafeHwnd()))
		WriteLog("列举图标资源停止!");


	FreeLibrary(hLibrary);


	CString log;
	log.Format("DLL*包含%d个图标资源!", m_iconList.GetItemCount());
	WriteLog(log);
}


// 显示图标
LRESULT CDLLAppSampleDlg::OnIconMessage(WPARAM wParam,LPARAM lParam)
{
	int iIconRet = imagelist.Add((HICON)wParam); 
	if (iIconRet!=-1)
	{
		m_iconList.SetImageList (&imagelist,LVSIL_SMALL);
		int iIndex = m_iconList.GetItemCount();
		m_iconList.InsertItem(iIndex, (const char*)&lParam, iIndex);
	}
    return 1;
}


DLLAppSample.cpp:
BOOL CALLBACK EnumIconProcedure(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
{
	HICON icon = LoadIcon((HINSTANCE)hModule,lpszName);
	SendMessage((HWND)lParam, WM_ICON_MESSAGE, (LPARAM)icon, (WPARAM)lpszName);	
	return TRUE;
}



六.使用模块对话框资源 

AfxSetResourceHandle函数可以切换要使用的资源所在的实例,从而实现调用其他模块中的对话框资源的功能


AfxSetResourceHandle(
HINSTANCE hInstResource);//指定应用程序要载入的资源所在的EXE或DLL文件的模块句柄或实例


AfxGetResourceHandle函数保存原来的实例句柄。


//使用模块对话框资源
void CDLLAppSampleDlg::OnButtonGetdialog() 
{
	HINSTANCE m_hInstOld=AfxGetInstanceHandle();
	HINSTANCE m_hInstNew = LoadLibrary("RedDLL.exe"); 
	if (m_hInstNew == NULL)  WriteLog("装载可执行文件失败!");	 
	AfxSetResourceHandle(m_hInstNew);
	CDialog* dlg = new CDialog();
	if (dlg->Create(IDD_ABOUTBOX))	dlg->ShowWindow(SW_SHOW);
	AfxSetResourceHandle(m_hInstOld);
}




七.替换应用程序的对话框资源

1.使用LoadLibrary函数装载替换内容的可执行文件
2.使用FindResource函数和LoadResource函数查找定位并装载用于替换对话框资源
3.调用LockResource函数获取对话框资源的数据指针
4.使用BeginUpdateResource函数打开要更新的资源
5.使用UpdateResource函数将用于替换的对话框资源复制到要替换的对话框资源
6.使用EndUpadteResource函数完成替换


void CDLLAppSampleDlg::OnButtonReplacedialog() 
{
	HRSRC hRes, hResLoad; 
	HANDLE hExe, hUpdateExe; 
	char *lpResLock;    
	BOOL bResult; 
 
	hExe = LoadLibrary("RedDLL.exe"); 
	if (hExe == NULL)  WriteLog("装载可执行文件失败!");		
 
	hRes = FindResource((HINSTANCE)hExe, MAKEINTRESOURCE(IDD_ABOUTBOX), RT_DIALOG); 
	if (hRes == NULL) WriteLog("无法查找要替换的资源!");
	 
	hResLoad = (HRSRC)LoadResource((HINSTANCE)hExe, hRes);  
	if (hResLoad == NULL)	WriteLog("无法装载对话框!"); 	


	lpResLock = (char*)LockResource(hResLoad); 
	if (lpResLock == NULL)  WriteLog("无法锁定对话框!"); 


 
	hUpdateExe = (HRSRC)BeginUpdateResource("GreenDLL.exe", FALSE); 
	if (hUpdateExe == NULL)  WriteLog("无法打开要写入资源的文件!"); 


	bResult = UpdateResource((HINSTANCE)hUpdateExe, RT_DIALOG, MAKEINTRESOURCE(IDD_ABOUTBOX),  
     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), lpResLock, 
     SizeofResource((HINSTANCE)hExe, hRes));  
	if (bResult == FALSE)  WriteLog("替换资源失败!"); 
	
	if (!EndUpdateResource(hUpdateExe, FALSE)) WriteLog("不能写入对文件的修改!");	
 
	if (!FreeLibrary((HINSTANCE)hExe)) 	WriteLog("释放文件失败!"); 	
}



八.屏蔽键盘Power键

通过回调函数,可以屏蔽系统按键的处理。通过底层键盘钩子的回调函数来屏蔽POWER键的方法。由于POWER键是底层键盘按键,因此
需要使用底层键盘钩子回调函数
LRESULT CALLBACK LowLevelKeyboardProc(
int nCode,//指定钩子处理代码 
WPARAM wParam,//指定键盘信息的标志符
LPARAM lParam);//定向KBDKKHOOKSTRUCT结构的指针,其中存储按下的按键的信息




Power键的按键代码是1,因此将其传入DLL中的StartShieldKey()函数后可以屏蔽Power按键。
//屏蔽键盘POWER键
void CDLLAppSampleDlg::OnButtonDisablePower() 
{
	DWORD dwVerKey[] = {0x00000001};
	DWORD dwConKey[] = {0};
    int nLength = sizeof(dwVerKey) / sizeof(DWORD);
    if (StartShieldKey(dwVerKey, dwConKey, nLength)) WriteLog("已经屏蔽POWER键");
	else WriteLog("屏蔽POWER键失败");
}




ShieldKeyBordSample.dll:
// 底层键盘钩子回调函数
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{    
     if (nCode == HC_ACTION)	// 禁用键盘的某个按键
     {
         KBDLLHOOKSTRUCT* pHookStruct = (KBDLLHOOKSTRUCT*)lParam;	// 取出钩子结构
		 LPDWORD tmpVirKey = m_lpdwVirtualKey;		// 取出要屏蔽的键的列表指针
         for (int i = 0; i < m_nLength; i++)
         {			 
			 if (*m_lpdwContentKey++ == 1)
			 {
				 DWORD dwAltKey = 32;
				 if ((pHookStruct->vkCode == *tmpVirKey++)
					 && (pHookStruct->flags == dwAltKey)) return TRUE;
			 }
			 if (pHookStruct->vkCode == *tmpVirKey++) return TRUE;
         }
     }
     return CallNextHookEx(m_hHook, nCode, wParam, lParam);	// 如果不是要屏蔽的按键则传给系统中的下一个钩子
}
// 启动屏蔽
SHIELDKEYBORDSAMPLE_API bool StartShieldKey(LPDWORD lpdwVirtualKey, LPDWORD lpdwContentKey, int nLength)
{
     if (m_hHook != NULL) return StopShieldKey();
     m_lpdwVirtualKey = (LPDWORD)malloc(sizeof(DWORD) * nLength);
	 m_lpdwContentKey = (LPDWORD)malloc(sizeof(DWORD) * nLength);
     LPDWORD tmpVirKey = m_lpdwVirtualKey;// 要屏蔽的底层键盘;
	 LPDWORD tmpConKey = m_lpdwContentKey;// 要屏蔽的底层键盘组合键;
     for (int i = 0; i < nLength; i++)
     {
         *tmpVirKey++ = *lpdwVirtualKey++;
		 *tmpConKey++ = *lpdwContentKey++;
     }


	 m_nLength = nLength;     
     // 安装底层键盘钩子
     m_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, m_hInstance, NULL);
     if (m_hHook == NULL) return FALSE;
     return TRUE;
}


// 停止屏蔽
SHIELDKEYBORDSAMPLE_API bool StopShieldKey()
{
     if (UnhookWindowsHookEx(m_hHook) == 0) return FALSE;
     m_hHook = NULL;
     return TRUE;
}





相关标签: dll