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!





November 7, 2007 at 1:23 am |
Is there a way we can get the Alpha channel also
Thanks
Jobi
November 7, 2007 at 11:45 am |
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
May 24, 2008 at 6:46 am |
Don’t forget to call ReleaseDC() when you are done!
May 24, 2008 at 10:19 pm |
Thanks Chris, I have updated the sample above.
June 5, 2008 at 5:55 pm |
should:
private struct POINT
{
public uint X;
public uint Y;
}
actually be
private struct POINTAPI
{
public uint X;
public uint Y;
}
????