Pixel Color Under Mouse

This is a feature that I wanted for a tool I’m doing. I have a color selection control that can select the color of the pixel under the mouse position from the entire application window. I searched the web for a solution and I found a cool implementation from theWPFblog, as Lee Brimelow explains:

I tried many different ways of doing this but the cleanest was to use the CroppedBitmap class. As you can see in the code below, I first pull out a 1×1 pixel cropped bitmap from the color picker image that is directly below the mouse. Then it’s just a matter of copying the 1 pixel into a byte array and reading the RGB values. There are 4 bytes in every pixel which corresponds to the RGB colors and 1 byte for alpha. To change the color of the rectangle I simply create a new SolidColorBrush from the RGB values. I can think of many great uses for this! Click on the image at the left to check out the app. The C# source code is listed below so you can check out exactly how I implemented it.

The code can be found here.

Another Alternative

Lee’s solution is not good enough for me because I need a color from a pixel found in the entire client area of my application, and Lee’s solution forces me to have a BitmapSource to take the pixel from it.

I found a cleanest way to do that, maybe not clean in “WPF” speaking but using only three simple Win32 functions:

private struct POINT
{
    public uint X;
    public uint Y;
}

[DllImport("gdi32")]
private static extern int GetPixel(int hdc, int nXPos,int nYPos);
[DllImport("user32")]
private static extern int GetWindowDC(int hwnd);
[DllImport("user32")]
private static extern int GetCursorPos(out POINTAPI lpPoint);
[DllImport("user32")]
private static extern int ReleaseDC(int hWnd, int hDC);

 

And here is the GetPixelColor method implementation:

private static SolidColorBrush GetPixelColor(Point point)
{
    int lDC = GetWindowDC( 0 );
    int intColor = GetPixel( lDC, (int)point.X, (int)point.Y );
    //
    // Release the DC after getting the Color.
    ReleaseDC( 0, lDC );

    //byte a = (byte)( ( intColor >> 0x18 ) & 0xffL );
    byte b = (byte)( ( intColor >> 0x10 ) & 0xffL );
    byte g = (byte)( ( intColor >> 8 ) & 0xffL );
    byte r = (byte)( intColor & 0xffL );
    Color color = Color.FromRgb( r, g, b );
    return new SolidColorBrush( color );
}

With GetWindowDC( 0 )  I ask for the entire window DC, which then I use with GetPixelColor that retrieves the color value from position.

The System.Windows.Media.Color class in WPF doesn’t have a FromArgb method that accepts a integer value of the color as its counterpart from System.Drawing.Color, so I break apart the RGB components from integer value.

Using it:

    protected override void OnMouseMove(MouseEventArgs e)
    {
        POINT point;
        GetCursorPos( out point );
        Point pos = new Point( point.X, point.Y );
        this.StrokeBrush = GetPixelColor( pos );
    }

This is an alternative solution, for getting the color under the mouse position even when you don’t have a BitmapSource to take it from or you are mixing WinForms or Win32 with WPF.

Have fun!

5 Responses to “Pixel Color Under Mouse”

  1. Jobi Says:

    Is there a way we can get the Alpha channel also

    Thanks
    Jobi

  2. andresd Says:

    Hi Jobi,

    As far as I know you can’t do it, at least with XP and the hardware I have (didn’t check with Vista), in all the tests I did, transparent colors are rendered as a non transparent color, with the RGB value changed to simulate the transparency, based on the pixel color already rendered beneath.

    Regards,
    Andrés

  3. Chris Says:

    Don’t forget to call ReleaseDC() when you are done!

  4. andresd Says:

    Thanks Chris, I have updated the sample above.

  5. Jammer Says:

    should:

    private struct POINT
    {
    public uint X;
    public uint Y;
    }

    actually be

    private struct POINTAPI
    {
    public uint X;
    public uint Y;
    }

    ????

Leave a Reply