MFC动态链接库以及全局钩子函数操作

    关于动态链接库以及钩子过程的概念这里不多说,请参考孙鑫的VC++ 深入详解!

    我们知道Inner Hook只能屏蔽当前进程的主线程的鼠标消息和键盘消息,如果要想屏蔽当前运行的所有进程的鼠标消息和键盘消息,那么安装钩子过程的代码必须放入动态链接库中。

   下面钩子过程的目的:屏蔽所有的鼠标消息以及除了F2以外的键盘消息,当按下F2,调用此钩子过程的应用程序退出,同时卸载钩子过程,你就可以趁别人不注意的时候在其电脑上安装这个应用程序^___^,恶作剧开始了,不知道后门的就只能重启电脑了!

Hook.h

#include<windows.h>
#include<stdio.h>
#define DLL_API extern "C" __declspec(dllimport) //extern "C"保证导出函数的函数名不发生改变
DLL_API void  SetHook(HWND hwnd);

Hook.cpp


为Hook.dll创建一个共享的节,把全局变量g_hWnd放入此节中,让全局变量在多个进程中共享。

#include "Hook.h" 

#pragma  data_seg("MySec")  //定义一个新节,将全局变量放入这个节中,用于共享
HWND g_hWnd = NULL;
#pragma  data_seg()
#pragma  comment(linker,"/section:MySec,RWS") //设置为共享的节


HHOOK g_hMouse = NULL;
//HHOOK g_hKeyBoard = NULL;
HHOOK g_hKeyBoardLL = NULL;
//鼠标钩子回调函数
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam){
	return 1; //return ture说明全部屏蔽
}
/*
//键盘钩子回调函数
LRESULT CALLBACK KeyBoardProc(int code, WPARAM wParam, LPARAM lParam){
	if (VK_F2==wParam)
	{
		//当按下F2则退出调用这个dll的应用程序
		::SendMessage(g_hWnd, WM_CLOSE, 0, 0);
		UnhookWindowsHookEx(g_hMouse);
		UnhookWindowsHookEx(g_hKeyBoard);
	}	
	return 1; //return ture说明全部屏蔽
}
*/
//低级键盘钩子函数用来屏蔽功能键以及组合键
LRESULT CALLBACK KeyBoardLLProc(int code, WPARAM wParam, LPARAM lParam){
	if (code == HC_ACTION)
	{

		KBDLLHOOKSTRUCT *kblp = (KBDLLHOOKSTRUCT*)lParam; //这个结构体暂时没怎么搞明白,官方msdn也写的不是很明白,有待琢磨
		if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN==wParam)  //如果按键为按下状态

		{
			if (kblp->vkCode == VK_LWIN || kblp->vkCode == VK_RWIN)     //屏敝 WIN (左右)

			{
				return TRUE;//表示已处理该消息
			}
			if (kblp->vkCode == 0x4D && ((GetKeyState(VK_LWIN) & 0x8000) ||

				(GetKeyState(VK_RWIN) & 0x8000)))						//屏敝 WIN+D 组合键(左右)
			{
				return TRUE;

			}
			if (kblp->vkCode == 0x44 && ((GetKeyState(VK_LWIN) & 0x8000) ||

				(GetKeyState(VK_LWIN) & 0x8000)))						//屏敝 WIN+M 组合键(左右)

			{

				return TRUE;

			}
			if (kblp->vkCode == VK_ESCAPE && GetKeyState(VK_CONTROL) & 0x8000) //屏敝 CTRL + ESC 组合键

			{

				return TRUE;

			}
			if (kblp->vkCode == VK_CONTROL) //屏敝 CTRL键

			{

				return TRUE;

			}

			if (kblp->vkCode == VK_TAB && kblp->flags & LLKHF_ALTDOWN) //屏敝 ATL + TAB 组合键

			{

				return TRUE;

			}

			if (kblp->vkCode == VK_ESCAPE && kblp->flags & LLKHF_ALTDOWN) //屏敝 ATL + ESC 组合键

			{

				return TRUE;

			}
			if (kblp->vkCode==VK_F2)
			{
				//当按下F2则退出调用这个dll的应用程序
				::SendMessage(g_hWnd, WM_CLOSE, 0, 0);
				UnhookWindowsHookEx(g_hMouse);
				UnhookWindowsHookEx(g_hKeyBoardLL);
			}
		}
	}
	return TRUE;
	//传给下一个钩子
	//return CallNextHookEx(g_hKeyBoard, code, wParam, lParam); 
}
void SetHook(HWND hwnd){
	g_hWnd = hwnd;
	g_hMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandle("HookDll"), 0);
	g_hKeyBoardLL = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardLLProc, GetModuleHandle("HookDll"), 0);
	//g_hKeyBoard = SetWindowsHookEx(WH_KEYBOARD, KeyBoardProc, GetModuleHandle("HookDll"), 0);
}

Hook.def文件:保证导出函数的函数名称不发生改变

LIBRARY HookDll

EXPORTS
SetHook


我们可以在以上代码的基础上做一个电脑屏保程序:新建一个MFC对话框程序,然后设置窗口的大小为屏幕的大小,最后在窗口上实现我们想要实现的功能,比如:显示时间,显示动画等等!以下是我的屏保程序界面截图:只有按下F2才会退出,代码实现起来也是非常简单!


核心代码如下所示:

BOOL CScreenProtectDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	int cxScreen, cyScreen;
	cxScreen = GetSystemMetrics(SM_CXSCREEN);
	cyScreen = GetSystemMetrics(SM_CYSCREEN);
	SetWindowPos(&wndTopMost, 0, 0, cxScreen, cyScreen, SWP_NOMOVE | SWP_NOACTIVATE);
	//HideTaskBar(FALSE);
	typedef void (* HOOKPROC)(HWND hwnd);
	HOOKPROC lpfnDllFuncHook;    // Function pointer
	hDLL = LoadLibrary(_T("HookDll.dll"));//加载动态链接库
	if (hDLL != NULL)
	{
		lpfnDllFuncHook = (HOOKPROC)GetProcAddress(hDLL, "SetHook");
		if (lpfnDllFuncHook != NULL)
		{
			// call the function
			lpfnDllFuncHook(m_hWnd);
		}
	}
	ShowCursor(FALSE);//隐藏鼠标
	SetTimer(1, 1000, NULL);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CScreenProtectDlg::OnPaint()
{
	 CPaintDC dc(this); // device context for painting
	 CDC*MemDC = new CDC();//定义一个显示设备对象
	 GetClientRect(m_rcClient);
	 dc.FillSolidRect(m_rcClient, RGB(192,192,192));	
	 CFont*pOldFont,font;
	 COLORREF pOldColor;
	 CBitmap MemBitmap;
	 CBitmap *OldBitmap;	
	 CString	str="",str1="";
	 font.CreatePointFont(m_rcClient.Width()/2, _T("Arial Bold"));
	 CTime	t = CTime::GetCurrentTime();	 
	 str1.Format(_T("%04d/%d/%d"), t.GetYear(), t.GetMonth(), t.GetDay());
	 str.Format(_T("TIME: %02d:%02d:%02d %s"),t.GetHour(), t.GetMinute(), t.GetSecond(),((t.GetHour() >= 12) ? _T("PM") : _T("AM")));
	 MemDC->CreateCompatibleDC(&dc);
	 MemBitmap.CreateCompatibleBitmap(&dc, m_rcClient.Width(), m_rcClient.Height());
	 OldBitmap = MemDC->SelectObject(&MemBitmap);
	 pOldColor = MemDC->SetTextColor(RGB(108, 108, 108));  //0 255 192
	 pOldFont = MemDC->SelectObject(&font);
	 //先用背景色将位图清除干净
	 MemDC->FillSolidRect(0, 0, m_rcClient.Width(), m_rcClient.Height(), RGB(192, 192, 192));
	 MemDC->TextOut(m_rcClient.Width()/3, m_rcClient.Height()/8, str1);
	 MemDC->TextOut(m_rcClient.Width()/6,m_rcClient.Height()/2.5,str);
	 MemDC->TextOut(m_rcClient.Width()/1.4, m_rcClient.Height()/1.3, "EasyLiu");
	 //将内存中的图拷贝到屏幕上进行显示
	 dc.BitBlt(0, 0, m_rcClient.Width(), m_rcClient.Height(), MemDC, 0, 0, SRCCOPY);
	 MemDC->SelectObject(OldBitmap);
	 MemDC->SelectObject(pOldFont);
	 MemDC->SelectObject(&pOldColor);
	 MemBitmap.DeleteObject();
	 OldBitmap->DeleteObject();
	 font.DeleteObject();
	 pOldFont->DeleteObject();
	 MemDC->DeleteDC();
	 delete MemDC;	
}

void CScreenProtectDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: Add your message handler code here and/or call default
	if (nIDEvent==1)
	{
		Invalidate();
	}
	CDialogEx::OnTimer(nIDEvent);
}


最后面讲一下动态链接库的加载方式

  动态链接库有两种加载方式:隐式链接加载动态链接库和动态加载动态链接库。

    1、隐式链接加载动态链接库

   如果有XXX.h ,XXX.lib ,XXX.dll,这样就可以隐式链接加载了。

   把这三个文件复制到工程目录下面,当发布应用程序的时候需要把XXX.dll文件放在Debug或者Release目录下面

   在所要引用的.cpp文件中加入#include"XXX.h", #pragma  comment(lib,"XXX") ,这样就可以使用dll中封装的函数了。

    其中其中语句“#pragma comment(lib,"XXX")”可以用工程设置对话框的设置来代替:就是右击工程,属性--》链接--》输入,加入lib文件所在的目录,比如我们在工程目录下面新建了一个文件夹:lib,然后把XXX.lib放在了这个目录下面,那么就应该在输入项里面输入:..\lib\XXX.lib。

                                                                    2、动态加载动态链接库

   如果只提供了XXX.dll,那么就需要用到动态加载了。

    动态加载主要通过LoadLibrary,GetProcAddress,FreeLibrary这三个函数来实现,代码如下:

typedef void (* HOOKPROC)(HWND hwnd);
	HOOKPROC lpfnDllFuncHook;    // Function pointer
	hDLL = LoadLibrary(_T("HookDll.dll"));
	if (hDLL != NULL)
	{
		lpfnDllFuncHook = (HOOKPROC)GetProcAddress(hDLL, "SetHook");
		if (lpfnDllFuncHook != NULL)
		{
			// call the function
			lpfnDllFuncHook(m_hWnd);
		}
	}

在析构函数中:
if (hDLL!=NULL)
	{
		FreeLibrary(hDLL);
	}	


    

   

    




  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值