Groups | Blog | Home
all groups > dotnet drawing api > october 2006 >

dotnet drawing api : Get the COLOR under the mouse anywhere


pamela fluente
10/15/2006 12:07:07 PM

Hi guys. A hard problem ;)

I have a form. The form has: 1 Label, 1 Panel.

I wish that

1. while the mouse move anywhere on the screen, that the label
continuosly shows the RGB values of the color pointed by the mouse
2. when one clicks, the panel background color is set to the current
color.

I have no idea how to do that. Can anyone show me how I can do that?

(if not clear, I am talking about displaying the color of *any* point
of the screen, not only those of my form, which I should know how to
do)

-P
pamela fluente
10/16/2006 4:00:58 AM




Joergen Bech ha scritto:

[quoted text, click to view]


Hi,
I need something which could work continusly. I need to show the pixel
color
under the mouse while it moves, then when clicked I need to get the
color. How can I do this in an appropriate way ?

[quoted text, click to view]
pamela fluente
10/16/2006 6:39:39 AM

Joergen Bech ha scritto:

[quoted text, click to view]

What I need to do is actually quite to explain simple.

I want to let the user to pick a color from the screen and to use it
within the application.
Something similar to the color picker that you can see for instance in
photoshop.

So I really need something simple: just show and get the color pointed
by the mouse. I do not care about other applications (like I should
perhaps in case of a magnifier, and that would be much more complicate,
I guess). I just need the current color of 1 pixel.


-P
pamela fluente
10/16/2006 8:22:41 AM
Thank you very much Joergen.

This works fine. But, actually somehow "inverse" way I need.

Is there no way to get continuosly the color while the mouse move over
the screen and to get it only when the mouse is clicked?

This is a possible sequence (in case can be adjusted) :

1. Click on a "Color Picker" button of my application (to start
the "pick" action)
2. move the mouse over the screen signaling the current color
3. Click (or Ctrl-Click) and - at this time . the color is
trasmitted to my application

if this is too difficult, perhaps I could change my logic to use your
method ...

-P

Joergen Bech ha scritto:

[quoted text, click to view]
Joergen Bech <jbech<NOSPAM> NO[at]SPAM
10/16/2006 9:57:26 AM

Just out of curiosity: Isn't CopyFromScreen one of those things one
should avoid calling continuously when using the Aero interface in
Windows Vista?

Beneath the covers, it calls

DeviceContext.FromHwnd(IntPtr.Zero)

which is fine for a screen capture application, but maybe not
for continuous queries due to constant GDI/DirectX10 context
switching?

I guess if the point query only runs a few times a second in a
timer would be okay?

/JB



On Mon, 16 Oct 2006 13:13:27 +1000, "Lloyd Dupont" <net.galador@ld>
[quoted text, click to view]
Lloyd Dupont
10/16/2006 1:13:27 PM
Something like:
Graphics.CopyFromScreen() ??

[quoted text, click to view]

Joergen Bech <jbech<NOSPAM> NO[at]SPAM
10/16/2006 2:37:22 PM
[quoted text, click to view]

I am not quite sure what you mean. Either of

1) You want something like what a screen magnifier does, i.e. inspect
what is under the mouse, but not actually interferring with normal
mouse operations. In this case, even though you are just moving
the mouse, other applications might change appearance, e.g. when
moving the mouse over a toolbar icon. Your application has no way
of detecting that you clicked the mouse button, so you would have
to use a hotkey or similar to tell the application that you want to
grab something now.

In this case, just grab the screen (pixel) at the time the hotkey
is invoked.

2) Like 1), but instead of using a hotkey, you can capture the mouse
until the mouse button has been clicked. In this case, other
applications will not be affected by moving the mouse over them,
but the user needs to initiate the "I want to grab a color now"
sequence somehow (e.g. by clicking a button or by invoking
the inspection window).

3) Your application maintains control of the mouse and you do not
want any applications to change their appearance while you move
the mouse over them. In this case you could grab the entire
desktop, then overlay the desktop with a full-screen form
containing this screen grab. Put your inspection window
on top of this full-screen form. When the mouse button is clicked,
remove the full-screen overlay.
Like 2), this requires initiation by the user.

4) Rather than faking it like in 3), you could simply grab a copy of
the desktop, but instead of displaying it in an overlay (giving
the illusion that the desktop is still visible), just put it in a
scollable window and let the user inspect the pixels in that
window. Although this might require that the user resizes
and/or scrolls this window, it is much more obvious what is
going on.
At any rate, providing some kind of zooming functionality is
normally beneficial, in which case this would be the best
solution, but I do not know what your application is supposed
to do.

BTW: I tried an old (non-.Net) magnifier application (Zoom+) on Vista
with
Aero enabled, and it did not seem to have any problems querying
the screen multiple times a second. Perhaps there is no problem after
all? At any rate, whatever you do, if you use the desktop device
context, test it on Vista with Aero enabled. Just in case. I'm not
sure.

/JB



Joergen Bech <jbech<NOSPAM> NO[at]SPAM
10/16/2006 4:55:41 PM
On 16 Oct 2006 06:39:39 -0700, "pamela fluente"
[quoted text, click to view]

Start a new project. Put a PictureBox and a Label on Form1.

Paste the following code:
---snip---

Public Class Form1
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e
As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
Label1.Text = "X, Y = " & e.X.ToString & ", " & e.Y.ToString &
": Color = " &
GetPixelColor(PictureBox1.PointToScreen(e.Location)).ToArgb.ToString("X8")
End Sub

Private Function GetPixelColor(ByVal screenLocation As Point) As
Color
Dim bm As New Bitmap(1, 1, Imaging.PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(bm)
g.CopyFromScreen(screenLocation, New Point(0, 0), New Size(1,
1))
Dim result As Color = bm.GetPixel(0, 0)
g.Dispose()
bm.Dispose()
Return result
End Function

End Class
---snip---

Run the program. Hold down the left mouse button when it is over
the picturebox, then move the mouse around the screen while still
holding down the mousebutton. I do not know if this is the right way
to do it, but it works and this is what the first one to reply
suggested.

You need to add a message filter or whatever to get the mouse
position regardless of what your mouse is over or whether the button
is down or not, but that is another topic.

/JB


Joergen Bech <jbech<NOSPAM> NO[at]SPAM
10/16/2006 5:47:15 PM

That is what I mentioned in the closing remark: You need to add a
filter to process mouse messages outside normal usage, which is an
entirely different topic.

Google for "prefiltermessage" and "addmessagefilter" and you should
be on your way.
http://blogs.msdn.com/jfoscoding/archive/2005/07/28/444647.aspx

Oh ... and if you go that route, make sure you know what you are
doing :)

Perhaps you can implement a much simpler solution using
Control.Capture, but I don't think so.

/JB



On 16 Oct 2006 08:22:41 -0700, "pamela fluente"
[quoted text, click to view]
pamela fluente
10/16/2006 10:19:51 PM

Joergen Bech ha scritto:

Thanks for the nice help Joergen :)

-P
[quoted text, click to view]
Bob Powell [MVP]
10/17/2006 6:14:32 PM
Theres an article on this in the FAQ.

Because the mouse messages are destined for a specific window you cannot
move the mouse outside of a window and still react to it's events unless
you've captured the mouse. I suggest that you should click at some place on
your form, capture the mouse and then use the technique shown in the
eyedropper article to obtain the colour under that point. When the mouse is
released, the capture should be released also.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.



[quoted text, click to view]

Michael C
10/18/2006 12:00:00 AM
[quoted text, click to view]

I was going to suggest Control.Capture. This will keep sending mousemove
events back to the original control no matter where the mouse is. The
OnLeave event might cause problems as I think it kills the capture.

Michael

AddThis Social Bookmark Button