全局键盘钩子在主程序最小化的时候可以截取到键盘信息,可是如果主程序隐藏到系统托盘就失灵了是为什么。
以下是dll钩子源码:
// MouseClickDll.cpp : Defines the initialization routines for the DLL.
//#include "stdafx.h"
#include "MouseClickDll.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endifBEGIN_MESSAGE_MAP(CMouseClickDllApp, CWinApp)
//{{AFX_MSG_MAP(CMouseClickDllApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
//    DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CMouseClickDllApp::CMouseClickDllApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}/////////////////////////////////////////////////////////////////////////////
// The one and only CMouseClickDllApp objectCMouseClickDllApp theApp;
//安装钩子
DllExport void WINAPI InstallLaunchEv()
{
if(Hook == NULL)
{
Init();
Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)LauncherHook,theApp.m_hInstance,0);
//Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)LauncherHook,GetModuleHandle(NULL),0);

}
/*if(MouseHook == NULL)
{
MouseHook = (HHOOK)SetWindowsHookEx(WH_MOUSE,(HOOKPROC)LauncherMouseHook,theApp.m_hInstance,0);
}*/
} //键盘钩子
LRESULT CALLBACK LauncherHook(int nCode,WPARAM wParam,LPARAM lParam)
{
MessageBeep(-1);
if(nCode >= HC_ACTION)
{
if(lParam < 0)
        {
char key[1];
key[0] = wParam;
if(key[0] == 123)
{
//GetCurrentPath();
//AfxMessageBox(CurrentPath);
if(!bIsRun){
bIsRun = TRUE;
CreateMyThread();
//AfxMessageBox("已开启");
}else
{
bIsRun = FALSE;
//AfxMessageBox("已停止");
}
}
if(key[0] == 122)
{
bIsRun = FALSE;
//AfxMessageBox("已停止");
}
}

}
return CallNextHookEx(Hook,nCode,wParam,lParam);
}
//鼠标钩子
LRESULT CALLBACK LauncherMouseHook(int nCode,WPARAM wParam,LPARAM lParam)
{
MessageBeep(-1);
return CallNextHookEx(Hook,nCode,wParam,lParam);
}
//建立线程
void CreateMyThread()
{
//AfxMessageBox(pFileName);
pThread = AfxBeginThread(MouseClick,(LPVOID)NULL);
}
//线程函数
UINT MouseClick(LPVOID pParam)
{
ReadCurrentPathFromReg();//从注册表中得到当前路径
ReadConfig();
OperationIndex = 0;
while(bIsRun && OperationIndex<OperationEndIndex)
{
switch(Operation[OperationIndex])
{
case DELAY_TIME:
Sleep(Operation[++OperationIndex]);
//AfxMessageBox("延时");
break;
case LEFT_MOUSEKEY_DOWN:
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
//AfxMessageBox("按下");
break;
case LEFT_MOUSEKEY_UP:
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
//AfxMessageBox("抬起");
break;
case RIGHT_MOUSEKEY_DOWN:
mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
//AfxMessageBox("右键按下");
break;
case RIGHT_MOUSEKEY_UP:
mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
//AfxMessageBox("右键抬起");
break;
case LOOP_START:
//AfxMessageBox("循环开始");
break;
case LOOP_END:
OperationIndex = LoopStartIndex;
//AfxMessageBox("循环结束");
break;
case KEY_DOWN:
keybd_event(Operation[++OperationIndex],0,0,0);
break;
case KEY_UP:
keybd_event(Operation[++OperationIndex],0,KEYEVENTF_KEYUP,0); 
break;
}
OperationIndex++;
//Sleep(2000);


//AfxMessageBox(CString(*a)); }
return TRUE;
}//存按键日志
void SaveLog(char* c)
{
CTime tm=CTime::GetCurrentTime();
CString name;
name.Format(CurrentPath+"key_%d_%d.log",tm.GetMonth(),tm.GetDay());
CFile file;
if(!file.Open(name,CFile::modeReadWrite))
{
file.Open(name,CFile::modeCreate|CFile::modeReadWrite);
}
file.SeekToEnd();
file.Write(c,1);
file.Close();
}
//读取配制文件
void ReadConfig()
{
CString strLine;
CStdioFile csFile;
CString cp = CurrentPath+"config.txt";
memcpy(pFileName,cp,cp.GetLength());
TRY    
{    
csFile.Open(pFileName,CFile::modeRead);    
}CATCH(CFileException, e)
{    
csFile.Abort();    
THROW_LAST();  
}END_CATCH
csFile.SeekToBegin();
while(csFile.ReadString(strLine))
{
if(strLine.Find("DelayTime:") != -1)//延时
{
int pos = strLine.ReverseFind(':');
strLine = strLine.Right(strLine.GetLength() - pos - 1);
Operation[OperationIndex] = DELAY_TIME;
OperationIndex++;
Operation[OperationIndex] = atoi(strLine);
}else if(strLine.Find("LeftMouseKeyDown") != -1)//左键按下
{
Operation[OperationIndex] = LEFT_MOUSEKEY_DOWN;
}else if(strLine.Find("LeftMouseKeyUp") != -1)//左键抬起
{
Operation[OperationIndex] = LEFT_MOUSEKEY_UP;
}else if(strLine.Find("RightMouseKeyDown") != -1)//右键按下
{
Operation[OperationIndex] = RIGHT_MOUSEKEY_DOWN;
}else if(strLine.Find("RightMouseKeyUp") != -1)//右键抬起
{
Operation[OperationIndex] = RIGHT_MOUSEKEY_UP;
}else if(strLine.Find("<loop>") != -1)//循环开始
{
Operation[OperationIndex] = LOOP_START;
LoopStartIndex = OperationIndex;
}else if(strLine.Find("</loop>") != -1)//循环结束
{
Operation[OperationIndex] = LOOP_END;
LoopEndIndex = OperationIndex;
}else if(strLine.Find("KeyDown") != -1)//键盘按键按下
{
int pos = strLine.ReverseFind(':');
strLine = strLine.Right(strLine.GetLength() - pos - 1);
Operation[OperationIndex] = KEY_DOWN;
OperationIndex++;
Operation[OperationIndex] = atoi(strLine);
}else if(strLine.Find("KeyUp") != -1)//键盘按键抬起
{
int pos = strLine.ReverseFind(':');
strLine = strLine.Right(strLine.GetLength() - pos - 1);
Operation[OperationIndex] = KEY_UP;
OperationIndex++;
Operation[OperationIndex] = atoi(strLine);
}
OperationIndex++;
}
OperationEndIndex = OperationIndex;
csFile.Close();
}

解决方案 »

  1.   


    //初始化
    void Init()
    {
    GetCurrentPath();
    WriteCurrentPathToReg();
    //ReadConfig();
    //ReadCurrentPathFromReg();
    //AfxMessageBox(pFileName);
    }
    //得到当前路径
    void GetCurrentPath()
    {
    TCHAR szFilePath[MAX_PATH + 1];
    GetModuleFileName(NULL, szFilePath, MAX_PATH);
    (_tcsrchr(szFilePath, _T('\\')))[1] = 0;
    CurrentPath=szFilePath;
    }//添加当前路径到注册表
    void WriteCurrentPathToReg()
    { HKEY hKey;//定义有关的hKey,在查询结束时要关闭
    HKEY hKey1;//新建项HKEY
    //打开与路径 DataSet相关的hKey
    LPCTSTR DataSet="Software\\MouseClick";

    //新建项
    ::RegCreateKey(HKEY_CURRENT_USER,DataSet,&hKey1);
    ::RegCloseKey(hKey1);

    //访问注册表,hKey则保存此函数所打开的键的句柄
    long ret0=(::RegOpenKeyEx(HKEY_CURRENT_USER,DataSet,0,KEY_WRITE,&hKey));
    if(ret0!=ERROR_SUCCESS)//如果无法打开hKEY,则中止程序的执行
    {
    AfxMessageBox("错误:无法打开有关的hKEY");
    return;
    } //设置有关的数据
    LPBYTE cp = CString_To_LPBYTE(CurrentPath);//当前路径
    DWORD DataType = REG_SZ;//数据类型
    DWORD DataLength = MAX_PATH;//数据长度 long ret1=::RegSetValueEx(hKey,"CurrentPath",NULL,DataType,cp,DataLength);
    if(ret1!=ERROR_SUCCESS)
    {
    AfxMessageBox("错误:无法设置有关的注册表信息");
    return;
    } //程序结束,关闭打开的hKEY
    ::RegCloseKey(hKey);
    }
    //从注册表读取当前路径
    void ReadCurrentPathFromReg()
    {
    HKEY hKey;//定义有关的hKey,在查询结束时要关闭 //打开与路径 DataSet相关的hKey
    LPCTSTR DataSet="Software\\MouseClick";

    //访问注册表,hKey则保存此函数所打开的键的句柄
    long ret0=(::RegOpenKeyEx(HKEY_CURRENT_USER,DataSet,0,KEY_READ,&hKey));
    if(ret0!=ERROR_SUCCESS)//如果无法打开hKEY,则中止程序的执行
    {
    AfxMessageBox("错误:无法打开有关的hKEY");
    return;
    } LPBYTE cp = new BYTE[MAX_PATH];//当前路径
    DWORD DataType = REG_SZ;//数据类型
    DWORD DataLength = MAX_PATH;//数据长度
    long ret2=::RegQueryValueEx(hKey,"CurrentPath",NULL,&DataType,cp,&DataLength);
    if(ret2!=ERROR_SUCCESS)
    {
    AfxMessageBox("错误:无法查询有关的注册表信息");
    return;
    }
    CurrentPath = CString(cp);
    //AfxMessageBox(CurrentPath);
    ::RegCloseKey(hKey);
    }LPBYTE CString_To_LPBYTE(CString str)
    {
    LPBYTE lpb=new BYTE[str.GetLength()+1];
    for(int i=0;i<str.GetLength();i++)
    lpb[i]=str[i];
    lpb[str.GetLength()]=0;
    return lpb;
    }//退出
    DllExport void WINAPI ExitMouseClick()
    {
    bIsRun = FALSE;
    pThread = NULL;
    UnhookWindowsHookEx(Hook);
    Hook = NULL;
    UnhookWindowsHookEx(MouseHook);
    MouseHook = NULL;
    }
      

  2.   

    以下是主程序源码:// MouseHookAppDlg.cpp : implementation file
    //#include "stdafx.h"
    #include "MouseHookApp.h"
    #include "MouseHookAppDlg.h"
    #include "MouseClickDll.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog
    {
    public:
    CAboutDlg();// Dialog Data
    //{{AFX_DATA(CAboutDlg)
    enum { IDD = IDD_ABOUTBOX };
    //}}AFX_DATA // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CAboutDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL// Implementation
    protected:
    //{{AFX_MSG(CAboutDlg)
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    };CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    //{{AFX_DATA_INIT(CAboutDlg)
    //}}AFX_DATA_INIT
    }void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CAboutDlg)
    //}}AFX_DATA_MAP
    }    
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    //{{AFX_MSG_MAP(CAboutDlg)
    // No message handlers
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    //最小化到系统工具栏
    void CMouseHookAppDlg::toTray() 
    {
    NOTIFYICONDATA nid;
    nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
    nid.hWnd=this->m_hWnd;
    nid.uID=IDR_MAINFRAME;
    nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
    nid.uCallbackMessage=WM_SHOWTASK;//自定义的消息名称
    nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME)); 
    strcpy(nid.szTip,"MouseHook"); //信息提示条为MouseHook
    Shell_NotifyIcon(NIM_ADD,&nid); //在托盘区添加图标 
    ShowWindow(SW_HIDE); //隐藏主窗口 
    }//删除系统工具栏
    void CMouseHookAppDlg::DeleteTray()
    {
    NOTIFYICONDATA nid;
    nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
    nid.hWnd=this->m_hWnd;
    nid.uID=IDR_MAINFRAME;
    nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
    nid.uCallbackMessage=WM_SHOWTASK;//自定义的消息名称   
    nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
    strcpy(nid.szTip,"MouseHook");    //信息提示条为 MouseHook   
    Shell_NotifyIcon(NIM_DELETE,&nid);    //在托盘区删除图标 
    }//显示系统工具栏菜单
    LRESULT CMouseHookAppDlg::onShowTask(WPARAM wParam,LPARAM lParam)//wParam接收的是图标的ID,而lParam接收的是鼠标的行为  
    {   
    if((UINT)wParam!=IDR_MAINFRAME)
    return   1;   
    switch(lParam)
    {
    case WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个 关闭
    {
    LPPOINT lpoint = new tagPOINT;   
    ::GetCursorPos(lpoint);//得到鼠标位置   
    CMenu menu;   
    menu.CreatePopupMenu();//声明一个弹出式菜单   
    //增加菜单项 关闭,点击则发送消息WM_DESTROY给主窗口(已隐藏),将程序结束。   
    menu.AppendMenu(MF_STRING,WM_DESTROY,"关闭");     
    //确定弹出式菜单的位置   
    menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);   
    //资源回收   
    HMENU hmenu=menu.Detach();   
    menu.DestroyMenu();   
    delete lpoint;   
    }   
    break;   
    case WM_LBUTTONDBLCLK://双击左键的处理   
    {    
    this->ShowWindow(SW_SHOW);//简单的显示主窗口完事儿
    DeleteTray();    
    }
    break;   
    }   
    return 0;
    }
      

  3.   


    /////////////////////////////////////////////////////////////////////////////
    // CMouseHookAppDlg dialogCMouseHookAppDlg::CMouseHookAppDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CMouseHookAppDlg::IDD, pParent)
    {
    //{{AFX_DATA_INIT(CMouseHookAppDlg)
    // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }void CMouseHookAppDlg::DoDataExchange(CDataExchange* pDX)
    {
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CMouseHookAppDlg)
    // NOTE: the ClassWizard will add DDX and DDV calls here
    //}}AFX_DATA_MAP
    }BEGIN_MESSAGE_MAP(CMouseHookAppDlg, CDialog)
    //{{AFX_MSG_MAP(CMouseHookAppDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_MESSAGE(WM_SHOWTASK,onShowTask)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CMouseHookAppDlg message handlersBOOL CMouseHookAppDlg::OnInitDialog()
    {
    CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range.
    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);
    }
    } // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE); // Set big icon
    SetIcon(m_hIcon, FALSE); // Set small icon

    // TODO: Add extra initialization here

    return TRUE;  // return TRUE  unless you set the focus to a control
    }void CMouseHookAppDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
    CAboutDlg dlgAbout;
    dlgAbout.DoModal();
    }
    else
    {
    CDialog::OnSysCommand(nID, lParam);
    }
    }// If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.void CMouseHookAppDlg::OnPaint() 
    {
    if (IsIconic())
    {
    CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
    int cxIcon = GetSystemMetrics(SM_CXICON);
    int cyIcon = GetSystemMetrics(SM_CYICON);
    CRect rect;
    GetClientRect(&rect);
    int x = (rect.Width() - cxIcon + 1) / 2;
    int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
    dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
    CDialog::OnPaint();
    }
    }// The system calls this to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CMouseHookAppDlg::OnQueryDragIcon()
    {
    return (HCURSOR) m_hIcon;
    }void CMouseHookAppDlg::OnOK() 
    { /*
    // TODO: Add extra validation here
    InstallLaunchEv();
    //CDialog::ShowWindow(SW_HIDE);
    CDialog::ShowWindow(SW_SHOWMINIMIZED);
    CDialog::HideCaret();
    //CDialog::OnOK();
    */
    toTray();}void CMouseHookAppDlg::OnCancel() 
    {
    // TODO: Add extra cleanup here
    ExitMouseClick();
    CDialog::OnCancel();
    }