This post is inspired by a recent one by Saveen Reddy on creating a bitmap color wheel image. Saveen’s post demonstrates some C# code to generate a png image pixel by pixel. I thought this might make a handy shape in Visio when you want manipulate colors without opening the modal format dialogs within Visio itself.
Shape structure
The shape contains three control handles:- one on the color wheel to adjust the hue, another on the horizontal bar to adjust the saturation and a third on the vertical bar to change the luminosity. The shape’s text displays the current color in one of three formats. A last feature pushes these RGB, HSL and HEX values out to the shape’s Shape Data fields to enable the user to copy and paste the color formulae to a cell. (Note – that Visio doesn’t use Hex values directly, but I’ve added it just in case you’re using this in a web based scenario.)
Context menu options allow you to:
- reset the saturation and luminosity values to fully saturated and the luminosity mid point respectively.
- set the shape’s background color to white or gray (as above). Note, that you can set any custom background color via the fill format UI, but white and gray are the two presets. If you want to alter the default gray, you can edit the User.Gray ShapeSheet cell as you wish.
- toggle the visibility of the formula text Shape Data fields.
So that’s how it works, but I’m guessing that if you’re the type of person that wants to use this shape then you’re probably also interested in how it’s built…
Shape building
From a construction perspective, this is an interesting shape as it requires you to solve a number of problems, namely:
- How to get a control handle to track the perimeter of a circle
- How to convert decimal color values to their Hexadecimal equivalents
- How to use the color functions within Visio to extract the Red, Green and Blue components along with their Hue, Saturation and Luminosity counterparts.
To solve these problems I’ve borrowed from a couple of places:
Perimeter tracking - Firstly the control handle on the color wheel uses a technique described in Graham Wideman’s book: Visio 2003 Developer’s Survival Pack. Basically this uses the SETATREF family of ShapeSheet functions to push the ‘Raw’ incoming x and y values of the control handle into some user cells and then reads a coerced or calculate value back again to position the actual yellow handles. If you want the full explanation then I would still recommend buying Graham’s book – it’s still a must have for serious Visio developers.
Hex values - Visio doesn’t have any decimal to hexadecimal function built in, but guess what? Chris Roth from VisGuy.com does. This time I’ve borrowed Chris’ idea of using a hexadecimal characters list to create the hex text. It’s a clever formula that gets the appropriate first character from a given color component and then the remainder converts to the second character. You can read more about this over at his blog here:
The final key part of this shape is the use of Visio’s color functions. The RED, GREEN and BLUE ShapeSheet functions are fairly self explanatory, but the SATURATION and LUMINOSITY functions are the important elements in creating the equivalent horizontal and vertical gradient bars. For the saturation bar the gradient is fairly straight forward using the following HSL formulae:
As you can see, the only difference between the foreground and background colors is the saturation value, which is 0 for the background and fully saturated (240) for the foreground.
The luminosity bar uses a similar principle, but this time the saturation remains constant and it’s the luminosity value that changes. Another difference for the luminosity bar is that that it has three gradient stops (rather than the two for the saturation bar). This means that you need to have two adjacent bars to accommodate the three colors involved:- white, the current color’s luminosity mid-point and black.
So, I hope that you find the shape useful and thanks to Saveen for creating the image code in the first place. Click here to download ColorSelector.vsd