Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Mouse Gestures for Internet Explorer

, 21 Sep 2005
Adding mouse gesture recognition to Internet Explorer.
mousegestures_inst.zip
MouseGestures.exe
mousegestures_inst_1.zip
MouseGestures.exe
mousegestures_src.zip
src
gesture.weights
images
about.bmp
ClickLeftRight.bmp
ClickRightLeft.bmp
down.bmp
downarrow.bmp
downleft.bmp
downright.bmp
downup.bmp
exclamation.bmp
left.bmp
leftarrow.bmp
leftright.bmp
none.bmp
right.bmp
rightarrow.bmp
rightleft.bmp
up.bmp
uparrow.bmp
updown.bmp
upleft.bmp
upright.bmp
wheel.bmp
MouseGestures.rgs
mousegestures_src_1.zip
MouseGestures
BrowserHelperObject.rgs
gesture.weights
images
about.bmp
ClickLeftRight.bmp
ClickRightLeft.bmp
down.bmp
downleft.bmp
downright.bmp
downup.bmp
left.bmp
none.bmp
right.bmp
up.bmp
updown.bmp
upleft.bmp
upright.bmp
wheel.bmp
MouseGestures.def
MouseGestures.dsp
MouseGesturesCfg.rgs
///////////////////////////////////////////////////////////////
//
// InternetExplorerSink.h
//
// Created: 12/07/2003
// Copyright (c) 2003 Ralph Hare (ralph.hare@ysgyfarnog.co.uk)
// All rights reserved.
//
// The code and information is provided "as-is" without
// warranty of any kind, either expressed or implied.
//
///////////////////////////////////////////////////////////////

#ifndef __INTERNETEXPLORERSINK_H_F2026BFC_F70F_46B5_A50E_896E4E022F83_
#define __INTERNETEXPLORERSINK_H_F2026BFC_F70F_46B5_A50E_896E4E022F83_

#include "Gesture.h"

/**
 * @brief Class to intercept mouse movements within a given window and
 *        inform an observer of these movements.
 *
 * The MouseTracker class subclasses a window. The classes message pump
 * intercepts all mouse messages and forwards these to the watcher.
 * 
 * Clients of the MouseTracker can disable mouse tracking by using the
 * Suspend RAII class. Each Suspend object sets the m_isSuspended flag
 * to true for its lifetime, and resets the flag to false when its
 * destroyed. The ProcessWindowMessage function (implemented via the
 * BEGIN_MSG_MAP_EX macro) ignores all messages if m_isSuspended is set
 * to true.
 *
 * We can't simply temporarily unsubclass the (subclassed) Window. If
 * we've got multiple ATL CWindowImpl derived objects subclassing a window
 * (as we do in the MouseGestures app if (for example) the Google toolbar
 * is installed), then there's no guarantee that we're the last object
 * in the message chain. Unsubclass can fail (the top-most message proc
 * will be different from the static WndProc function for this class),
 * resulting in recursion (and ultimately a stack overflow) if we send
 * our own messages to the subclassed window.
 **/

class MouseTracker : public CWindowImpl< MouseTracker >
{
public:
    struct Watcher
    {
    //
    // return true if we want to pass the message onto the subclassed window
    // or false if we want to swallow the message and start tracking the mouse
    //
        virtual bool OnLeftButtonDown( HWND hWnd, const POINT &pt, DWORD flags ) { return true; }
        virtual bool OnRightButtonDown( HWND hWnd, const POINT &pt, DWORD flags ) { return true; }

    //
    // if the user (i.e. the class that derives from Watcher) returns true from
    // either OnLeftButtonDown or OnRightButtonDown then we fire the OnLeftButtonUp
    // or OnRightButtonUp events respectively, with the (cracked) WPARAM and LPARAM
    // of the mouse message.
    //
        virtual bool OnLeftButtonUp( HWND hWnd, const POINT &pt, DWORD flags ) { return true; }
        virtual bool OnRightButtonUp( HWND hWnd, const POINT &pt, DWORD flags ) { return true; }

    //
    // if the user (i.e. the class that derives from Watcher) returns false from
    // either OnLeftButtonDown or OnRightButtonDown then we fire the OnLeftButtonUp
    // or OnRightButtonUp events respectively, with the path of the mouse
    // between the two events. There's no return value as we always swallow 
    // the windows message
    //
        virtual void OnLeftButtonUp( HWND hWnd, const Path &path ) {}
        virtual void OnRightButtonUp( HWND hWnd, const Path &path ) {}

    //
    // Mouse Wheel
    //
        virtual bool OnMouseWheel( HWND hWnd, WORD flags, WORD delta, const POINT &pt ) { return true; }
    };

public:
    MouseTracker();
    ~MouseTracker();

/**
 * Extend the BEGIN_MSG_MAP macro to (which implments the head of the 
 * ProcessWindowMessage function) to ignore all messages if the m_isSuspended
 * flag is set
 **/

#define BEGIN_MSG_MAP_EX(theClass) \
public: \
	BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
	{ \
        if( m_isSuspended ) return FALSE; \
		BOOL bHandled = TRUE; \
		switch(dwMsgMapID) \
		{ \
		case 0:

public:
    BEGIN_MSG_MAP_EX( MouseTracker )
        MESSAGE_HANDLER( WM_MOUSEMOVE, OnMouseMove )
        MESSAGE_HANDLER( WM_RBUTTONDOWN, OnRightButtonDown )
        MESSAGE_HANDLER( WM_RBUTTONUP, OnRightButtonUp )
        MESSAGE_HANDLER( WM_LBUTTONDOWN, OnLeftButtonDown )
        MESSAGE_HANDLER( WM_LBUTTONUP, OnLeftButtonUp )
        MESSAGE_HANDLER( WM_MOUSEWHEEL, OnMouseWheel )
        MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
    END_MSG_MAP()

private:
    LRESULT OnMouseWheel( UINT, WPARAM, LPARAM, BOOL & );
    LRESULT OnMouseMove( UINT, WPARAM, LPARAM, BOOL & );
    LRESULT OnRightButtonDown( UINT, WPARAM, LPARAM, BOOL & );
    LRESULT OnRightButtonUp( UINT, WPARAM, LPARAM, BOOL & );
    LRESULT OnLeftButtonDown( UINT, WPARAM, LPARAM, BOOL & );
    LRESULT OnLeftButtonUp( UINT, WPARAM, LPARAM, BOOL & );
    LRESULT OnDestroy( UINT, WPARAM, LPARAM, BOOL & );

public:
    HRESULT Advise( HWND hWnd, Watcher *pWatcher );
    HRESULT Unadvise();

/**
 * Call reset if you want to stop tracking the mouse in response
 * to a mouse event (e.g. a left-right click)
 **/
    void Reset();

private:
    struct ButtonRec
    {
        Path    path;
        bool    isTracking;

        ButtonRec() :
            path(),
            isTracking( false )
        {
        }
    };

    enum
    {
        Left  = 0,
        Right = 1,

        REC_COUNT
    };

public:
/**
 * RAII class to toggle the m_isSuspended flag. When the
 * Suspend object is constructed, m_isSuspended is set to true.
 * When the Suspend object is destroyed, m_isSuspened is set to
 * false.
 * The current state of the m_isSuspended is ignored, so Suspend 
 * objects shouldn't be used simultaneously.
 **/
    class Suspend
    {
    public:
        Suspend( MouseTracker &mouseTracker );
        ~Suspend();

    private:
        bool    &isSuspended;
    };

    friend class Suspend;

private:
    void SetCapture();
    void ReleaseCapture();

private:
    ButtonRec   m_buttonRecs[ REC_COUNT ];
    bool        m_isBound;                  /// < are we bound to a subclassed window
    Watcher     *m_pWatcher;                /// < the object watching the mouse
    bool        m_isSuspended;              /// < is tracking suspended?
    bool        m_hasCapture;               /// < have we captured the mouse?
};

#endif // __INTERNETEXPLORERSINK_H_F2026BFC_F70F_46B5_A50E_896E4E022F83_

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Ralph Hare
Web Developer
United Kingdom United Kingdom
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141216.1 | Last Updated 21 Sep 2005
Article Copyright 2003 by Ralph Hare
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid