孙鑫VC学习(第20课-HOOK过程和数据库)

钩子过程主要是通过函数SetWindowsHookEx来实现的,现在是对WH_MOUSE进行屏幕,首先,新建一个基于对话框的MFC的EXE程序,在BOOL CSXLSN20Dlg::OnInitDialog()中加入如下代码:
HHOOK hmyHook;
hmyHook = SetWindowsHookEx(WH_MOUSE,(HOOKPROC)(MouseProc),NULL,GetCurrentThreadId());
hmyHook = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)(KeyboardProc),NULL,GetCurrentThreadId());

在CSXLSN20Dlg::OnInitDialog()函数之前加入如下的钩子函数:

LRESULT __stdcall MouseProc(
  int nCode,      // hook code
  WPARAM wParam,  // message identifier
  LPARAM lParam   // mouse coordinates
  ) 
{
return -2;//return >=1||<0;MOUSE消息被屏蔽了。return 0;MOUSE消息没有被屏蔽了。
}
LRESULT CALLBACK KeyboardProc(
 int code,       // hook code
 WPARAM wParam,  // virtual-key code
 LPARAM lParam   // keystroke-message information
 )
{
//if(wParam == 13) return 0;//13==VK_RETURN
//if(wParam == VK_RETURN || (1==(lParam>>29 & 1 ) && wParam == VK_F4)) return 1;//只屏蔽return 1;消息,其余消息不管,照系统默认的来处理 
//else return CallNextHookEx(g_keyboardHook,code,wParam,lParam);
//return 2;//return >=1||<0;WH_KEYBOARD消息被屏蔽了。return 0;KEYBOARD消息没有被屏蔽了。
if(wParam == VK_F2)//输入F2,程序直接退出
{
SendMessage(m_mywnd1,WM_CLOSE,0,0);
UnhookWindowsHookEx(g_keyboardHook);//把键盘的钩子过程取消,同理,可以取消鼠标的钩子过程
}
return 1;
}

将当前正在运行的所有线程的鼠标和键盘消息。安装钩子的代码要放到DLL中实现,下面就编写一个DLL。
新建一个WIN32的DLL工程,名字为HookDll。
源文件HookDll.cpp中的代码为:

#include <windows.h>
HHOOK g_hMouse;
HHOOK g_keyBoard;
HWND g_hwnd;
/*HINSTANCE g_hinst;
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,  // handle to the DLL module
DWORD fdwReason,     // reason for calling function
LPVOID lpvReserved   // reserved
)
{
g_hinst = hinstDLL;
return TRUE;
}
*/
LRESULT CALLBACK MouseProc(
  int nCode,      // hook code
  WPARAM wParam,  // message identifier
  LPARAM lParam   // mouse coordinates
  )
{
return 1;
}
LRESULT CALLBACK KeyboardProc(
 int code,       // hook code
 WPARAM wParam,  // virtual-key code
 LPARAM lParam   // keystroke-message information
 )
{
if (VK_F12 == wParam)
{
SendMessage(g_hwnd,WM_CLOSE,0,0);
UnhookWindowsHookEx(g_hMouse);
UnhookWindowsHookEx(g_keyBoard);
return 0;
}
return 1;
}
void setHook(HWND hwnd)
{
//HHOOK g_hMouse = SetWindowsHookEx(WH_MOUSE,MouseProc,g_hinst,0);
g_hwnd = hwnd;
g_hMouse = SetWindowsHookEx(WH_MOUSE,MouseProc,GetModuleHandle("HookDll"),0);
g_keyBoard = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle("HookDll"),0);
}

HookDll.def中的代码为:
LIBRARY HookDll
EXPORTS
setHook   @2 ;@2表示不想用系统导出的序号,想自己人为的改变这个函数的序号为2

工程/设置/link/object library modules中填入要链接的LIB文件的路径和名字,也可以,这种方法和把LIB文件放到测试目录下面是一样的效果。
在BOOL CHookDllTestDlg::OnInitDialog()加入如下代码:
//_declspec (dllimport) void setHook(HWND hwnd);//这个是静态加载的方法,记得在SETTING中设置一下……
BOOL CHookDllTestDlg::OnInitDialog()
{
//下面是动态加载的方法
// TODO: Add extra initialization here
HINSTANCE hinstLib = LoadLibrary("HookDll.dll"); 
typedef VOID (*MYPROC)(HWND hwnd); 
if (hinstLib != NULL) 

MYPROC ProcAdd= (MYPROC) GetProcAddress(hinstLib, "setHook"); 
ProcAdd(m_hWnd);

FreeLibrary(hinstLib);
//setHook(m_hWnd);//这个是静态加载的方法,记得在SETTING中设置一下,还要把DLL放在调用的文件夹下面
return TRUE;  // return TRUE  unless you set the focus to a control
}
此时可以看到,桌面上的所有线程的鼠标消息已经被屏蔽了。

接下来让用户始终看到我这个窗口,可以把这个窗口设置为顶层窗口,大小等于屏幕的大小,这样用户就看不到其它的窗口了。可以在CHookDllTestDlg::OnInitDialog()加入如下代码:SetWindowPos( &wndTopMost , 0, 0, GetSystemMetrics(SM_CXSCREEN), 
GetSystemMetrics(SM_CYSCREEN), SWP_NOMOVE|SWP_SHOWWINDOW  );但是此时的F12退出键只是针对本进程的,这是因为虽然DLL中的函数是对全体进程而言的,但是各个进程中的数据都有自己的COPY,数据不同步,如果想让F2变成所有进程的退出键,可以采用如下的办法:
此时只有按ALT+TAB把程序调到这个测试DLL的EXE时(被激活时),按F12才会起作用,如果在其它程序上面,F12没有起作用。原因分析:理论上所有进程可以共享DLL中的数据,但是WINDOWS采用了写入时COPY的机制,每个进程都有自己的数据,为了让F12对所有进程有效,设计一个结,然后让所有的进程共享这一个节,先看一下这个DLL的各个节的列表(进入DLL的DEBUG目录下,dumpbin -headers HookDll.dll)可以看到有很多节,像.text这个节,编译器在编译的时候就会把代码都放到这个.text这个节中,对于每个标准的节,都是以.开始的,每个节的信息权限等信息在下面都有。我们可以创建一个新的节,把变量放到这个新创建的节中。
如下是创建一个新的节,下面代码在DLL中添加如下代码:
#pragma data_seg( "MY_DATA" )  //注意名字不能超过8个,不然会自动截断
HWND g_hwnd=NULL;       //将g_hwnd这到这个节中,其余变量放到原先的节中,节中变量必须被初始化
#pragma data_seg( )
然后把节设置为共享的节,这样可以让多个进程共享,代码如下,在DLL中写下如下代码
#pragma comment(linker, "/SECTION:MY_DATA,RWS")//RWS表示这个节是读写共享
除了上述方法,还可以用下述方法把节变成一个共享的节:
在DEF文件中写如下代码:
SEGMENTS
MY_DATA READ WRITE SHARED   //读写和共享可以是小写字母,大小写无所谓
这里重新编译DLL工程,再重新运行DLLTEST工程,就可以在其它进程激活的时候,按F12退出了,因为这里的g_hwnd成了一个共享的数据,所以就都有效了。因为句柄值是同一个,当在发送WM_CLOSE发送消息时,就给这个句柄的窗口发送WM_CLOSE消息,那么调用者的窗口就退出了。

下面看看数据库编程方面:
先在VB中看下如何利用ADO访问数据库。VB中有一个ADO控件,在VB中增加ADO控件的方法,在空白的地方选择 部件,选择microsoft ADO Data Control 6.0(SP6),将它放到窗体上,在控件上面右击属性,弹出GENERAL页面,选择using connection string,单击build,在这个上面选择OLE DB的provider,点击for SQL Server的那个选项,点击下一步,在选择或输入服务器名称中,如果在本地机器上,可以输入.或者不输入,如果在远程机器上,要输入服务器的名字,然后输入名称和密码,如果选择不上,在选择数据库的时候会失败,选择pubs数据库,这个里面主要存放发行的图书和版本信息,点击测试连接,确定确定,再到recordsource下面,COMMAND TYPE选择 2.adcmdTable,表选择author,点击确定。接下来再添加一个控件,此控件叫数据网格控件,microsoft dataGrid control 6.0(SP6),在窗体上面放一个数据网格控件,在它的datasoruce属性下面选择adodc1,运行,就可以看到其中的一些数据,在此控件中改变的数据会存储到数据库当中,这个数据库应用可以对一个数据库进行查询并修改它。在数据网格上面右键,选择属性中的通用,选中允许添加和允许删除,就可以添加和删除数据了。

接下来用ADO的对象访问数据库,再打开一个VB工程,要在VB环境中添加ADO对象,在工程中添加引用,选择microsoft active data controls 2.6 library,选择VIEW 对象浏览器,可以查看ADODB,可以看到有很多对象,在窗体中放置一个列表框和BUTTON,点击BUTTON编辑代码,

下面是MFC中的数据库的应用:
新建一个基于对话框的MFC程序,先在MFC程序中导入"C:\Program Files\Common Files\System\ado\msado15.dll" 这个DLL,它是ADO2.6的版本,在stdafx.h中,加入如下语句:#import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","rsEOF")//no_namespace无命名空间,说明这是唯一的,因为文件的结尾也是EOF,为了避免混淆,在导入ADO库的时候要重命名一下,这时在这个MFC程序的文件目录下面的DEBUG目录下,有msado15.tlh(可以看作头文件)和msado15.tli(可以看作源文件)  这2个文件,把这2个文件加入到这个 MFC的工程下,可以看到这2个文件内容,这2个文件是当导入ADO库的时候,编译器在编译的时候自动生成的,当我们利用ADO技术访问数据库的时候,不需要导入这2个文件,我们导入只是为了查看方便。OLEDB是基于COM技术编写的,ADO是基于OLEDB技术基础之上的,它是OLEDB的客户程序,ADO本身也是一个COM组件,要使用COM组件,首先要初始化一个COM库,













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值