HOW NOT TO compute the inverse of a colour

I once wrote a simple VB utility that acted like a window decorator, allowing the user to redact any window on the desktop by highlighting on a rectangular region within it. The highlighting code tracked the user mouse movements and drew the selected region as a hollow rectangle with black border.

My highlighting code had a problem: what if the window you're highlighting had a black background? That would render the highlighting rectangle virtually invisible, wouldn't it?

The code really should have used, for its border colour, the inverse colour of whatever the window's background colour is. OK...How the heck do we compute the inverse colour in VB?

Well, some quick googling yielded this link, which seemed to be somewhat useful:

Take any point in the [RGB] cube, then draw a line from this point to the centroid. If you then extend this line through the centroid the same length as between the original point and the centroid, you will have found the inverse colour to that defined by the original point. Inverting an RGB image involves a kind of turning inside out of the colour values.


uhh, yeah...

So, anyway, I did some more googling, and it turned out that there was a simpler way to do this in VB, thanks to this link.

The trick is in using a PictureBox and the vbInvert constant. The PictureBox will serve as the drawing canvas, onto which a snapshot of the actual window is placed for selection. The following simplified pseudocode illustrates the rest:


' Initializes PictureBox drawing settings
Private Sub Form_Load()
' Set drawmode to draw using the invert of the background colour
Picture1.DrawMode = vbInvert
' Set pen width
Picture1.DrawWidth = 2
...
End Sub
...
...
Private Sub Picture1_MouseDown(Button As Integer, _
Shift As Integer, _
X As Single, _
Y As Single)
If Button <> LEFT Then Exit Sub
LeftDowned = True
' Store [X,Y] as [Left,Top]
...
...
End Sub
...
...
Private Sub Picture1_MouseMove(Button As Integer, _
Shift As Integer, _
X As Single, _
Y As Single)
If Not LeftDowned Then Exit Sub

' Clear previous drawn rectangle
...
' Get current drag region [Top, Left,Bottom,Right]
...
' Draw new rectangle
Picture1.Line (Left, Top)-(Right, Bottom), vbBlack, B
End Sub
...
...
Private Sub Picture1_MouseUp(Button As Integer, _
Shift As Integer, _
X As Single, _
Y As Single)
' Re-set [Left,Top,Right,Bottom] = [0,0,0,0]
...
LeftDowned = False
...
End Sub


The moral of the story is this: There is a simple solution out there somewhere, waiting to be discovered. So keep googling, ya lazy bastard!

0 comments: