Environment

ColorSpy was created with VC++ 6.0 SP5 with WTL 7.0, and was mainly tested on my machine Win2k with SP3. To build, you will need WTL installed. At the time of writing this, MS WTL can be found here. If you haven't tried it out, go get it.

Picking up and sampling a pixel color on screen

In practice, I created a transparent window with WS_EX_TRANSPARENT style, which covered the entire screen, but soon realized that use of transparent window would not work; you can see all pixel colors through the transparent window, but mouse events won't get through.

The way ColorSpy picks up the pixel color was inspired by other utility apps (e.g. WindowFinder). It adapts one of the golden rules of Windows programming found in those utilities. The golden rule is that when you find there is no appropriate message to response to, you make it yourself. ColorSpy also uses a timer to create its application specific message (WM_APP_COLORSPY) periodically and then responses to the message by itself, picking up a color of the pixel located by mouse cursor:

Controlling over the timer will be a key for sampling colors. When holding down CTRL+SHIFT, by killing the timer, ColorSpy samples a pixel color and stores it in colorbox. It becomes inactive until you hit the colorbox again.

If you kept running timer instead, you could always resume color picking using CTRL+SHIFT as a toggle key... but customization is all up to you... there is always more than one way to do it.

Reading color codes from HTML source

When ColorSpy is inactive (while no timer ticking), ColorSpy has a different work to do; it reads a color code (in '#RRGGBB' form including preceding '#') from an HTML file. For example, you visit a web site and view source or open an HTML file in the editor you use.

Selecting the color code and simply pressing CTRL+C will give you a color you have selected.

To do this, ColorSpy utilizes a clipboard management feature called Clipboard viewer window, so it can read color codes clipped by the user. Here is a template class sample that turns ColorSpy into a clipboard viewer window for color-code-watching extension:

Clipboard (viewer window) management

Previously, I stated incorrectly. CB viewer windows are really supposed to respond to WM_CHANGECBCHAIN message and refresh a pointer to a handler to next viewer window.

If you search web pages on clipboard viewer, you may find SDK documentation like this:

Creating a clipboard viewer window

A clipboard viewer window displays the current content of the clipboard, and receives messages when the clipboard content changes.

To create a clipboard viewer window, your application must do the following:

Add the window to the clipboard viewer chain.

Process the WM_CHANGECBCHAIN message.

Process the WM_DRAWCLIPBOARD message.

Remove the window from the clipboard viewer chain before it is destroyed.

Here is my observation and vital update of CB viewer on Windows 2000 SP3. That is, the result on your machine would be most likely the same:

Add the window to the clipboard viewer chain. => TRUE. With WTL, you do that with CWindow::SetClipboardWindow()

Process the WM_CHANGECBCHAIN message. => TRUE

Process the WM_DRAWCLIPBOARD message. => TRUE but not quite. SDK documentation says "WPARAM is not used...", or "must be zero...". WM_DRAWCLIPBOARD, however, comes with WPARAM filled, and WPARAM is actually a handle to the window that has placed CB data. Probably I would not have realized what WPARAM value was, if I was using MFC. WTL is nice.

Remove the window from the clipboard viewer chain before it is destroyed. => TRUE. Make sure to call CWidnow::ChangeClipboardChain() on your way out.

The documentation on clipboard management API may deserve some remarks. Or does it?

Color names. Tell me your name.

If sampled color value matches the RGB value defined in Color name-to-RGB value table, ColorSpy shows its name in ToolTip. While ColorSpy is inactive, you can try color names like, darkviolet, navy, navajowhite and so on.

Before we start, you might want to pull up the source code for this update. To support color names (hereinafter called colornames), ColorSpy utilizes a modified version of RGB color name-to-value table defined in rgbtable.h, which was taken from Xpm library from XFree86 (See References). As supplemental information, ColorSpy displays color name as a tooltip text only if the sampled pixel color value matches any RGB value defined in the table. In addition to color triplets (#RRGGBB), it can also interpret a color name and display its color and RGB triplet by looking up the table.

I never thought this color table support would eventually lead to another story to tell you about.

While testing ColorSpy with colornames, I found that there is some unique color name interpretation in web browsers. Can you tell the names of the following colors rendered beautifully? Take a guess. You can run ColorSpy to check RGB values of these colors now.

Now time is up, sir. If you thought these were Green something, nice try. These are called Gray (grayXX). Unlike those browser unrecognizable color names, with which resultant color may depend on the type of browser you use. As you can see, these names are, however, somehow interpreted.

Because of this interpretation - RGB(0x00, 0xA0, 0xXX), where XX is numeric part of Gray color names except for gray100, which is black - I had to comment out the grayXX part from the original color table to avoid confusion. Color names may be informative, but they may not be that essential. Once you played around with color names and found your favorite color name, you can use triplet of the color instead. Oh BTW, this interpretation is a common among the browsers. Bottom line - Confusing yet intriguingly worthwhile.

Quick check on Desktop color settings

This feature is rather for developers, not for web designers. Instead of checking with Display Properties applet in Control Panel, you can check your desktop color settings from system color types (COLOR_XXXX defined in WinUser.h). For example,

COLOR_INFOBK, which is background color of ToolTips

COLOR_ACTIVECAPTION, which is color of the title bar for the active window (Go to Control Panel > Display > Color1 in Appearance)

All system color types are defined in CSysColors class. There are around 30 different display aspects as system color types. In colorbox.h, CSysColors is also used to determine whether ColorSpy should use system color brush based on your desktop settings as shown below:

#define HANDLE_SYS_COLOR_BRUSH(index) \
if (m_clrBackground == theSystemColors[index].clr) \
{ \
return brh.CreateSysColorBrush(index); \
}
HBRUSH CreateBrush()
{
// Use system cache
CBrushHandle brh;
// whatever color is requested, try matching your system color settings
// first; chances are the most of time it will hit one of them if you
// are not exploring the world of colors.
HANDLE_SYS_COLOR_BRUSH(COLOR_BACKGROUND); // Desktop color (same as
// COLOR_DESKTOP which sounds more descriptive)
[...] // rest omitted
}

When your mouse makes you nuts

You have tried out the earlier version and realized that it is hard to work on tity pictures. Why not try magnifier? This feature may be helpful especially when sampling pixel colors in a dense-colored picture.

Some utilities offer a magnifier, presents a zoomed picture, but somewhat make you feel like a machine when working on a single pixel. Why? Because you still have to pin-point a single pixel on on-screen while watching the zoomed picture. After all 2 px. mouse movement is still 2px. distance so no matter how hard you look at the magnifier, it only tells you the mouse cursor is still pointing to the wrong spot unless you can work on the zoomed picture.

ColorSpy's magnifier acts like a clickable panel with variable magnification levels. So take a snapshot first. You don't have to pin-point the pixel on screen. Then click a magnified image as many as you like. I hope with this feature you no longer have to fire up another magnifier application just for easier viewing. And next time you feel like a machine, you might go like "stinky mouse or is it? software? (possibly, with creepy background music)".

Simplicity over fancy stuff

My ColorSpy is a simple app. I am hoping it will be part of your desktop goodies because of its simplicity. With source code you can make your own ColorSpy. Idea is all yours.

This is my first attempt to write an article and I have always admired tireless work of folks here at CodeProject, contributing their articles. Crappy rating would be welcome if you could first tell me the reason why you have read my article...

License

Share

About the Author

Live (1994 "Throwing Copper" till 1999 "The Distance To Here") is one of his favorite bands.

After 9 years life in U.S, he lives in his hometown Yokohama, working in Automotive After-sales business. He sometimes found himself drunk once in a while in Munich.

He has put the period to his windows development after writing first and last article about a light-weight memory program, called colorspy (which is amusingly running on his latest windows except for dual display support.) He has a message to the WTL author, "you rock. you proved that WTL kicks ass, M*F*C". F, in the middle, always reminds him of somewhat different wording.

Time lapse

His codepen is live.copper. His main focus has changed to various web technologies, to build fastest EPC services for automotive clients instead of pharmaceutical ones. Ironically, he has not yet been released from the chaotic Windows software development installations even though he is no longer programming for Windows but for server side development.

Ein Prosit, Ein Prosit! He is still with a company in Munich as he loves to help people all over the world who need to fix their cars.

Thank you for the ideas. As said, "Idea is all yours", meaning you could addmore stuff yourself as you wish but it seems like my "making..." article should go on (?) so what the heck, I'll keep the color representation in mind in addition to my stuff, with which I am hoping to provoke your thoughts before summer ends

I have just verified: App-side chain management is still necessary; OnChangeCbChain is called if previously registered CB viewer calls ChangeClipboardChain() while being dismissed.

Back to my motivation, I *thought* this mandatory has been gone simply because this management style - relying on other applications to manage the chain or your fate - was utterly unreliable; what happens if the previous viewer missed to call ChangeClipboardChain API before exiting? Wouldn't it incur out-of-sync situation to other viewer windows?

I am updating my article to reflect correction and for the community's sake. OnChangeCbChain gets called.

1. Display a flag saying whether this is a web-safe color2. Display Name of the color, if it matches any of the web named colors3. Display index of the windows system color, if it matches any4. Transparency level of the window5. Options Dialog available from the context menu to choose how to display the color (hex/decimal), display or not pixels at all, speed of scan for point, + display or not features 1-4

Regards,Vitaly Tomilov

Professional tooltips for all development platforms available on www.Tooltips.NET