Click here to Skip to main content
15,875,017 members
Articles / Web Development / HTML
Tip/Trick

ColourGrabber2

Rate me:
Please Sign up or sign in to vote.
4.83/5 (4 votes)
5 Mar 2014CPOL2 min read 33.9K   214   13   18
Using Windows hooks to capture mouse action.

Image 1

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...

C++
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:

C++
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:

C++
pDialog = this;  

In CColourGrabber2::OnBnClickedPickColourButton, place the statements:

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

Now define the functions that will process the mouse information:

C++
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:

C++
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)


Written By
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". Pin
redbat6-Mar-14 13:19
redbat6-Mar-14 13:19 
AnswerRe: Error : unable to open file "Resource.h". Pin
rbrunton7-Mar-14 1:41
rbrunton7-Mar-14 1:41 
GeneralRe: Error : unable to open file "Resource.h". Pin
redbat9-Mar-14 14:00
redbat9-Mar-14 14:00 
QuestionZip file corrupt Pin
Martin Hart Turner5-Mar-14 21:55
Martin Hart Turner5-Mar-14 21:55 
AnswerRe: Zip file corrupt Pin
rbrunton6-Mar-14 1:22
rbrunton6-Mar-14 1:22 
AnswerRe: Zip file corrupt Pin
rbrunton6-Mar-14 3:10
rbrunton6-Mar-14 3:10 
GeneralRe: Zip file corrupt Pin
Martin Hart Turner6-Mar-14 3:48
Martin Hart Turner6-Mar-14 3:48 
QuestionDoes not work in Windows 8 Pin
rbrunton20-Oct-13 4:46
rbrunton20-Oct-13 4:46 
AnswerRe: Does not work in Windows 8 Pin
rbrunton7-Mar-14 1:45
rbrunton7-Mar-14 1:45 
GeneralThanks for the updated code Pin
Jan Zumwalt17-Jun-13 10:24
Jan Zumwalt17-Jun-13 10:24 
GeneralMy vote of 5 Pin
Jan Zumwalt17-Jun-13 10:19
Jan Zumwalt17-Jun-13 10:19 
GeneralMy vote of 3 Pin
Jan Zumwalt17-Jun-13 8:41
Jan Zumwalt17-Jun-13 8:41 
GeneralRe: My vote of 3 Pin
rbrunton17-Jun-13 9:38
rbrunton17-Jun-13 9:38 
GeneralRe: My vote of 3 Pin
Herbert H Dupree II6-Mar-14 13:13
professionalHerbert H Dupree II6-Mar-14 13:13 
GeneralRe: My vote of 3 Pin
rbrunton7-Mar-14 1:21
rbrunton7-Mar-14 1:21 
GeneralRe: My vote of 3 Pin
Herbert H Dupree II7-Mar-14 18:01
professionalHerbert H Dupree II7-Mar-14 18:01 
GeneralRe: My vote of 3 Pin
rbrunton8-Mar-14 1:05
rbrunton8-Mar-14 1:05 
GeneralRe: My vote of 3 Pin
Herbert H Dupree II8-Mar-14 9:18
professionalHerbert H Dupree II8-Mar-14 9:18 

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.