比较烦琐,希望大家有耐心,谢谢。看了一个全局鼠标钩子的例子(查找钩子例子,很多都是这个,呵呵,是以前程序员大本营中打包的),是这样做的。
在DLL中自己写了个钩子类,并且定义了构造,析构,开始,停止函数。然后用#PRAGMA定义了若干全局的变量。它的开始函数是以一个目标窗口的句柄为参数。
鼠标钩子函数中把鼠标指向的窗口名称写给这个目标窗口(用SENDMESSAGE, WM-SETTEXT)。
然后是个对话框,采用隐式连接,给对话框类定义了一个钩子对象,然后在初始化过程中取得一个编辑框的句柄,用开始函数把钩子挂上。这样编辑框就出现鼠标指向窗口的名字。这都很正常。后来我把名字改成鼠标位置,也很好。
接下来,我想把开始函数的参数改成一个点,(点在对话框中定义)鼠标钩子函数把坐标写到这个点中,但为什么总都没有效果?是不是在DLL中不能访问应用程序的地址空间?但是调用DLL时不是把DLL影射到应用程序的地址空间了吗?
而且奇怪的是,一旦我把向这个点赋值的语句写到鼠标钩子函数中,就连设置窗口标题也都不执行,只显示程序刚开始运行时的鼠标坐标,而切我一旦使用这个点,程序执行时就会报什么内存不能为读的错误。
有无办法用这样方式传递?还是必须采用复杂的方式,比如什么WM-COPYDATA的?还有,在DLL中定义的共享数据,如何在应用程序中引用?后来是第二种尝试,我在DLL中加了一些导出函数,在导出函数中定义钩子对象,挂钩子等,编译可以通过,但试验效果好象是在外面引用这些函数,钩子始终没有挂上。这个DLL有MAIN函数,并且定义了一个全局HINSTANCE 对象,glhins,在DLLMAIN函数中把hinstance赋给这个对象,然后在钩子类的开始函数中,SETWINDOWSHOOKEX时把它做为第三个参数,我的导出函数没有作用是不是因为我这样子改了之后,程序根本没有走DLLMAIN ,这个对象始终是空的?所以钩子挂不上?如果我在没有DLLMAIN的DLL中挂钩子,那么第三个参数,也就是当前模块实例该用什么?或者怎么获得?比较麻烦,谢谢。
回头我看看能不能找到那个例子。
虽然用到钩子,不过我觉得这还属于DLL问题吧。

解决方案 »

  1.   

    (3)由于VC5没有现成的钩子类,所以要在项目目录中创建Mousehook.h文件,在其中建立钩子类:   class AFX_EXT_CLASS Cmousehook:public CObject   {   public:   Cmousehook();   //钩子类的构造函数   ~Cmousehook();   //钩子类的析构函数   BOOL starthook(HWND hWnd);   //安装钩子函数   BOOL stophook();   卸载钩子函数   };   (4)在Mousehook.app文件的顶部加入#include"Mousehook.h"语句;   (5)加入全局共享数据变量:   #pragma data_seg("mydata")   HWND glhPrevTarWnd=NULL;   //上次鼠标所指的窗口句柄   HWND glhDisplayWnd=NULL;   //显示目标窗口标题编辑框的句柄   HHOOK glhHook=NULL;   //安装的鼠标勾子句柄   HINSTANCE glhInstance=NULL;   //DLL实例句柄   #pragma data_seg()   (6)在DEF文件中定义段属性:   SECTIONS   mydata READ WRITE SHARED   (7)在主文件Mousehook.cpp的DllMain函数中加入保存DLL实例句柄的语句:   DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)   {   //如果使用lpReserved参数则删除下面这行   UNREFERENCED_PARAMETER(lpReserved);   if (dwReason == DLL_PROCESS_ATTACH)   {    TRACE0("MOUSEHOOK.DLL Initializing!\n");    //扩展DLL仅初始化一次    if (!AfxInitExtensionModule(MousehookDLL, hInstance))    return 0;    new CDynLinkLibrary(MousehookDLL);    //把DLL加入动态MFC类库中    glhInstance=hInstance;    //插入保存DLL实例句柄   }   else if (dwReason == DLL_PROCESS_DETACH)   {    TRACE0("MOUSEHOOK.DLL Terminating!\n");    //终止这个链接库前调用它    AfxTermExtensionModule(MousehookDLL);   }   return 1;   }   (8)类Cmousehook的成员函数的具体实现:   Cmousehook::Cmousehook()   //类构造函数   {   }   Cmousehook::~Cmousehook()   //类析构函数   {   stophook();   }   BOOL Cmousehook::starthook(HWND hWnd)   //安装钩子并设定接收显示窗口句柄   {   BOOL bResult=FALSE;   glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0);   if(glhHook!=NULL)    bResult=TRUE;   glhDisplayWnd=hWnd;   //设置显示目标窗口标题编辑框的句柄   return bResult;   }   BOOL Cmousehook::stophook()   //卸载钩子   {   BOOL bResult=FALSE;   if(glhHook)   {    bResult= UnhookWindowsHookEx(glhHook);    if(bResult)    {    glhPrevTarWnd=NULL;    glhDisplayWnd=NULL;//清变量    glhHook=NULL;    }   }   return bResult;   }   (9)钩子函数的实现:   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(glhHook,nCode,wparam,lparam);    //继续传递消息   }   (10)编译项目生成mousehook.dll。   2.创建钩子可执行程序   (1)用MFC的AppWizard(EXE)创建项目Mouse;   (2)选择“基于对话应用”并按下“完成”键;   (3)编辑对话框,删除其中原有的两个按钮,加入静态文本框和编辑框,用鼠标右键点击静态文本框,在弹出的菜单中选择“属性”,设置其标题为“鼠标所在的窗口标题”;   (4)在Mouse.h中加入对Mousehook.h的包含语句#Include"..\Mousehook\Mousehook.h";   (5)在CMouseDlg.h的CMouseDlg类定义中添加私有数据成员:   CMouseHook m_hook;//加入钩子类作为数据成员   (6)修改CmouseDlg::OnInitDialog()函数:   BOOL CMouseDlg::OnInitDialog()   {   CDialog::OnInitDialog();   ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);   ASSERT(IDM_ABOUTBOX < 0xF000);   CMenu* pSysMenu = GetSystemMenu(FALSE);   if (pSysMenu != NULL)   {    CString strAboutMenu;    strAboutMenu.LoadString(IDS_ABOUTBOX);    if (!strAboutMenu.IsEmpty())    {    pSysMenu->AppendMenu(MF_SEPARATOR);    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);    }   }   SetIcon(m_hIcon, TRUE);//Set big icon   SetIcon(m_hIcon, FALSE);//Set small icon   //TODO: Add extra initialization here   CWnd * pwnd=GetDlgItem(IDC_EDIT1);   //取得编辑框的类指针   m_hook.starthook(pwnd->GetSafeHwnd());   //取得编辑框的窗口句柄并安装钩子   return TRUE;   //return TRUE unless you set the focus to a control   }   (7)链接DLL库,即把..\Mousehook\debug\Mousehook.lib加入到项目设置链接标签中;  还是这个老例子,呵呵。
    我主要改了鼠标钩子函数。
    LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam)   {   LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam;    if (nCode>=0)    { 
       char szCaption[100]; 
         sprintf(sz,“%d,%d”,pmousehook-》pt。x,pmousehook-》pt。y);   SendMessage(glhDisplayWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption);  
         //我在这里试图向一个点写值。
       }    return CallNextHookEx(glhHook,nCode,wparam,lparam);    //继续传递消息   } 
      

  2.   

    忽然有个想法,
    我在DLL的导出函数中这样用,是不是相当与执行模块与钩子模块就在一起了?所以要挂全局钩子,肯定是挂不上的,如果我要使用这样的导出函数,是不是需要自己再写一个DLL(就相当于那个对话框了),然后在那里连接这个DLL?
      

  3.   

    HANDLE hDllIns=GetModuleHandle(“dllname”)
      

  4.   

    我在DLL内部也可以这样用吗?
    自己获得自己的实例句柄?
    而且,那个参数应该十HINSTANCE类型的,可以吗?
    是不是我的问题说的太长了,没人响应啊。