Click here to Skip to main content
Click here to Skip to main content

ColourGrabber2

, 5 Mar 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Using Windows hooks to capture mouse action.

Introduction

I was working on another project when I discovered I wanted a particular colour for an HTML style class and I had no immediate means to discover the HTML colour value. I had previously created a colour picker application (ColourGrabber) and it accomplished what I needed. However, I noticed some shortcomings with the application and decided I’d like to resolve those. The primary deficiency was that the program was a dialog-based application and used SetCapture() to capture mouse input. Unfortunately, SetCapture() confines cursor position reporting to the application/parent window and thus I couldn’t provide a preview of the colour under the cursor. After a lot of trial and error, I discovered the hook functions. ColourGrabber2 resolves the problem.

Unfortunately, as soon as I upgraded my OS to Windows 8.1, ColourGrabber2 stopped working. The solution has been a closer examination of the hook functions.

Using the Code

This project begins with a dialog based program. The primary dialog class is called CColourGrabber2Dlg. Set up two global variables...

CColourGrabber2Dlg *pDialog=NULL;
HHOOK handleHook=NULL; 

...at the beginning of CColourGrabber2.cpp.

The next step was to create the hook function immediately following the two global variables. In the previously posted version, I used the hook type WH_JOURNALRECORD. Unfortunately, I discovered that the set hook call failed in Windows 8. However, by changing the call to the Low Level mouse hook, WH_MOUSE_LL, and then changing the mouse message handling function so that wParam and lParam are handled correctly, the problem is solved. wParam contains the specific mouse message such as WM_LBUTTONDOWN and WM_MOUSEMOVE and lParam is a pointer to an MSLLHOOKSTRUCT that provides location information. Therefore, the new code for MouseProc is:

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) { 
    CPoint ptLocation;
    
    MSLLHOOKSTRUCT * Msg = (MSLLHOOKSTRUCT *)lParam; 
    ptLocation = Msg->pt;
    if (wParam == WM_LBUTTONDOWN) 
    { 
        pDialog->GrabColour(ptLocation); 
    } 
    if (wParam == WM_MOUSEMOVE)
    { 
        pDialog->ShowCoordinates(ptLocation); 
    } 
    LRESULT result = CallNextHookEx(handleHook, nCode, wParam, lParam); 
    return result; 
 } 

Notice that this is very simple. The function determines the cursor position and then processes just two messages, WM_LBUTTONDOWN and MW_MOUSEMOVE. For each of these messages, a method belonging to CColourGrabber2Dlg is called.

In CColourGrabber2Dlg::InitDialog, make the dialog accessible to the MouseProc function:

pDialog = this;  

In CColourGrabber2::OnBnClickedPickColourButton, place the statements:

handleHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC) MouseProc, GetModuleHandle(NULL), NULL); 

Now define the functions that will process the mouse information:

void CColourGrabber2Dlg::GrabColour(CPoint point)
{
    if (m_bGetPostion ) // this is a member variable set to true 
            // when the "Get Colour" button is clicked
    {
        CDC dcScreen ;
        dcScreen.CreateDC("DISPLAY", NULL, NULL, NULL);

        COLORREF crPixelColour = GetPixel(dcScreen.GetSafeHdc(), 
            point.x, point.y);
        // Do something with the information such as 
        // set a control’s background colour to the colour just
        // grabbed and report the position 

        ReleaseDC(&dcScreen);
        m_bGetPosition = false;
        UnhookWindowsHookEx(handleHook);
    }

and:

void CColourGrabber2Dlg::ShowCoordinates(CPoint point )
{
    if (m_bGetPostion)
    {
        CDC dcScreen ;
        dcScreen.CreateDC("DISPLAY", NULL, NULL, NULL);
        COLORREF crPixelColour  = GetPixel(dcScreen.GetSafeHdc(), 
            point.x, point.y);
        // Again do something with the information about the
        // position of the cursor as the mouse moves it such as
        // dynamically changing the text and background colour of
        // a static control.

        ReleaseDC(&dcScreen);
    }
}

Everything else in the project is for displaying and using the colour and position information. I hope others find this helpful.

Please also note that the project uses the Ultimate TCP-IP library which is not included with the source files.

Acknowledgements

History

  • Version 2.0 June 14, 2013: The move to using hooks provides a significant improvement to the user interface for a colour grabber.
  • Version 2.2 March 5, 2014: Version 2.0 did not work with Windows 8.1. Changes to the hook type (WH_MOUSE_LL from WH_JOURNALRECORD) and subsequent changes to the function processing the messages from the mouse have solved the problem.

License

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

Share

About the Author

rbrunton
Software Developer BruntonSoft Software
Canada Canada
Retired teacher, I have enjoyed programming as recreation since 1983. I began with Pascal and subsequently learned C and C++ (as an amature). I continue to learn and develop programs.

Comments and Discussions

 
QuestionError : unable to open file "Resource.h". Pinmemberredbat6-Mar-14 14:19 
AnswerRe: Error : unable to open file "Resource.h". Pinmemberrbrunton7-Mar-14 2:41 
GeneralRe: Error : unable to open file "Resource.h". Pinmemberredbat9-Mar-14 15:00 
QuestionZip file corrupt PinmemberMartin Hart Turner5-Mar-14 22:55 
AnswerRe: Zip file corrupt Pinmemberrbrunton6-Mar-14 2:22 
AnswerRe: Zip file corrupt Pinmemberrbrunton6-Mar-14 4:10 
GeneralRe: Zip file corrupt PinmemberMartin Hart Turner6-Mar-14 4:48 
QuestionDoes not work in Windows 8 Pinmemberrbrunton20-Oct-13 5:46 
AnswerRe: Does not work in Windows 8 Pinmemberrbrunton7-Mar-14 2:45 
GeneralThanks for the updated code PinmemberJan Zumwalt17-Jun-13 11:24 
GeneralMy vote of 5 PinmemberJan Zumwalt17-Jun-13 11:19 
GeneralMy vote of 3 PinmemberJan Zumwalt17-Jun-13 9:41 
GeneralRe: My vote of 3 Pinmemberrbrunton17-Jun-13 10:38 
GeneralRe: My vote of 3 PinmemberHerbert H Dupree II6-Mar-14 14:13 
GeneralRe: My vote of 3 Pinmemberrbrunton7-Mar-14 2:21 
GeneralRe: My vote of 3 PinmemberHerbert H Dupree II7-Mar-14 19:01 
GeneralRe: My vote of 3 Pinmemberrbrunton8-Mar-14 2:05 
GeneralRe: My vote of 3 PinmemberHerbert H Dupree II8-Mar-14 10:18 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411023.1 | Last Updated 5 Mar 2014
Article Copyright 2013 by rbrunton
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid