做了一个工业控制方面的程序,为了保持加工精度,不能在程序运行时再运行 别的应用程序。做了如下处理:鼠标不能动,键盘只能动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键弹出询问是否退出的对话框
请问是什么原因?这个办法行不行?怎么解决?
注:本人水平不够,代码是借用网上的,再怎么为各位加分?感激不尽啊!

解决方案 »

  1.   

    把esc的判断放在pretranslatemessage里
    这样截获到此按键消息,解除钩子!
      

  2.   

    BOOL CmyView::PreTranslateMessage(MSG* pMsg) 
    {
    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()的函数里面。
    我这样做了以后还是没有解决问题。请帮我看看 
      

  3.   

    如果你觉得没调用呢,看看你loadlibrary的返回值
    然后再看看getprocaddress的返回值!
      

  4.   

    初始化的时候
    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();//?它执行的情况如何?为什么截获不了键盘消息?
    }
      

  5.   

    据说:WH_KEYBOARD_LL hook.这个hook将被用于用户输入后,系统接收到它们之前进行处理.但是这个hook又一个严重的缺点:容易引起无限循环或者挂起. 假如这样发生了,系统就不能正确的处理击键消息了.
    为了减轻这种痛苦,微软放了一个时间限制在这个hook上面. 当系统发送一个通知给一个低级键盘hook的过滤函数时,系统给这个函数一定的时间去执行.假如在允许时间内没有返回的话,系统将忽略它.并进行正常处理.这个时间通过LowLevelHooksTimeout值来实现(HKEY_CURRENT_USER\Control Panel\Desktop )
    我用的是win2000 没有找到这个键值?
      

  6.   

    在你的循环中加入:MSG msg;
    while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE)
    {
    TranslateMessage( &msg );
    DispatchMessage( &msg );
    }