Holy cow, I wrote a book!
GetWindowText() is more complicated than you think. The documentation tries to explain
its complexity with small words, which is great if you don't understand long words,
but it also means that you're not getting the full story.
Here's an attempt to give the full story.
There are two ways window classes can manage their text. They can either do it manually
or they can let the system do it. The default is to let the system do it.
If a window class lets the system manage its text, the system will do the following:
On the other hand, if a window class manages its window text manually, the system
will not do any special handling, and it is the window class's responsibility to respond
to the WM_GETTEXT/WM_SETTEXT messages and return/save the strings explicitly.
Frame windows typically let the system manage their window text. Custom controls typically
manage their window text manually.
GetWindowText has a problem: Window text needs to be readily available without hanging.
FindWindow() needs to get window text in order to find a window. Task-switching applications
need to get window text so they can display the window title in the switcher window.
It should not be possible for a hung application to clog up other applications. This
is particularly true of the task switcher scenario.
This argues against sending WM_GETTEXT messages, because the target
window of the WM_GETTEXT might be hung. Instead, GetWindowText should use the "special
place" since that cannot be affected by hung applications.
On the other hand, GetWindowText is used to retrieve text from controls on a dialog,
and those controls frequently employ custom text management. This argues for sending
WM_GETTEXT messages, because that is the only way to retrieve custom-managed text.
So GetWindowText strikes a compromise.
According to the first rule, if you are trying to get text from a window in your own
process, and the window is hung, then GetWindowText() will also hang. But since the
window belongs to your process, it's your own fault and you deserve to lose. Sending
the WM_GETTEXT message ensures that text from windows that do custom text management
(typically, custom controls) are properly retrieved.
According to the second rule, if you are trying to get text from a window in another
process, then GetWindowText() will not send a message; it will just retrieve the string
from the "special place". Since the most common reason for getting text from a window
in another process is to get the title of the frame, and since frame windows typically
do not do custom window text manipulation, this usually gets the right string.
The documentation simplifies this as "GetWindowText() cannot retrieve text from a
window from another application."
Note, however, that if the target window is hung, your application will also hang
since SendMessage() will not return until the target window responds.
Note also that since WM_GETTEXT is in the system message range (0 to WM_USER-1), you
do not need to do any parameter marshalling (and in fact, you shouldn't). USER will
do the marshalling for you.
lstrcpyn((LPTSTR)lParam, "Booga!", (int)wParam);
case WM_GETTEXTLENGTH: return 7; // lstrlen("Booga!") + null
hwnd = CreateWindow("Sample", "Frappy", ...);
GetWindowText(hwnd, szBuf, 80);
SendMessage(hwnd, WM_GETTEXT, 80, (LPARAM)szBuf);