Click here to Skip to main content
15,867,704 members
Articles / Programming Languages / C++

Middle Mouse Button (or Wheel) to Doubleclick (VC6)

Rate me:
Please Sign up or sign in to vote.
4.67/5 (17 votes)
26 Jul 2010CPOL2 min read 83.5K   2K   34   19
This is a small but handy tool I'm using every day. It converts a middle mouse button click in to a left mouse button double click.

Config GUI

  • Displays function state
  • Enables / disables doubleclick function
  • Chooses whether to confirm exit of the application
Screenshot - MBtn2DblClickVC.jpg

Introduction

Once I had a logitech mouse and everything was fine!

Logitech provided you with a handy application called EMEXEC.exe, which would allow you to set up the behavior of the available buttons. The function I most used was the converter for the middle mouse button/wheel which would turn a single click from the specific button into a left mouse button double click. But what if you uninstalled mouseware, or what if you have to work on a machine without LogiMouse. You're not able to install MouseWare until you have a LogiMouse connected. Pretty soon I began to miss this cool feature from Logitech and said to myself that I am going to write a tool which implements exactly this feature. And here we go....

Problem

The trickiest part I was facing was that the application had to get the clicks from all the other applications running at this time. Therefore a global mousehook had to be set and that might be a little bit tricky. You have to place the code for the mousehook callback in a external DLL with a custom code-segment. I used MouseHook.cpp - I found this a while ago while surfing the web, but I don't remember where I got it from (sorry!). If this is your MouseHook.cpp, please drop a line.

Setting up the MouseHook

C++
__declspec(dllexport) BOOL setMyHook(HWND hWnd) {
    if(hWndServer != NULL)
        return FALSE; // already hooked!
    
    hook = SetWindowsHookEx(WH_MOUSE_LL,
        (HOOKPROC)msghook,
               hInst,
               0);
    if(hook != NULL) { /* success */
        hWndServer = hWnd;
        return TRUE;
    } /* success */

    return FALSE; // failed to set hook
} // setMyHook

...
//Hook-Function:

...

static LRESULT CALLBACK msghook(UINT nCode, WPARAM wParam, LPARAM lParam) {
    if(nCode < 0) { /* pass it on */
        CallNextHookEx(hook, nCode, wParam, lParam);
        return 0;
    } /* pass it on */
    
    if(wParam == WM_MBUTTONUP ){
        PostMessage(hWndServer, UWM_MBTNCLICK, 0, 0);
    }
    
    return CallNextHookEx(hook, nCode, wParam, lParam);
} // msghook

Clearing the Hook

C++
__declspec(dllexport) BOOL clearMyHook(HWND hWnd) {
    if(hWnd != hWndServer || hWnd == NULL)
        return FALSE;
    
    BOOL unhooked = UnhookWindowsHookEx(hook);
    
    if(unhooked)
        hWndServer = NULL;
    
    return unhooked;
} // clearMyHook

Converting the Click

C++
BEGIN_MESSAGE_MAP(CMBtn2DblClickDlg, CDialog)
    ON_REGISTERED_MESSAGE(UWM_MBTNCLICK, OnMyMbtnClick)

....
LRESULT CMBtn2DblClickDlg::OnMyMbtnClick(WPARAM wParam, LPARAM lParam) {
    CPoint pt;
    GetCursorPos(&pt);
    
    // width
    int cx = GetSystemMetrics(SM_CXSCREEN);
    // height
    int cy = GetSystemMetrics(SM_CYSCREEN);
  
    //Reformat screen coordinates
    int x2 = ( 65535 * pt.x ) / cx;
    int y2 = ( 65535 * pt.y ) / cy;
 
    INPUT input[2];
    
    input[0].type = INPUT_MOUSE;
    input[0].mi.dx = x2;
    input[0].mi.dy = y2;
    input[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN;
    input[0].mi.mouseData   = 0L; 
    input[0].mi.time        = 0L; 
    input[0].mi.dwExtraInfo = 0L;

    input[1].type = INPUT_MOUSE;
    input[1].mi.dx = x2;
    input[1].mi.dy = y2;
    input[1].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP;
    input[1].mi.mouseData   = 0L; 
    input[1].mi.time        = 0L; 
    input[1].mi.dwExtraInfo = 0L;
    
    SendInput( 1, &input[0], sizeof(input[0]));
    SendInput( 1, &input[1], sizeof(input[1]));

    Sleep(40);
    
    SendInput( 1, &input[0], sizeof(input[0]));
    SendInput( 1, &input[1], sizeof(input[1]));
    
    return 0;
} // MBtn2DblClickDlg::OnMyMouseMove

Credits

  • CReadOnlyEdit by Kevin Bond
  • CRegistry by Shane Martin
  • CSimpleTray by T1TAN / SprdSoft Inc.
  • CWinStartup (by unknown)

I hope this article is useful to anyone or helps to understand how mousehooks work. If you are interested in the source of a good MouseHook DLL, I'd recommend you to download this source since the original location of MouseHookManager is gone and I couldn't find it on the net anymore so far. So hope you enjoy and all the best - hope you'll be reading my next articles as well.

Cheers, Kim

History

  • 9th July, 2007: Initial post
  • 15th April, 2010: Corrected a bug with the persitence of Registry settings enabled at startup and other config settings
  • 24th July, 2010: Updated the source and application so they work with Windows 7 on x64 systems

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Switzerland Switzerland
programmer and software junkie since 1991 zurich switzerland

Comments and Discussions

 
Questiongood work, but got a general problem of 'WH_MOUSE_LL' Pin
Michael ZY9-Aug-07 16:56
Michael ZY9-Aug-07 16:56 
AnswerRe: good work, but got a general problem of 'WH_MOUSE_LL' Pin
Hatod6-Nov-07 22:04
Hatod6-Nov-07 22:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.