Win32 COLORREF vs .NET Color

2007, Aug 23    

I have been migrating a large application from Win32/MFC to .NET and ran into an interesting problem. We store all of the application colors in the database as integers that represent the Win32 COLORREF value. COLORREF is just a DWORD representing the RGB value, so I thought that I could just take the value and get a .NET Color structure using the static FromArgb method.

This didn't go too well. It turns out that the byte orders are different. COLORREF is in the order 0x00bbggrr and Color is in the order 0xaarrggbb. Notice that the high order byte in .NET is the alpha channel, but in Win32 it is always zero (fully transparent in .NET) Also notice that the byte order is backwards in Win32, Blue/Green/Red compared to the more standard Red/Green/Blue in .NET.

We began by doing the conversion in code using a bit of bit fiddling;

public static Color ConvertFromWin32Color( int color )
{
    int r = color & 0x000000FF;
    int g = ( color & 0x0000FF00 ) >> 8;
    int b = ( color & 0x00FF0000 ) >> 16;
    return Color.FromArgb( r, g, b );
}

This worked well at first, but it was error prone converting between the values. As new code was written, we often forgot that we needed to convert. Finally we decided to do the right thing and convert the values in the database. To do this, I wrote a simple upgrade script for our SQL Server database that consisted of one method which was then applied to each column in the database that contained color values.

-- =============================================
-- Author: Rob Prouse
-- Date: 15/08/07
-- Description: Convert control colors from
-- Win32 COLORREF (0x00BBGGRR) values to .NET
-- Color Values (0xFFRRGGBB)
-- =============================================
CREATE FUNCTION SwapColorBytes( @Color int )
RETURNS int
AS
BEGIN
    RETURN 0xFF000000 +
    ((@Color & 0x00FF0000)/0x00010000) +
    (@Color & 0x0000FF00) +
    (( @Color & 0x000000FF)*0x00010000)

END
GO

-- Do the following for every column in the DB that contains colors
UPDATE mytable SET colorcolumn = SwapColorBytes(colorcolumn)
GO