A customer saw that the DrawÂFocusÂRect
function was drawing an orange focus rectangle when applied to highlighted text. Whose bright idea was it for the focus rectangle to be orange?
The focus rectangle says, “I’m not orange. I’m just drawn that way.”
The focus rectangle is drawn by performing an XOR operation with a checkerboard brush. The idea behind using an XOR brush was that you could erase the focus rectangle by drawing it again. And the checkerboard brush means that both horizontal and vertical lines are dotted, and the corners match.
Rewind back to 1983. Most computer screens were monochrome. Bitmaps were one bit per pixel. And screens were 96 DPI.
In this world, XOR is a perfectly reasonable thing to do, since it looks good against both white¹ and black backgrounds.
A simple pattern of alternating white and black pixels gets you the dotted-line effect.
Of course, weird things happened if the focus rectangle was drawn against a non-solid background, but given the limitations of the hardware, you didn’t really have too much choice.
Fast-forward to the days of high-density 32-bit-per-pixel displays. That simple algorithm doesn’t produce results that are quite so pretty any more. For one thing, a single pixel dotted line is barely visible on high-density displays. And for another thing, XOR’ing colored pixels can produce strange effects.
In our case, what happened is that we took the blue color #0078D7
and flipped all the bits, producing #FF8728
, which is bright orange.
That’s where the orange comes from. The focus rectangle doesn’t draw orange. It just flips the pixels that are already there, and blue flips to orange.
The DrawÂFocusÂRect
function can’t do anything about the XOR brush, because that would break compatibility with code that used a second DrawÂFocusÂRect
to erase the focus rectangle. But at least it can do a little bit to help with the dotted rectangle: The thickness of the dotted rectangle is controlled by an accessibility setting. In Control Panel, under Ease of Access, Make the computer easier to see, you can check “Make the focus rectangle thicker”, which makes the focus rectangle two pixels thick instead of just being a dotted line.
Programs which draw their own focus indicators can match the accessibility setting by using the SPI_
and SPI_
system metrics.
Bonus chatter: The blinking line that indicates where typing will be inserted is called the caret, and it too is drawn by XOR. This works fine when the caret is against a white or black background, but again, if it’s against a colored background, things can get a little weird.
¹ Or, more likely, P1 phosphor green and black, or P3 phosphor amber and black.
The idea behind using an XOR brush was that you could erase the focus rectangle by drawing it again.
This explains a lot. Back in the days when everyone used GDI+ and liked it, these highlight rectangles would sporadically only get partially removed¹. It never occurred to me, that the application might be relying on the XOR-nature instead of redrawing the entire window (or part of it).
This brings me to the hypothesis, that when...
The color inverse of gray is… gray. Example.
You should never use mid values (i.e. 50% gray) as background when information is going to be placed on it. Human vision is far more sensitive to luminance than to chrominance, so the best way to make something readable is either dark text (or pictures) on clear background, or clear text (or pictures) on dark background. This is also why, for example, yellow on white, or navy blue on black, are really hard to read....
I agree with you, but Microsoft does not. https://aka.ms/AAeqt41
That is a very good point. The 50ish% gray as an edge-case isn't even all that rare either.
And since the XORing nature - and not just the 2nd-call-reverts-changes-nature - is actually documented, can't even be changed to use some other mapping where (which would at least enable the graphics designers to choose pairs of colors which look less odd than blue-orange and are more visible than gray-gray).
Ah, but it can – simply XOR with 50% grey,
0x7F7F7F
if you want colour inversion,0x808080
if you don’t. In at least Windows 95-2000 you also used to be able to do this with the mouse cursor, but of course this was undocumented behaviour and sadly stopped working in Windows XP.Actually,
0x7F7F7F
doesn’t work on light grey0xC0C0C0
because it just turns it into0xBFBFBF
so forget that. As for0x808080
, it does at least guarantee exactly 50% contrast on all grey backgrounds, but I can’t remember how it looks like on coloured backgrounds, although I do remember it being dim and so I understand it wouldn’t suit everyone.XORing a 50% grey with white, black or any saturated color gives a 50% grey, which may not have enough contrast. And with a non-saturated color (dark, pastel, grayed, etc.) is even worse: it gives the an opposite color, yes, but with a value (luminance) dangerously near to the original (a purple dotted line on a medium green background, for example). It is a bad idea, specially when you take accessibility into account. See my...