Click here to Skip to main content
15,891,529 members
Articles / Desktop Programming / WPF

Improve Zooming with Enhanced Mouse Wheels

Rate me:
Please Sign up or sign in to vote.
4.65/5 (7 votes)
19 Oct 2011CPOL6 min read 43.8K   4K   33  
How to give your users a better zooming experience with High Resolution Mouse Wheels.
// MouseWheel.cpp :

#include "stdafx.h"

HHOOK g_hHook = 0 ;
HANDLE g_hThread = 0 ;
bool g_bSkip = false ;
LONG g_nTotalDelta = 0 ;
bool g_bExit = false;

// parameters for SetParameters (and their defaults)
int g_nDelta = WHEEL_DELTA ;
int g_nSleep = 18 ; // 18 milliseconds seems to be the minimum value that can be processed.
int g_nEvents = 1 ; // 18 milliseconds seems to be the minimum value that can be processed.

__declspec( dllexport ) void SetParameters(int x1, int x2, int x3)
{
	//SuspendThread(g_hThread) ;
	g_bSkip = true ;
	g_nDelta = x1 ;
	g_nSleep = x2 ;
	g_nEvents=x3 ;
	g_bSkip = false ;
	//ResumeThread(g_hThread) ;
}

DWORD WINAPI WorkerThread(LPVOID pParam)
{
	while (!g_bExit) {
		if (g_bSkip) {
			Sleep(3) ;
			continue ;
		}
		if (g_nTotalDelta == 0) {
			Sleep(3) ;
			continue ;
		}
		int nDirection = g_nTotalDelta/abs(g_nTotalDelta) ; 
		mouse_event( MOUSEEVENTF_WHEEL, 0, 0, nDirection*g_nDelta, 0);
		Sleep(g_nSleep) ;
	}
	return 0 ;
}

LRESULT WINAPI ProcMouseLL (int nCode, WPARAM wParam, LPARAM lParam)
{
	if (nCode < 0)
		return CallNextHookEx ( g_hHook, nCode, wParam, lParam );
	if (WM_MOUSEWHEEL == wParam) {
		if (lParam == 0)
			return CallNextHookEx ( g_hHook, nCode, wParam, lParam );
		MSLLHOOKSTRUCT *hookStruct = (MSLLHOOKSTRUCT *)lParam ;
		short delta = (short)HIWORD(hookStruct->mouseData) ;
		if (hookStruct->flags & LLMHF_INJECTED) {
			// created by mouse_event()
			// assumption is that we called it from our WorkerThread
			if ((g_nTotalDelta*delta) > 0) {
				g_nTotalDelta -= delta ;
				if ((g_nTotalDelta*delta) < 0) {
					g_nTotalDelta = 0 ;
				}
				return CallNextHookEx ( g_hHook, nCode, wParam, lParam ); // pass mouse wheel to system and application
			}
			else {
				// we've reversed directions and discard mouse_event() going in the opposite direction
				return -1 ; // eat mouse wheel
			}
		}
		else {
			// physical hardware generated event
			g_nTotalDelta = abs(delta)/delta*g_nDelta*g_nEvents ;
			return -1 ; // eat mouse wheel
		}
	}
	if ((WM_LBUTTONDOWN == wParam) ||
	    (WM_LBUTTONUP == wParam) ||
		(WM_RBUTTONDOWN == wParam) ||
		(WM_RBUTTONUP == wParam)) {
			g_nTotalDelta=0 ;
	}
	return CallNextHookEx ( g_hHook, nCode, wParam, lParam );
}

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,
    DWORD fdwReason,
    LPVOID lpvReserved)
{
    if ( fdwReason == DLL_PROCESS_ATTACH )
    {
		DisableThreadLibraryCalls( hinstDLL );
        if ( g_hHook )
            return FALSE;
        g_hHook = SetWindowsHookEx( WH_MOUSE_LL, (HOOKPROC)ProcMouseLL,hinstDLL, 0 );
		DWORD threadid;
		g_bExit = false ;
		g_bSkip = true ;
		g_hThread = CreateThread(NULL, 0,  WorkerThread, 0, 0, &threadid);
	}
    else if ( fdwReason == DLL_PROCESS_DETACH )
    {
		g_bSkip = false ;
		g_bExit = true ;
		Sleep((DWORD)(g_nSleep+5)) ;
		if (g_hHook)     
		{                                       
			UnhookWindowsHookEx(g_hHook);     
			g_hHook = 0;
		}
    }
    return TRUE;
}

extern "C" BOOL __stdcall _DllMainCRTStartup( 
    HINSTANCE hinstDLL,
    DWORD fdwReason,
    LPVOID lpvReserved)
{
    return DllMain( hinstDLL, fdwReason, lpvReserved );
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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) Logitech Corporation
United States United States
Stephen lives in Fremont, CA with his wife and daughter and has programmed in C and C++ for a very long time.

Comments and Discussions