做了一个工业控制方面的程序,为了保持加工精度,不能在程序运行时再运行 别的应用程序。做了如下处理:鼠标不能动,键盘只能动ESC键,按下ESC键时退出程序。我做的处理如下:
//keymask.dll .cpp文件
#include "stdafx.h"
#include "KeyMask.h"
#include "stdlib.h"#pragma data_seg("mydata")
HHOOK glhHook = NULL; // 安装的鼠标钩子句柄
HINSTANCE glhInstance = NULL; // DLL实例句柄
#pragma data_seg() BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
glhInstance = (HINSTANCE) hModule; switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported variable
KEYMASK_API int nKeyMask=0;// This is an example of an exported function.
KEYMASK_API int fnKeyMask(void)
{
return 42;
}// This is the constructor of a class that has been exported.
// see KeyMask.h for the class definition
CKeyMask::CKeyMask()
{
return;
}
////////////////////////////////////////////////////////////////////////////////////
// 低级键盘钩子处理函数
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL fEatKeystroke = FALSE;
PKBDLLHOOKSTRUCT p = NULL; if (nCode == HC_ACTION)
{
p = (PKBDLLHOOKSTRUCT) lParam;
switch (wParam)
{
case WM_KEYDOWN:
// Backdoor to user information
if (p->vkCode == VK_ESCAPE)
{
int rv=::MessageBox(NULL,"退出打标?","确认",MB_YESNO|MB_DEFBUTTON2|MB_ICONEXCLAMATION);
if(rv==IDYES)
exit(1);
else
break;
}
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
fEatKeystroke = (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN) || // 屏蔽Win
// 屏蔽Alt+Tab
((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
// 屏蔽Alt+Esc
((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
// 屏蔽Ctrl+Esc
((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0))
||(p->vkCode==VK_NUMLOCK)||(p->vkCode==VK_CAPITAL)||
(p->vkCode==VK_RMENU)||(p->vkCode==VK_LMENU);
break;
default:
break;
}
} return (fEatKeystroke ? TRUE : CallNextHookEx(glhHook,nCode,wParam,lParam));
}void _stdcall StartKeyMask()
{
// 安装钩子
glhHook = SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,glhInstance,GetCurrentThreadId());
}void _stdcall StopKeyMask()
{
// 卸载钩子
if (glhHook!=NULL)
UnhookWindowsHookEx(glhHook);
}
编译成dll文件后在主程序如此调用:
.h文件
//变量定义和初始化
typedef (* IMPORT) (void);
HMODULE m_hDll;
IMPORT m_fStart;
IMPORT m_fStop;
m_hDll=LoadLibrary("KeyMask.dll");
if (m_hDll)
{
m_fStart =(IMPORT)
m_fStop =(IMPORT) GetProcAddress(m_hDll,"StopKeyMask");
}
//调用,循环做了简化
while(1)
{
if(m_fStart)m_fStart();
}
可是并没有达到屏蔽键盘的效果,也不能实现一按ESC键弹出询问是否退出的对话框
请问是什么原因?这个办法行不行?怎么解决?
注:本人水平不够,代码是借用网上的,再怎么为各位加分?感激不尽啊!
//keymask.dll .cpp文件
#include "stdafx.h"
#include "KeyMask.h"
#include "stdlib.h"#pragma data_seg("mydata")
HHOOK glhHook = NULL; // 安装的鼠标钩子句柄
HINSTANCE glhInstance = NULL; // DLL实例句柄
#pragma data_seg() BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
glhInstance = (HINSTANCE) hModule; switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported variable
KEYMASK_API int nKeyMask=0;// This is an example of an exported function.
KEYMASK_API int fnKeyMask(void)
{
return 42;
}// This is the constructor of a class that has been exported.
// see KeyMask.h for the class definition
CKeyMask::CKeyMask()
{
return;
}
////////////////////////////////////////////////////////////////////////////////////
// 低级键盘钩子处理函数
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL fEatKeystroke = FALSE;
PKBDLLHOOKSTRUCT p = NULL; if (nCode == HC_ACTION)
{
p = (PKBDLLHOOKSTRUCT) lParam;
switch (wParam)
{
case WM_KEYDOWN:
// Backdoor to user information
if (p->vkCode == VK_ESCAPE)
{
int rv=::MessageBox(NULL,"退出打标?","确认",MB_YESNO|MB_DEFBUTTON2|MB_ICONEXCLAMATION);
if(rv==IDYES)
exit(1);
else
break;
}
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
fEatKeystroke = (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN) || // 屏蔽Win
// 屏蔽Alt+Tab
((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
// 屏蔽Alt+Esc
((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
// 屏蔽Ctrl+Esc
((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0))
||(p->vkCode==VK_NUMLOCK)||(p->vkCode==VK_CAPITAL)||
(p->vkCode==VK_RMENU)||(p->vkCode==VK_LMENU);
break;
default:
break;
}
} return (fEatKeystroke ? TRUE : CallNextHookEx(glhHook,nCode,wParam,lParam));
}void _stdcall StartKeyMask()
{
// 安装钩子
glhHook = SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,glhInstance,GetCurrentThreadId());
}void _stdcall StopKeyMask()
{
// 卸载钩子
if (glhHook!=NULL)
UnhookWindowsHookEx(glhHook);
}
编译成dll文件后在主程序如此调用:
.h文件
//变量定义和初始化
typedef (* IMPORT) (void);
HMODULE m_hDll;
IMPORT m_fStart;
IMPORT m_fStop;
m_hDll=LoadLibrary("KeyMask.dll");
if (m_hDll)
{
m_fStart =(IMPORT)
m_fStop =(IMPORT) GetProcAddress(m_hDll,"StopKeyMask");
}
//调用,循环做了简化
while(1)
{
if(m_fStart)m_fStart();
}
可是并没有达到屏蔽键盘的效果,也不能实现一按ESC键弹出询问是否退出的对话框
请问是什么原因?这个办法行不行?怎么解决?
注:本人水平不够,代码是借用网上的,再怎么为各位加分?感激不尽啊!
这样截获到此按键消息,解除钩子!
{
CmyDoc* pDoc=GetDocument();
if(pMsg->message ==WM_KEYDOWN&&pMsg->wParam ==VK_ESCAPE)
{ int rv=::MessageBox(NULL,"退出?","确认",MB_YESNO|MB_DEFBUTTON2|MB_ICONEXCLAMATION);
if(rv==IDYES)
{
if(pDoc->m_fStop)
pDoc->m_fStop();
exit(1);
}
else
{
TranslateMessage(pMsg);
DispatchMessage(pMsg);
}
} // TODO: Add your specialized code here and/or call the base class
return CView::PreTranslateMessage(pMsg);
}
我的处理函数是在cmyDoc里面,如上面的死循环就是在其中的一个onbutton1()的函数里面。
我这样做了以后还是没有解决问题。请帮我看看
然后再看看getprocaddress的返回值!
m_hDll=LoadLibrary("KeyMask.dll");
if (m_hDll)
{m_fStart =(IMPORT) GetProcAddress(m_hDll,"StartKeyMask");
m_fStop =(IMPORT) GetProcAddress(m_hDll,"StopKeyMask");
}
返回值是正常的
只是在循环里面
while(1)
{
if(m_fStart)
m_fStart();//?它执行的情况如何?为什么截获不了键盘消息?
}
为了减轻这种痛苦,微软放了一个时间限制在这个hook上面. 当系统发送一个通知给一个低级键盘hook的过滤函数时,系统给这个函数一定的时间去执行.假如在允许时间内没有返回的话,系统将忽略它.并进行正常处理.这个时间通过LowLevelHooksTimeout值来实现(HKEY_CURRENT_USER\Control Panel\Desktop )
我用的是win2000 没有找到这个键值?
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE)
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}