Holy cow, I wrote a book!
Regional windows are neat, but they come at a cost.
Most of the cost you can see directly.
For example, constantly changing the region clearly generates
a cost since you have to sit there and generate new regions all
One question that came up on an internal performance alias
highlights one of the hidden costs of regional windows:
The putative window rectangle.
Suppose you have a large window but set a small window region.
How much worse is this than haveing a small window with a small
Quite a bit, actually.
Hit-testing is one of the most common operations performed by
a window manager. Given a point on the screen, find the window
that it corresponds to. To speed this up, the window rectangle
is used to rule out windows quickly. For example, if a window's
rectangle is (0,0)-(100,100) then the point (200,10) is clearly
not within the window since it doesn't fit in the rectangle.
Rectangle tests are fast.
If the window is regional, then the rectangle test is not good
enough, because the point may exist within the rectangle but outside
the region. In that case, the point must be tested against the
window region itself.
But Windows uses the window rectangle as a "quick test" to see
if the region is worth checking. If the point lies outside the
rectangle, then the window manager doesn't even bother checking
the region, which is good because region testing is comparatively slow.
In other word, the pseudocode for hit-testing goes something like
if (point is outside window rectangle)
else if (window has no region)
else if (point is inside region)
So if you create a huge window with a tiny region, the window
manager can't rule out the hit-test based on the first (fast)
rectangle test. It has to go to the third (slower) region test.
Moral of the story: When using regional windows,
try to keep the window rectangle reasonably close to the bounding
box of the region itself.
It helps the window manager decide more quickly
which window a point belongs to.
Just a little tip: If you're going to be adding a lot of items
to a listbox or combobox, there are a few little things you can do
to improve the performance significantly.
(Note: The improvements work only if you have a lot
of items, like hundreds. Of course, the usability of a listbox
with a hundred items is questionable, but I'm assuming you have
a really good reason for doing this.)
First, you can disable redraw while you add the items.
(This tip works for all controls, actually.)
... add the items ...
InvalidateRect(hwnd, NULL, TRUE);
SetWindowRedraw is defined in the
<windowsx.h> header file.
This suppresses the control redrawing itself each time you add
an item. But there is still something else you can do:
SendMessage(hwndCombo, CB_INITSTORAGE, cItems, cbStrings);
... add the items ...
(For listbox controls, use the
cItems is the number of items you intend to add,
cbStrings is the total amount of memory (in bytes)
required by the strings you intend to add.
It's okay if these values are merely estimates.
If you are too low, then there will still be some reallocation
for the extra items. If you are too high, then some memory will
be allocated but remain unused.
Some people will recommend using LockWindowUpdate, but this is
LockWindowUpdate disables drawing in the window you specify,
but suppressing flickering during updates is not what it was designed for.
One clear limitation limitation of LockWindowUpdate is that only one
window can be locked for update at a time.
So if two windows each try the LockWindowUpdate trick at the same
time, only one of them will succeed. That's not particularly reliable,
now, is it.
The purpose of
LockWindowUpdate is to assist code that is drawing drag/drop feedback.
If you are drawing the cursor for a drag/drop operation, you don't
want the window beneath the cursor to start drawing (and thereby
overwrite your beautiful cursor). So you lock the window while you draw
the cursor and unlock it when the cursor leaves the window.
That's why there is only one locked window at a time:
There can be only one drag/drop operation active at a time,
since there is only one mouse.
A little-known department in the city of Baltimore is
the Rumor Control Center, whose purpose is to squash
rumors before they get out of hand.
Scott Simon talked with supervisor Tom Saunders on
cash rewards for blue-eyed cicadas and other rumors he's
had to handle in the past.
A reader asked,
I was wondering why it's common for some Microsoft products
to have a directory called "1033"
within it's program directory installation location?
What does it mean?
This reader was probably from the United States,
because 1033 is the locale identifier for "English (United States)",
whose hexadecimal value is 0x0409. You may also find directories
called "0409". Some programs use hex codes and some use decimal.
a list of a whole bunch of locales and their identification
numbers, both in decimal and hexadecimal.
Now you too can become an expert in locale identifiers.
The value of a locale identifier is given by the formula
For example, Swiss German is LANG_GERMAN + 1024 * SUBLANG_GERMAN_SWISS
= 7 + 1024 * 2 = 2055.
So why would a program create a directory named after a language code?
Many Microsoft products support a multilingual user interface.
This means that the same program can be used to display
its user interface in multiple languages.
Windows are the two biggest examples.
Language-specific resources need to be broken out into
their own directories so they won't conflict with resources corresponding
to some other language.
(For fun, I installed the Swedish language pack on my computer at work,
so all strings - including the error messages - are in Swedish.)
A simple experiment, and you can eat the results!
The Annals of Improbable Research.
Kenny Mayne is one of the regular anchors for
and for some reason I find this particular home run call hilarious:
I am king of the diamond!
Let there be a grand clubhouse feast! [WAV]
Bring me the finest meats and cheeses throughout the land!
— From The
SportsCenter Altar multimedia download center.
a whimisical interview where he explains where he got that from
Another one I like for its understatedness:
<Football player> has decided to tackle people on behalf of
the <NFL team>.
Terms of the contract are not disclosed,
but we believe it has something to do with money.
Actually, I enjoyed just reading through
a collection of phrases used by the SportsCenter anchors.
Almost makes me want to watch television.
Everybody who has messed with window messaging knows
that GetMessage and PeekMessage retrieve queued messages,
which are dispatched to windows via DispatchMessage.
Most people also know that GetMessage and PeekMessage
will also dispatch nonqueued messages.
(All pending nonqueued messages are dispatched, then
the first queued message is returned.)
But apparently not many people realize that
SendMessage will also dispatch messages!
If one thread T1 send a message to a window that belongs to another
thread T2, the sending thread T1 is put to sleep until the
receiving thread replies to the message.
But if somebody else sends a message to thread T1, thread T1
is woken to process the message,
then is returned to sleep.
Why is that?
Well, when two threads T1 and T2 are working together,
it's common that thread T1 may send a message to thread T2,
and while handling the message, thread T2 will send messages
back to thread T1 before it returns to T1.
Therefore, thread T1 must be ready to accept incoming sent messages.
For example, thread T1 may send a message saying, "Tell me
about all the X's that you know."
Thread T2 will then send one message back to thread T1
saying, "Here's an X", and then another message to say
"Here's another X", and so on, until it has finished
telling thread T1 about all the X's, at which point it
Thread T1 now knows, when the original message returns,
that it has received the entire list of X's
from thread 2.
This back-and-forth is
how DDE service discovery works.
Another case is that thread T1 sends a message to thread T2,
and thread T2 needs to ask thread T1 for help before it can
finish the operation. This isn't as strange as it sounds.
You do something similar all the time without realizing
it when you respond to a WM_NOTIFY message by sending messages
back to the control that sent the notification.
(For example, you may respond to a LVN_ITEMACTIVATE by sending
back a LVM_GETITEM to get information about the item that was activated.)
Any time you send a message, there is a potential for re-entrancy.
Earlier, I discussed the interactions of the various FILE_SHARE_* flags,
then Larry Osterman took this as
inspiration to give
history of the file sharing flags.
If a file is opened with delete-sharing enabled and you delete the file,
the file doesn't actually go away until the open handles are closed.
In the meantime, the file hangs around as a zombie.
(Under Unix, a deleted file with open handles is removed from the
directory and merely floats around in the happy sea of inodes
with no name.)
Why doesn't the file go away?
Well, one reason is that
device drivers can ask for the name of the file that corresponds
to an open handle.
If the directory entry were removed, then there would be no name
(What would you expect to be returned from GetModuleFileName if
the module no longer exists? Should it be possible for
GetModuleFileName to return ERROR_FILE_NOT_FOUND?)
Another reason is that if power were to be lost while a
"forgotten but not lost" handle was still open,
you would now have
lost clusters on the disk.
And a final reason is that a "pending delete" file isn't
actually gone for good. A driver can
"undelete" the file by clearing the delete-on-close flag!
Two legs good - four wheels bad.
to George Orwell.)
Researchers link increase car use with obesity.
Each hour spent in a car was associated with a 6 percent
increase in the likelihood of obesity and
each half-mile walked per day reduced those odds by nearly 5 percent,
the researchers found.
A study last year came to a similar conclusion.
Good to know that quality research yields quality results.
During the run-up to
Windows XP Service Pack 2 Beta in December of last year,
there was a list of five bugs that the release management
team decided were so critical that they were going to slip
the beta until those bugs got fixed.
The third bug on the list:
Deer Hunter 4 won't run.
Deer Hunter has the power to stop a beta.