C is for... Color
Dealing with color in .NET isn't always black-and-white, given the existence of distinct Color structures present in two different .NET namespaces.
Windows Forms applications make use of the Color structure in the System.Drawing namespace, while Windows Presentation Foundation (WPF) applications use the System.Windows.Media namespace. Each of these structures supports alpha transparency (A) and the customary red (R), green (G), and blue (B) channels via byte properties, and each has a method, FromArgb, to assemble those channels into the desired color.
The following screen shots show how you can programmatically set the background of a Windows Form and a WPF window to the color mimosa, the 2009 Pantone Color of the Year (and a fine cocktail as well).
There's a few differences that come to light right away when comparing the two examples above. First, while both use a FromArgb method, the System.Drawing namespace version has some overloads, so the alpha channel in the Windows Forms sample defaults to 255.
The System.Windows.Media.Color.FromArgb method requires all four values to be explicitly set, but the structure also provides a FromRgb method in which the alpha channel also defaults to 255.
More notable though, is the fact that in WPF you don't assign the color directly, but rather do so via a brush. In this simple case, it's a SolidColorBrush, but the advanced rendering capabilities of WPF support many different types of brushes including three color brushes and three tile brushes:
That means you can easily create quite unique and appealing user experiences with WPF by combining colors into gradients, such as below.
In addition to the standard ARGB values (known as the sRGB color space), System.Windows.Media.Color also supports an enhanced color space known as scRGB. Here the color channel components are floating point values, ranging from 0.0 to 1.0, versus byte values ranging from 0 to 255. This results in a finer granularity of colors that can be represented. To support this additional color space, the following properties and methods are provided:
|Methods||FromScArgb||Create a new color structure from the component alpha and color channels|
|AreClose||Compare colors for fuzzy equality. (Since the component channels are floating point values, a test for strict equality is not recommended.)|
|Clamp||Set individual color channels to 0 or 1 if they fall outside of the range (which is possible as transformations are applied)|
|Properties||ScA||ScRGB alpha channel value|
|ScR||ScRGB red channel value|
|ScG||ScRGB green channel value|
|ScB||scRGB blue channel value|
Whenever you use the sRGB or scRGB properties, the analogous property of the other color space is automatically kept in sync, so for instance, the SolidColorBrush background color created on the first WPF window above reports the scRGB values shown in the following image:
System.Windows.Media.Color offers one additional technique for setting color values - using a custom ICC (International Color Consortium) profile. The structure includes two methods (FromAValues and FromValues) and one property (ColorContext) that supports this more advanced mechanism designed to provide cross-platform, cross-device, and cross-application color compatibility.
When working on Windows Forms applications or WPF applications, it's now clear that you deal with color differently, and unfortunately, there's no implicit casting or direct conversion capability (other than creating a new object based on the ARGB values of the source color).
So, what happens when your (color) worlds collide and you're using WPF-Windows Forms interoperability? To support a seamless integration, property mapping is provided on both WindowsFormsHost (used to host a Windows Forms control on a WPF page) and ElementHost (used to host a WPF element on a Windows Form). The default mapping specifies the translation rules for the foreground and and background color properties as well as additional properties for fonts, cursors, and visibility, but customized mappings are supported via the PropertyMap property.