• 【原】DIY属于自己的鼠标侧键


    现在的鼠标功能越来越强大,不单单只有左右中三键,有更多的按键,比如5键,7键,20+键、、、我也顺便淘了一个5键的鼠标。但是无奈国产货(Understand?),鼠标侧面的两个键完全白费了,只能用来当前进后退键。看到罗技、Razor的鼠标按键自定义爽爽的,心里就不舒服,然后萌生了这个想法——自己来重新DIY下这俩个鸡肋按键。

    网上资料倒是一大堆,先分析下这个工程怎么实现。

    由于是从打开软件开始这两个按键一直要处于DIY的条件下,所以远程注入不能实现,否则要一一注入那还不麻烦死?杀毒软件也要来一直阻止你的。丢个例子,试试就知道有多蛋疼了:

    #include <windows.h>

    #include <iostream.h>

     

    bool EnableDebugPriv()

    {

        HANDLE hToken;

        LUID sedebugnameValue;

        TOKEN_PRIVILEGES tkp;

     

        if (!OpenProcessToken(GetCurrentProcess(),

            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {

            return false;

        }

     

        if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {

            CloseHandle(hToken);

            return false;

        }

     

        tkp.PrivilegeCount = 1;

        tkp.Privileges[0].Luid = sedebugnameValue;

        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

     

        if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {

            CloseHandle(hToken);

            return false;

        }

     

        return true;

    }

     

    BOOL InitDll(const char *DllFullPath, const DWORD dwRemoteProcessId)

    {

    EnableDebugPriv();

     

    HANDLE hRemoteProcess;

     

        //打开远程线程

        hRemoteProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId );

     

    char *pszLibFileRemote;

     

        //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名空间

        pszLibFileRemote = (char *) VirtualAllocEx( hRemoteProcess, NULL, lstrlen(DllFullPath)+1,

    MEM_COMMIT, PAGE_READWRITE);

     

        //使用WriteProcessMemory函数将DLL的路径名写入到远程进程的内存空间

        WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (void *) DllFullPath,

    lstrlen(DllFullPath)+1, NULL);

     

    DWORD dwID;

    LPVOID pFunc = LoadLibraryA;

    HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0,

    (LPTHREAD_START_ROUTINE)pFunc, pszLibFileRemote, 0, &dwID );

     

     

    if(hRemoteThread == NULL)

    {

    cout<<"注入线程失败!"<<endl;

    return 0;

    }

        CloseHandle(hRemoteProcess);

        CloseHandle(hRemoteThread);

     

        return TRUE;

    }

     

    int main()

    {

        InitDll("E:\\工作区间\\源程序\\远程注入\\Debug\\iGazeU.dll", 576) ;//这个dll你所要注入的dll文件,这个数字是你想注入的进程的PID

        return 0;

    }

     

    所以另寻方法了。

    熟悉Windows的童鞋也许能通过修改注册表实现小部分功能,比方说把按键映射,连编写都省了,但是绝对做不出自定义想要的功能,比方说复制粘贴什么的。

    最后,只有靠一种方法了,就是用全局钩子。

    全局钩子?没怎么看过的童鞋一定觉得很神秘,360有时候也会提示带有Hook字样的内容,其实钩子只是一个纸老虎。

    Windows和DOS最大的区别就是消息。现在学编程的童鞋肯定知道一个面向过程的程序是怎么编的,但是可能并不清楚面向对象的程序是怎么写的,比方说一个状态栏带有动态时间显示的记事本是怎么显示的?如果用面向过程写,记事本要输入文字,又要定时刷新时间,两个事情怎么可能同时做?所以说,消息就是Windows提醒程序什么时候做什么事情,程序只要循环不断接收消息就行了。就像这样:

    while (GetMessage(&msg, NULL, 0, 0))  //程序永远在接收消息

    {

    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 

    {

    TranslateMessage(&msg);

    DispatchMessage(&msg);

    }

    }

    我们现在研究的核心,就是怎么让Windows在向程序发送鼠标侧键消息的时候把这个消息拦截掉,改掉并换成自定义的消息,这就是钩子的本来面目。

    最重要的一关被我们跨过去了,现在是实战阶段了。

    打开你的VS2010,或者VC6也一样,由于MFC比较方便,很多代码都是自动添加好的,所以我们以MFC为例:

    1、新建一个 MFC AppWizarddll) 工程,选择 MFC扩展DLL(使用共享MFC DLL),建立工程名为TestHook

    为什么要建立DLL(动态连接库)?Windows坑爹的规定,没办法,人家是老大,只能听他的,Linux没试过,应该会好很多。

    DLL是什么?普及下,就是独立出来的库,比方说你有n+1个程序都要使用 void max(int *a, int *b)

    {

    a ^= b ^= a ^= b;

    }

    那么你只需写一个这样的功能,做成DLL,你就可以让n+1个程序都可以用它了,是不是很方便?

    2、打开stdafx.h,在#include <afxwin.h>上面加入:

    #define _WIN32_WINNT 0x500

    stdafx.h最后面加上:

    #include <windows.h>

    #include <winuser.h>

    这是什么意思呢?你可以打开winuser.h看看,原来_WIN32_WINNT是用来区分系统版本的,我们的程序只能在Windows 2000和以上版本的电脑才能运行。

    3、打开TestHook.def,在最下面加入:

    SECTIONS

    mydata READ WRITE SHARED

    4、现在来做几个函数了,用类来管理比较方便,应该说是一个好习惯。先来定义一个类:新建头文件MouseHook.h,写上:

    class AFX_EXT_CLASS CMouseHook:public CObject

    {

    public:

    CMouseHook();

    ~CMouseHook();

     

    BOOL startHook();

    BOOL stopHook();

    static LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam);

    };

    再新建一个MouseHook.cpp,添加以下代码:

    #include "stdafx.h"

    #include "MouseHook.h"

     

    #ifdef _DEBUG

    #define new DEBUG_NEW

    #endif

     

    #pragma data_seg("mydata")

    HHOOK glhHook = NULL;

    HINSTANCE glhInstance = NULL;

    #pragma data_seg()

     

    CMouseHook::CMouseHook()

    {

    }

     

    CMouseHook::~CMouseHook()

    {

    stopHook();

    }

    LRESULT CALLBACK CMouseHook::MouseProc(int nCode,WPARAM wParam,LPARAM lParam)

    {

    return CallNextHookEx(glhHook, nCode, wParam, lParam);

    }

    BOOL CMouseHook::startHook()

    {

    BOOL bResult = FALSE; 

    glhHook = SetWindowsHookEx(WH_MOUSE_LL, CMouseHook::MouseProc, glhInstance, 0); 

     

    if(glhHook != NULL) 

    bResult = TRUE; 

     

    return bResult; 

    }

     

    BOOL CMouseHook::stopHook()

    {

    if (glhHook == NULL)

    {

    MessageBox(NULL, _T("NULL HOOK"), _T("glhHook"), MB_OK);

    }

     

    BOOL bResult = FALSE; 

     

    bResult = UnhookWindowsHookEx(glhHook); 

    if(bResult) 

    MessageBox(NULL, _T("UnhookWindowsHookEx Success"), _T("glhHook"), MB_OK);

    glhHook = NULL; 

    }

     

    return bResult;

    }

    5、现在是关键代码了,我们的代码都在

    LRESULT CALLBACK CMouseHook::MouseProc(int nCode,WPARAM wParam,LPARAM lParam)

    {

    return CallNextHookEx(glhHook, nCode, wParam, lParam);

    }

    中完成,具体代码如下:

    LRESULT CALLBACK CMouseHook::MouseProc(int nCode,WPARAM wParam,LPARAM lParam)

    {

    LPMSLLHOOKSTRUCT pMouseHook = (MSLLHOOKSTRUCT*)lParam;

    if (nCode >= 0)

    {

    If (wParam==WM_XBUTTONDOWN && HIWORD(pMouseHook->mouseData)==XBUTTON1)

    {

    //写上自己代码

    return TRUE;

    }

     

    if (wParam == WM_XBUTTONUP && HIWORD(pMouseHook->mouseData)==XBUTTON1)

    {

    //写上自己代码

    return TRUE;

    }

     

    if (wParam == WM_XBUTTONDOWN && HIWORD(pMouseHook->mouseData)==XBUTTON2)

    {

    //写上自己代码

    return TRUE;

    }

     

    if (wParam == WM_XBUTTONUP && HIWORD(pMouseHook->mouseData)==XBUTTON2)

    {

    //写上自己代码

    return TRUE;

    }

    }

    return CallNextHookEx(glhHook, nCode, wParam, lParam);

    }

    VC6的童鞋会说了,为什么我编译下后程序出现N多错误?其实是VC6太老了,有些库比较新,没有得到更新。只要在cpp#include "stdafx.h"下加上这些:

    #define WM_XBUTTONDOWN 0x020B

    #define WM_XBUTTONUP 0x020C

    #define XBUTTON1 0x1

    #define XBUTTON2 0x2

    是不是行了呢?

     

    注意:VC6要把_T()去掉,比方说_T("glhHook")变成"glhHook"。

    由于5键鼠标不是常规鼠标,而我们使用的是低级钩子(Low-Level Hook)因此要用MSLLHOOKSTRUCT结构体。

     

    6、做完DLL当然要有程序去调用啊,接下来做一个调用程序(以VC6为例):

    (1)新建一个MFC EXE工程Mouse,把做完的Dll工程下的Debug目录下的TestHook.lib和Dll工程目录中的MouseHook.h拷贝到新建工程的目录下,按快捷键Alt+F7打开工程设置,点击 连接 选项卡,在对象/库模块中填写TestHook.lib,打开MouseDlg.h,在#include "stdafx.h"下方加入

    #include "MouseHook.h",

    然后在class CMouseDlg : public CDialog下的public:下加入:

    CMouseHook m_hook;

    切换到MouseDlg.cpp,在BOOL CMouseDlg::OnInitDialog()下的SetIcon(m_hIcon, FALSE); // Set small icon

    下加入

    m_hook.startHook();

    然后编译链接吧。

     

    现在,把做完的TestHook.dll和Mouse.exe放在同一个目录下,打开是不是发现鼠标的侧键被屏蔽了?因为我们到现在都没有加入自己想要的功能,又是运行了直接return TRUE; 所以截取的消息直接被吃掉了!

    加个小功能吧,有些童鞋的鼠标左右键不好用了,可以临时代替应急:

    LRESULT CALLBACK CMouseHook::MouseProc(int nCode,WPARAM wParam,LPARAM lParam)

    {

    int cx=GetSystemMetrics(SM_CXSCREEN);//得到屏幕宽度

    int cy=GetSystemMetrics(SM_CYSCREEN);//得到屏幕高度

    LONG ldx = pMouseHook->pt.x * 65535 / cx;

    LONG ldy = pMouseHook->pt.y * 65535 / cy;

     

    LPMSLLHOOKSTRUCT pMouseHook = (MSLLHOOKSTRUCT*)lParam;

     

    if (nCode >= 0)

    {

    If (wParam==WM_XBUTTONDOWN && HIWORD(pMouseHook->mouseData)==XBUTTON1)

    {

    INPUT input[1];

    ZeroMemory(&input, sizeof(INPUT));

     

    //鼠标左键弹起

    input[0].type = INPUT_MOUSE;

    input[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;

    input[0].mi.dx = ldx;

    input[0].mi.dy = ldy;

     

    SendInput(

    1, // count of input events

    input, // array of input events

    sizeof(INPUT) // size of structure

    );

     

    return TRUE;

    }

     

    if (wParam == WM_XBUTTONUP && HIWORD(pMouseHook->mouseData)==XBUTTON1)

    {

    INPUT input[1];

    ZeroMemory(&input, sizeof(INPUT));

     

    //鼠标左键弹起

    input[0].type = INPUT_MOUSE;

    input[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;

    input[0].mi.dx = ldx;

    input[0].mi.dy = ldy;

     

    SendInput(

    1, // count of input events

    input, // array of input events

    sizeof(INPUT) // size of structure

    );

     

    return TRUE;

    }

     

    if (wParam == WM_XBUTTONDOWN && HIWORD(pMouseHook->mouseData)==XBUTTON2)

    {

    INPUT input[1];

    ZeroMemory(&input, sizeof(INPUT));

     

    //鼠标左键弹起

    input[0].type = INPUT_MOUSE;

    input[0].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;

    input[0].mi.dx = ldx;

    input[0].mi.dy = ldy;

     

    SendInput(

    1, // count of input events

    input, // array of input events

    sizeof(INPUT) // size of structure

    );

     

    return TRUE;

    }

     

    if (wParam == WM_XBUTTONUP && HIWORD(pMouseHook->mouseData)==XBUTTON2)

    {

    INPUT input[1];

    ZeroMemory(&input, sizeof(INPUT));

     

    //鼠标左键弹起

    input[0].type = INPUT_MOUSE;

    input[0].mi.dwFlags = MOUSEEVENTF_RIGHTUP;

    input[0].mi.dx = ldx;

    input[0].mi.dy = ldy;

     

    SendInput(

    1, // count of input events

    input, // array of input events

    sizeof(INPUT) // size of structure

    );

     

    return TRUE;

    }

    }

    return CallNextHookEx(glhHook, nCode, wParam, lParam);

    }

     

    写到了这里,就是那么多了,其实也没多少技术含量的事情,接下来怎么玩看各位的想法了,比方说自动打怪,设置快捷键什么的。

  • 相关阅读:
    输入分隔符
    GO
    match|align|identify|cover_rate
    KEGG
    InterProScan
    Functional annotation
    GeneWise
    get middle lines
    goland debug web app with urfave cli
    go mod proxy
  • 原文地址:https://www.cnblogs.com/ZzzZzz/p/xbutton.html
Copyright © 2020-2023  润新知