1. Home
  2. Computing & Technology
  3. Visual Basic
Calculating a Contrasting Color Code
Part 6: The Second Bug and VB .NET
 More of this Feature
• Part 1: VBA - Calculating a Contrasting Color Code
• Part 2: The First Solution Attempt
• Part 3: The Second Solution Attempt
• Part 4: The First Bug
• Part 5: Symbolic Logic in Visual Basic
• Part 7: Lessons Learned
 
 Join the Discussion
Is this the kind of article that helps you?
Let us know!
 
 Related Resources
• Beginning Visual Basic
• Visual Basic 6
 
 Elsewhere on the Web
• A short intro to binary numbers
• Binary, Decimal, and Logic
• Color Differences
VB 6 versus VB .NET

 

This is also where I ran into the second interesting bug.

The trailing ampersand on GreenMask (&HFF00&) is necessary and the failure to include it is an example of the type of subtle bug that VB 6 sometimes presents to you. Keep in mind that the values being assigned are all binary numbers in the computer and the only difference is how they are interpreted. Without the trailing ampersand, VB 6 assumes that &HFF00& is an Integer type. The value assigned to it, however, makes the high bit a binary one. The rules of VB 6 state that when the high order bit of an Integer type is one, the number is a negative number. The net result is that the formula uses the wrong value -- but only for GreenMask! BlueMask is a large enough number to be "automagically" assigned a Long type and RedMask is small enough so it doesn't get interpreted as a negative number because the high bit is zero.

Although this was an interesting bug, the real reason it's worth writing about is that it's an ideal example of why VB .NET's "strong typing" is such a good idea. To understand this, it's worth noting that you can avoid this same bug in VB 6 by simply using the built-in constants vbBlue, vbGreen, and vbRed instead of defining your own Const values. The built-in constants already have the correct type. This is not a recommendation to use these built-in constants as masks since they're really intended as color codes and this could be considered to be bad programming style. The point is that system defined objects, even in VB 6, can have more uniform and predictable properties than values that you define yourself.

This idea is taken much further in VB .NET. You never run into this species of bug because VB .NET REQUIRES that the type of every object be explicitly declared. The only reason this bug is possible in VB 6 is that VB 6 "assumes" (Remember, "ass, u and me"?) that it can figure out what data type you want to assign to variables. In this case, VB 6 gets it really wrong in one of the three constants.

VB .NET also avoids the first problem (the confusing way Microsoft encodes colors as both "Red-Green-Blue" and "Blue-Green-Red" in different circumstances). The OOP (Object Oriented Programming) principle of "Encapsulation" states that we should never care how an object is implemented internally and VB .NET doesn't tell you. Colors are objects in VB .NET, not a constant or a value. (Actually, they're at least two different objects: System.Drawing.Color and System.Drawing.SystemColors.)

Maybe another way to say it is that "Encapsulation means never having to say you're sorry."

When I shared these new results with my programming friend, he said, "Whoa! If all you want to do is flip the bits, just use an "all ones" mask for the entire code:

txtDisplay.ForeColor = _
    ((txtDisplay.BackColor Xor &HFFFFFF) And &HFFFFFF) _
    Or (txtDisplay.BackColor) And (Not &HFFFFFF)

This makes my original version using strings look complicated, inefficient, and ... well ... pretty stupid. But by this time, we had learned even more about color codes in VB 6. Actually, you don't need most of the logical calculation. Simply using ...

txtDisplay.ForeColor = _
    txtDisplay.BackColor Xor &HFFFFFF

... seemed to work fine too. It should be noted that none of these methods work when the high order bits of the color code are not zero. And we discovered that they could be non-zero. The Microsoft VB 6 documentation also states,

"Setting the most significant bit to 1 changes the meaning of the color value: It no longer represents an RGB color, but an environment-wide color specified through the Windows Control Panel. The values that correspond to these system-wide colors range from &H80000000 to &H80000015."

Using the Properties dialog to set BackColor to the color value Scroll Bars (&H80000000) results in a program error. Another logical calculation could be used to avoid the error:

If (txtDisplay.BackColor And &HFF000000&) = 0 Then
  <perform the above calculation>
Else
  <the above calculation won't work>
End If

(Also, the System color palette goes to at least &H80000018. Never trust the documentation completely.)

Having come this far, I thought it might be interesting to see what the difference was between the original formula in the Forum (new_color = &HFFFFFF - old_color) and what we were calculating using our methods. Much to my horror, I discovered that the simple formula in the question gave the identically same result!

In other words, all this effort was for exactly nothing in terms of the original problem!

Xor versus Subtract

The reason this is true became obvious after a moment contemplating the Truth Table for Xor compared with subtraction. I remembered then that I had learned this all at least once before in a computer science class.

Time to look for something to laugh about: Why do programmers have sloped foreheads? The answer? "Doh!!" (Hitting forehead in the classic Homer Simpson style)

Next page > Lessons Learned > Page 1, 2, 3, 4 5, 6, 7
Explore Visual Basic
By Category
About.com Special Features

Holiday Central

What to eat, where to go, fun things to do and how to save money on the perfect gifts. More >

Family Tech Center

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. More >

  1. Home
  2. Computing & Technology
  3. Visual Basic

©2009 About.com, a part of The New York Times Company.

All rights reserved.