http://download.csdn.net/detail/handanxiaoliang/4386358
WH_CALLWNDPROC 系统将消息发送到指定窗口之前的“钩子”
WH_CALLWNDPROCRET 消息已经在窗口中处理的“钩子”
WH_CBT 基于计算机培训的“钩子”
WH_DEBUG 差错“钩子”
WH_FOREGROUNDIDLE 前台空闲窗口“钩子”
WH_GETMESSAGE 接收消息投递的“钩子”
WH_JOURNALPLAYBACK 回放以前通过WH_JOURNALRECORD“钩子”记录的输入消息
WH_JOURNALRECORD 输入消息记录“钩子”
WH_KEYBOARD 键盘消息“钩子”
WH_MOUSE 鼠标消息“钩子”
WH_MSGFILTER 对话框、消息框、菜单或滚动条输入消息“钩子”
WH_SHELL 外壳“钩子”
WH_SYSMSGFILTER 系统消息“钩子”
HHOOK SetWindowsHookEx(int idHook;HOOKPROC lpfn;HINSTANCE hMod;DWORD dwThreadId); |
BOOL UnhookWindowsHookEx(HHOOK hhk); |
LRESULT CallNextHookEx(HHOOK hhk;int nCode;WPARAM wParam;LPARAM lParam); |
BOOL CMouseHook::StartHook(HWND hWnd)
{
BOOL result = FALSE;
// 安装钩子
glhHook = (HWND)SetWindowsHookEx(WH_MOUSE, MouseProc, glhInstance, 0);
if (glhHook != NULL)
result = TRUE;
glhDisplayWnd = hWnd; // 设置显示目标窗口标题编辑框的句柄
return result;
}
LRESULT WINAPI MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
LPMOUSEHOOKSTRUCT pMouseHook = (MOUSEHOOKSTRUCT FAR *) lParam;
if (nCode >= 0) {
HWND glhTargetWnd = pMouseHook->hwnd; // 取目标窗口句柄
HWND ParentWnd = glhTargetWnd;
while (ParentWnd != NULL){
glhTargetWnd = ParentWnd;
ParentWnd = GetParent(glhTargetWnd); // 取应用程序主窗口句柄
}
if (glhTargetWnd != glhPrevTarWnd) {
char szCaption[100];
GetWindowText(glhTargetWnd, szCaption, 100); // 取目标窗口标题
if (IsWindow(glhDisplayWnd))
SendMessage(glhDisplayWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)szCaption);
glhPrevTarWnd = glhTargetWnd; // 保存目标窗口
}
}
// 继续传递消息
return CallNextHookEx((HHOOK)glhHook, nCode, wParam, lParam);
}
BOOL CMouseHook::StopHook()
{
BOOL result = FALSE;
if (glhHook){
result = UnhookWindowsHookEx((HHOOK)glhHook); // 卸载钩子
if (result)
glhDisplayWnd = glhPrevTarWnd = glhHook = NULL;
}
return result;
}
目前开发的项目和MES类似,但功能超过了MES,客户的一些设备的运行数据采集是通过一个工控机上MFC程序实现的,可以采集ACCESS、SQL Server 2000数据库表中数据条目,机器数据都是1分钟增加一条历史数据,所以采集的时间间隔也是1分钟左右。但是现场的工人会将数据采集软件关闭,所以取消了关闭按钮的效果,但是还是存在于任务栏里,有的看到了会进行强制关闭,所以现在加了一条可以隐藏的功能,用Ctrl + Q 实现置标志位的功能,定时器实现按照标志位进行数据采集软件的显示和隐藏的效果切换。
具体实现过程如下:
MFC程序APP 源文件中声明钩子程序并实现,g_show_wnd是一个全局变量,在APP源文件要声明为外部的 extern ,用来确定窗口的显示或隐藏:
//一个拦截系统消息的钩子程序事例
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
if (nCode == HC_ACTION)
{
int vKey = LOBYTE(p->vkCode);
//如果为键盘消息
if (wParam == WM_KEYDOWN)
{
switch(vKey)
{
case 'q':
case 'Q':
{
//如果用户按下了Win + D键盘消息
if(::GetKeyState(VK_CONTROL) < 0)
{
///do anything here///
//AfxMessageBox("QQQ");
g_show_wnd = 1;
}
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
}
在APP源文件的初始化实例函数中调用,其中第一个参数 WH_KEYBOARD_LL 是最底层挂钩 ,监视键盘敲击
BOOL CKApp::InitInstance ()
{
HHOOK hhkKybd = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
AfxGetApp()->m_hInstance, 0);
//...//
...
//...//
}
在窗口源文件中定义全局变量g_show_wnd 赋初始值1,设置定时器在窗口显示前系统调用的函数BOOL CKMainWnd::OnCreateClient (LPCREATESTRUCT lpcs, CCreateContext *pContext)中:
{
//处理窗口显示或者隐藏
SetTimer(SHOW_MAIN_WINDOW ,2000, NULL);
//...
...
//...
}
定时器函数中实现判断,清标志位的效果:
{
if(SHOW_MAIN_WINDOW == nIDEvent)
{
if (1 == g_show_wnd)
{
BOOL bshow = IsWindowVisible();
if (bshow)
{
ShowWindow(SW_HIDE);
}
else
{
ShowWindow(SW_SHOW);
}
g_show_wnd = 0;
}
}
//
...
//
}
通过上面的程序,当程序运行时,如果用户在键盘上点击Ctrl+q组合键,就可以显示软件窗口,如果再点击一次组合键,就可以隐藏软件窗口,
隐藏时任务管理器中应用程序看不到该采集软件,但是进程管理器可以看到。
-
顶