我本想通过鼠标钩子来将鼠标在屏幕上的坐标(鼠标可能不在本程序窗口中)显示在我的应用程序中的对话框中。原理是:在DLL中设置一个 HWND hwnd, 在DLL 中建立一函数SetWnd(HWND hWnd_p),应用程序通过此函数将应用程序的窗口句柄传给DLL,钩子函数通过 SendMessage(...)给应用程序发消息,程序负责显示。但我发现当鼠标移到别的窗口时,已被赋值的 hWnd 变为了NULL,后来用键盘钩子来试却不会,不知为什么,请大家一定要帮忙,我已被折摩好久了
说明:
 1、MouseProc()函数中的代码是为了测试才这样写的
 2、hIns 已被赋值,代码未写出来,
 3、鼠标位于本程序窗口时正常,钩子函数也能钩到鼠标消息#pragma data_seg("_MyData")
HHOOK     hook = NULL;
HWND      hWnd = NULL;
HINSTANCE hIns = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:_MyData, RWS")//设置钩子
BOOL DLLEXPORT CALLBACK InstallHook()
{
   hook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC )MouseProc, hIns, 0);    
   return (hook != NULL);
}
//应用程序通过此函数将应用程序的窗口 HWND 传给钩子, hWnd在上面有定义
void DLLEXPORT  CALLBACK SetWnd(HWND hWnd_p)
{
hWnd = hWnd_p; 
}
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if( nCode < 0 )
return CallNextHookEx(hook, nCode, wParam, lParam); if ( nCode == HC_ACTION ){
CString str;
POINT pt;
pt.x = rand() % 800;
pt.y = rand() % 600;
str.Format("%d, %d", pt.x, pt.y);
                 if( hWnd == NULL){ //当设置鼠标钩子且鼠标移到应用程序窗口以外的窗口时就会
                                   //显示下面的AfxMessageBox(),当设置键盘钩子且在别的
                                   //窗口按下一个键时也不会显示,经过测试发现当设置鼠标钩
                                   //子显鼠标不在本窗口时 hWnd == NULL,但键盘钩子却不会
  AfxMessageBox(str);
                }
} return CallNextHookEx(hook, nCode, wParam, lParam);
}

解决方案 »

  1.   

    ////////////////////////////////////////////////////////////////////////////////////////
    //
    //头文件:HOOK.h
    //
    //源文件:HOOK.CPP
    //
    //功能:钩子
    //
    //作者:徐怀移
    //
    //时间:2005年12月13日
    //
    //
    //
    //
    ////////////////////////////////////////////////////////////////////////////////////////// HOOK.cpp : 定义 DLL 的初始化例程。
    //#include "stdafx.h"
    #include "HOOK.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #endif//
    // 注意!
    //
    // 如果此 DLL 动态链接到 MFC
    // DLL,从此 DLL 导出并
    // 调入 MFC 的任何函数在函数的最前面
    // 都必须添加 AFX_MANAGE_STATE 宏。
    //
    // 例如:
    //
    // extern "C" BOOL PASCAL EXPORT ExportedFunction()
    // {
    // AFX_MANAGE_STATE(AfxGetStaticModuleState());
    // // 此处为普通函数体
    // }
    //
    // 此宏先于任何 MFC 调用
    // 出现在每个函数中十分重要。这意味着
    // 它必须作为函数中的第一个语句
    // 出现,甚至先于所有对象变量声明,
    // 这是因为它们的构造函数可能生成 MFC
    // DLL 调用。
    //
    // 有关其他详细信息,
    // 请参阅 MFC 技术说明 33 和 58。
    //// CHOOKApp#pragma data_seg ("shared")
    HWND hwnd=NULL; //接收窗口的指针KBDLLHOOKSTRUCT kbkey={0};MSLLHOOKSTRUCT mouse={0};#pragma data_seg () #pragma comment(linker,"/SECTION:shared,RWS")
    BEGIN_MESSAGE_MAP(CHOOKApp, CWinApp)
    END_MESSAGE_MAP()
    // CHOOKApp 构造CHOOKApp::CHOOKApp()
    {
    // TODO: 在此处添加构造代码,
    // 将所有重要的初始化放置在 InitInstance 中
    }
    // 唯一的一个 CHOOKApp 对象CHOOKApp theApp;
    // CHOOKApp 初始化BOOL CHOOKApp::InitInstance()
    {
    CWinApp::InitInstance(); return TRUE;
    }
    HHOOK phook[2]={0,0};
    LRESULT WINAPI  LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) //钩子函数
    { if(nCode==HC_ACTION)
    { mouse=*(MSLLHOOKSTRUCT*)lParam;
    PostMessage(hwnd,WM_MOUSEHOOK,(WPARAM)&mouse,wParam);

    } return   CallNextHookEx(phook[1],nCode, wParam,lParam);
    }
    LRESULT WINAPI  LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) //钩子函数
    { kbkey = *(KBDLLHOOKSTRUCT *) lParam;
           switch (nCode)
        {
            case HC_ACTION:
    TRACE("%d\n",::GetFocus());
    PostMessage(hwnd,WM_KEYHOOK,(WPARAM)&kbkey,wParam);// return 1;

           
                // Check to see if the CTRL key is pressed
                // bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);
                
                // Disable CTRL+ESC
               // if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown)
                 //   return 1;            // Disable ALT+TAB
                if (kbkey.vkCode == VK_TAB && kbkey.flags & LLKHF_ALTDOWN)
                    return 1;
    if(kbkey.vkCode==91)
    return 1;

                // Disable ALT+ESC
                //if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN)
                 //   return 1;

                
            
            default:            break;
        }
    return   CallNextHookEx(phook[0],nCode, wParam,lParam);}void WINAPI AddHook(HWND wnd) //安装钩子
    { hwnd=wnd; if(phook[0]!=NULL)
    {
    UnhookWindowsHookEx(phook[0]);
    } if(phook[1]!=NULL)
    {
    UnhookWindowsHookEx(phook[1]);
    }
    phook[0]=SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,theApp.m_hInstance,0);
    phook[1]=SetWindowsHookEx(WH_MOUSE_LL,LowLevelMouseProc,theApp.m_hInstance,0);
    /*
    HHOOK SetWindowsHookEx( 
         int idHook,      // 钩子的类型,即它处理的消息类型
         HOOKPROC lpfn,   // 钩子子程的地址指针。如果dwThreadId参数为0
       // 或是一个由别的进程创建的线程的标识,
       // lpfn必须指向DLL中的钩子子程。
       // 除此以外,lpfn可以指向当前进程的一段钩子子程代码。
       // 钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。
         HINSTANCE hMod,  // 应用程序实例的句柄。标识包含lpfn所指的子程的DLL。
       // 如果dwThreadId 标识当前进程创建的一个线程,
       // 而且子程代码位于当前进程,hMod必须为NULL。
       // 可以很简单的设定其为本应用程序的实例句柄。
         DWORD dwThreadId // 与安装的钩子子程相关联的线程的标识符。
       // 如果为0,钩子子程与所有的线程关联,即为全局钩子。
                     );
     */}void WINAPI DelHook() //御载钩子
    {

    if(phook[0]!=NULL)
    { UnhookWindowsHookEx(phook[0]); phook[0]=NULL;
    }
    if(phook[1]!=NULL)
    { UnhookWindowsHookEx(phook[1]); phook[1]=NULL;
    }

    }
    我在 XP 里是可以用的
      

  2.   

    to: iyaosan(修炼中) ( )
    你好,很感谢你的回复,但不知你的 hwnd 你是在哪里赋值的呢?
    PostMessage(hwnd,WM_MOUSEHOOK,(WPARAM)&mouse,wParam);我的程序之所以不行,就是因为鼠标移动其它窗口时 hwnd 的值自动变为 NULL,而鼠标移到本窗口时却不会。对于键盘HOOK, 则无论在哪个窗口按键盘, hwnd 却不会变为 NULL。
    我用的是WIN2000
      

  3.   

    to: iyaosan(修炼中) ( )
      不好意思,对于键盘消息 hwnd 也会变成 NULL,(之前不小心把if语句给删了)
      

  4.   

    你修改过你的DLL后,有没有将你的.dll,.h文件,.lib文件(别漏了一样)拷贝给你的测试程序,另外对于MFC动态库的DLL,最好在每个函数中加上
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    如果实在不行的话,建议直接用win32 dll,不要用MFC dll
      

  5.   

    非常感谢 iyaosan(修炼中) 和 xiaoqiqixiao(七七) 。
    我的QQ现在用不了,我先记下你的,以后再向你们赐教!