Holy cow, I wrote a book!
If instead of calling ExitProcess you merely
return from the main thread of a process, does the process terminate?
No, but maybe yes.
This is another one of the places where
the C runtime behaves differently from raw Win32.
Under raw Win32, a process exits when any thread chooses to
exit the process explicitly
(usually by calling ExitProcess)
or when all threads have exited.
Exiting the main thread will not result in the process exiting
if there are any other threads still active.
the old-fashioned model of how processes exit,
a process was in control of all its threads and could mediate the
shutdown of those threads, thereby controlling the shutdown of the process.
(Of course, nowadays, with the thread pool, COM worker threads,
and other threads doing random background work,
the idea of
being in control of all the threads in the process is now just
a reminder of those simpler days.)
On the other hand, the C runtime library automatically calls
ExitProcess when you exit the main thread,
regardless of whether there are any worker threads still active.
This behavior for console programs
is mandated by the C language, which says that
"a return from the initial call to the main
function is equivalent to calling the exit
function with the value returned by the main
function as its argument."
The C++ language has an equivalent requirement (3.6.1).
Presumably, the C runtime folks carried this behavior to
WinMain for consistency.
This also means that if you decide to exit your main thread
by calling ExitThread directly, then you aren't
returning from the main function.
Instead, you've leapt into the Win32 world where the process
will not exit until all threads are gone.
A customer had the following question:
I'm using the ShellExecute function to launch a new
process and am passing the handle to my application's main window
as the hwnd parameter.
From the new process, I want to get information from the
old process, and to do that, I need the window handle.
How can I recover that window handle from the new process?
That window handle is used by the ShellExecute
function only to host any user interface operations that occur
as a result of the attempt to execute the program.
For example, it is the owner window used for any error dialogs.
The ShellExecute function does not pass the window
handle to the launched process.
(It couldn't even if it wanted to:
There is nowhere to pass it.
There is no window handle among the parameters to
CreateProcess nor is there a window handle
If you want to pass this information to the process being launched,
you'll have to come up with your own mechanism for transferring
For example, you can pass it
on the command line,
or if you have a lot of information to pass,
use a shared memory block.
My young nieces live in a Chinese-speaking household,
which is great for them because it means that when they grow up,
they will be fluent in two languages.
But it makes things a bit tricky at the beginning.
The niece who is the subject of this story
had just turned two at the time this story takes place,
so her language skills even in Chinese are pretty rudimentary.
Her language skills in English are restricted to a collection of set
I want ice cream!,
any catch phrase from the character
Dora the Explorer.
(I'm also fairly sure she doesn't know what What'you doing?
She'll come into a room and say,
and then appear completely uninterested in the answer.
I think she believes it to be a form of greeting and not an actual question.)
She also loves to answer the phone,
and this usually isn't a problem since most callers are relatives
who can speak Chinese.
But occasionally, it'll be somebody who speaks only English.
(In general, these are just telemarketers, since most
members of the household use their mobile phones as their main number.)
Sometimes she'll run to the phone, pick it up,
say "喂" (Hello), listen for a few seconds,
and then just hang up.
— Who was that on the phone? we'll ask.
"人" is her one-word reply.
It's hard to explain why this is a funny answer.
人 means man, person,
so her response was a casual "A person."
The offhand way she says it expresses her attitude that
"The purpose of the telephone is to amuse me,
but this was just some guy who provided no entertainment at all."
The 人 phase lasted for only a month or so.
In the next phase, she
still picked up the phone and hung up when there was somebody
speaking English on the other end,
but when we asked her who it was, she gave a more detailed reply:
which translates roughly as
"It's some guy speaking A-B-C."
("A-B-C" being her word for the English language.)
A customer noticed that when you right-click on
Computer in the second column of the Start menu
on Windows Vista, the first two options are
Open and Explore.
On the other hand, in Windows 7,
the Explore option is gone, leaving just Open.
The customer also noticed that
in Windows Vista, the two commands had the same effect
and wondered if Explore was removed because it was redundant.
The response from the product team was a very simple "Yes."
It's interesting when a customer notices
a relatively insignificant UI change,
figures out the likely reason for the change,
and then asks for confirmation.
It's not like the reason for the change affects anything.
My guess is that the customer already paid for a support contract
so they're just going to use it, even when the issue wouldn't
normally be worth raising a support incident over.
Today marks the 15th anniversary of the public release of
During the development of Windows 95, one of the team members
attended a Mac conference.
And not as a secret agent, either.
He proudly wore a Windows 95 team
as he strolled among the booths.
The rest of us back at the mother ship wished him well and
started discussing how we could get access to his dental records
so we could identify his remains
when they were sent back to us from the conference.
When he returned,
kill a calf in his honor,
but we did marvel at his survival skills and asked him how it went.
— I got a lot of funny looks.
And one guy, upon confirming that I really did work on the
Windows 95 project, said to me,
"I have to commend you guys on Windows 95 so far.
It sucks less."
That backwards compliment tickled the team's funny bone, and it
quickly became the unofficial team motto:
Windows 95: It sucks less.
Commenter Erbi has a program which creates a splash screen on a background
thread while the main thread initializes.
"I create and then destroy this splash screen window
just before creating and displaying the main window."
The problem is that the main window fails to obtain foreground activation.
Commenting out the code that creates the splash screen fixes the problem,
but then there isn't a splash screen any more (obviously).
"Is there an explanation for this behavior?"
This behavior is explained by two earlier blog posts, plus a PDC talk.
The first blog post came out years before this question was asked:
The correct order for disabling and enabling windows.
Destroying a window is a rather extreme case of disabling it,
but the effect is the same.
When you destroy the splash screen, foreground activation needs to move
to some other window, and since your main window isn't around to inherit
it, foreground activation leaves your program.
When the main window appears, it's too late.
followed shortly thereafter by
a blog post version of the same talk.
As marketing folks like to remind you,
"You get only one chance to make a first impression."
Similarly, you get only one chance to use your foreground activation
permission, and you decided to blow it on a splash screen.
That's fine as far as it goes, but if you want to transfer that
permission to another window, you have to manage it yourself.
The recommended way is to establish an owner/owned relationship
between them; that's the case that the "disabling and enabling windows"
article focuses on.
Miss Universe 2010 National Costumes, Part 1
Miss Universe 2010 National Costumes, Part 2
Commentary in parts NSFW but they so deserve it.
By definition, the primary monitor is the monitor that has (0,0) as
its upper left corner.
Why can't the primary monitor be positioned somewhere else?
Well, sure you could do that, but then you'd have to invent a new name
for the monitor whose upper left corner is at (0,0),
and then you're back where you started.
In other words, it's just a name.
You could ask,
"Why can't starboard be on the left-hand side of the boat?"
Well, sure you could do that, but then you'd have to come up with
a new name for the right-hand side of the boat,
and then things are pretty much the same as they were,
just with different names.
Perhaps a more descriptive (but clumsier) name for the primary monitor
would be the backward-compatibility monitor (for applications which
do not support multiple monitors),
because that's what the primary monitor is.
If an application is not multiple-monitor aware,
then any time it asks for properties of "the" monitor,
it gets information about the backward-compatibility monitor.
A call to GetSystemMetrics(SM_CXSCREEN) gives the width
of the backward-compatibility monitor,
GetSystemMetrics(SM_CYMAXIMIZED) gives the height of
a window maximized on the backward-compatibility monitor,
positioning a window at (0,0) puts it at the upper left corner of the
The window manager still respects window coordinates passed to
functions like CreateWindow or SetWindowPos.
If you pass coordinates that are on a secondary
monitor—oops—a monitor different from the backward-compatibility
then the window manager will happily put the window there.
These coordinates might be the result of a program that is
or possibly merely from a program which is multiple-monitor agnostic.
Multiple-monitor agnosticism is a term I just made up which refers
to programs which might not explicitly support multiple monitors,
but at least were open to the possibility of multiple monitors
by not making assumptions about the number of monitors but
instead using functions like RectVisible to determine
what the visible portions of the screen are.
These techniques were hot topics
many years ago
when you wanted to
write a program that ran both on single-monitor-only versions of Windows
as well as multiple-monitor versions of windows;
nowadays there are rather old-fashioned,
like coming up with mnemonics for all your friends' telephone numbers
so you didn't have to keep looking them up.
(Today, you just go ahead and call the multiple monitor functions
and use the address book function in your mobile phone to remember
your friends' phone numbers.)
It is not the case that the primary monitor is
the applications show up here first monitor.
As noted earlier, applications show up on whatever monitor they ask for,
whether they asked for it explicitly (hunting around for a monitor and
using it) or implicitly (restoring to the same coordinates they were on
when they were last run).
programs which pass CW_USEDEFAULT to the
CreateWindow function explicitly abdicated the choice of
the window position and therefore the monitor.
In that case, the window manager tries to guess an appropriate monitor.
If the new window has a parent or owner, then it is placed on the
same monitor as that parent or owner;
otherwise, the window manager
just puts the window on
the backward-compatible monitor, for lack of a better idea.
The other day, I was in the office kitchenette,
and two of my colleagues both named Paul happened to be there
"Oh no, is this legal?
I think it's a violation of the
Paul Exclusion Principle."
It was a horrible physics pun,
perhaps one of the worst I've made in a long time.
My challenge to you is to come up with an even worse one that you've told.
Note: You have to have actually made the pun to an appropriate audience.
No fair just making one up for the purpose of the challenge.
In Windows 7, the folder tree in the Explorer navigation pane
by default no longer highlights the item in the view pane.
This change was based on user testing and feedback,
but if, like me, you prefer things the old way,
you can play with two new check boxes on the Folder Options dialog.
You can get to Folder Options in a variety of ways:
However you wind up there, the item you want to turn on is
Automatically expand to current folder
(or Expand to current folder if you use the super élite method).