Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

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

4.67/5 (17 votes)
26 Jul 2010CPOL2 min read 1   2.1K  
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)