Holy cow, I wrote a book!
James Manning mentioned in a footnote to a blog entry on PowerShell and WMI that he considers the Ctrl+Backspace shortcut key a Windows-ism. Where did this shortcut key come from?
From a fan of the Brief editor.
A few people in the early days of the Internet Explorer group used the Brief editor, which uses Ctrl+Backspace as the shortcut key to delete the previous word, and they liked it so much that one of them added it to the autocomplete handler. Therefore, any edit control that uses SHAutoComplete will gain this secret Ctrl+Backspace hotkey.
SHAutoComplete
This is one of those scary "rogue features". There's no spec, there's no testing, it's just a developer who spent some time whacking a feature into the product because he liked it. Sure, rogue features can often become useful, but they also create a lot of liability. Imagine if a rogue feature was the cause of a program crash, an application compatibility problem, or worse, a security vulnerability.
The word actionable has as its primary meaning "providing grounds for legal action", but in the world of management, it is the secondary meaning "capable of being acted upon" that is more common. Something that is actionable provides a specific demand for action. Although I'm not necessarily a big fan of the word itself, I definitely appreciate the value of the concept it is trying to capture.
The concept is valuable because it emphasizes the importance of clear communication, and making sure people understand what you want. Without it, meetings turn into a passive-aggressive-athon, with people saying, "Oh, sorry, I didn't realize you wanted me to do anything about that. I thought you were just venting."
That's also why I'm not happy with the nounification of the word ask. It's not a requirement; it's not a demand. It's this vague ask thing. How do you prioritize an ask?
Kai Jones describes what you see in the mixing room of a movie studio. It's very simple but very telling. I won't give away the punch line; go read it yourself. (It's the paragraph that begins, "We also went into the sound building.")
(Via Anita Rowland.)
If you merge in the Internal Consistency Evaluators into your MSI package, you may run into error ICE16, complaining that the product name is longer than 63 characters. Why is this so bad?
Well, it isn't really, at least not any more. The original Windows 95 version of the Add/Remove Programs control panel did limit product names to 63 characters. (If you had a longer name, it didn't show up at all because the call to RegQueryValueEx failed with ERROR_MORE_DATA.) This limit was raised to around 259 characters starting with Windows 2000, the version that introduced the fancy list with icons and sizes. However, ICE rule 16 still checks against the old limitation because it doesn't know whether or not your program was designed to run on versions of Windows prior to Windows 2000.
RegQueryValueEx
ERROR_MORE_DATA
If your program doesn't install on those older versions of Windows, then you can disregard the 63-character limit; the new limit is approximately 259 characters.
Commenter Phil Quirk wants to know what the rules are for determining which windows appear in the Alt+Tab list. It's actually pretty simple although hardly anything you'd be able to guess on your own. Note: The details of this algorithm are an implementation detail. It can change at any time, so don't rely on it. In fact, it already changed with Flip and Flip3D; I'm just talking about the Classic Alt+Tab window here.
For each visible window, walk up its owner chain until you find the root owner. Then walk back down the visible last active popup chain until you find a visible window. If you're back to where you're started, then put the window in the Alt+Tab list. In pseudo-code:
BOOL IsAltTabWindow(HWND hwnd) { // Start at the root owner HWND hwndWalk = GetAncestor(hwnd, GA_ROOTOWNER); // See if we are the last active visible popup HWND hwndTry; while ((hwndTry = GetLastActivePopup(hwndWalk)) != hwndTry) { if (IsWindowVisible(hwndTry)) break; hwndWalk = hwndTry; } return hwndWalk == hwnd; }
The purpose of this algorithm is to assign the most meaningful representative winow from each cluster of windows related by ownership. (Notice that the algorithm doesn't care whether the owned window is modal or non-modal.)
At least that's the simple rule if you're not playing crazy window style games. The WS_EX_TOOLWINDOW and WS_EX_APPWINDOW extended styles were created so people can play games and put their window in the Alt+Tab list or take it out even if the simple rule would normally have decided otherwise. This is one of those "Okay, if you think you're smarter than Windows, here's your chance to prove it" options. Personally, I would avoid them since it makes your window behave differently from the rest of the windows in the system.
WS_EX_TOOLWINDOW
WS_EX_APPWINDOW
A window with the WS_EX_TOOLWINDOW extended style is treated as if it weren't visible, even if it is. A window with the WS_EX_APPWINDOW extended style is treated as if it has no owner, even if it does.
Once you start adding these extended styles, you enter the world of "I'm trying to work around the rules" and the result is typically even worse confusion than what you had without them.
I'm not sure what the original commenter is getting at. The window hierarchy described in the suggestion (which doesn't make it so much a suggestion as it is a request for me to debug their problem) says that window C is modal on both windows A and B, which doesn't make sense to me, since a window has only one owner.
The algorithm for choosing the Alt+Tab representative from each cluster of windows may not be the best, but it's what we have. I wouldn't be surprised if the details are tweaked from time to time. No, wait, let me rephrase that. I know that the details are tweaked from time to time. The spirit of the operation is preserved (to show the windows the user can switch to, using the most "natural" candidate for each cluster of windows), but the specific details may be fined-tuned as the concept of "naturalness" is refined.
In the discussion last year regarding retail companies allegedly not collecting personal information as aggressively, a few people mentioned tactics for confusing salesdroids. For a while, I would intentionally confuse salesdroids by using my passport as identification. But far more frustrating is when I manage to confuse salesdroids completely by accident.
A tour of Redmond campus cafeterias back in the old days took much less time than it would require nowadays. Back then, the cafeterias were tiny affairs, the size of maybe three offices not counting the prep area, with a seating capacity of maybe a dozen tables. Each cafeteria had a theme, so going to lunch back in the day was not "Let's go to the nearby mega-cafeteria and decide what we'll have." It was "Let's decide what we'll have, and then go to the mini-cafeteria that is serving it."
Here are the cafeterias on campus back in The Before Time, along with their specialties:
All cafeterias had a salad bar, and the cafeterias in buildings 8 through 10 were extra large: In addition to the featured theme, they also had a grill and made sandwiches to order. (It was like three cafeterias in one!)
I myself have never even seen a Blibbet Burger, much less eaten one. Larry Osterman has some Blibbet memories, and Adam Barr has more cafeteria memories.
My fancy new office phone has an option to change the language of its user interface, so naturally I chose Swedish. Once I did that, I saw some obvious translation errors.
The first example above is just sloppiness, but the second one illustrates how a simple LocalizeString("some text") algorithm doesn't work. As Lance Fisher's teacher put it, "Russian is not a translation of English." You can't just take words and phrases in one language and put them through a simple mapping table and expect the result to be accurate.
Back in the Windows 95 days, the German translation team needed some beta testers, and I volunteered. The most interesting translation bug I reported was one in which an English menu item Sort was translated as Art (which means class, kind) instead of Anordnen (which means to arrange). The one English word has two different meanings, and a blind dictionary translation won't know which one is intended.
Tracey Ullman joins the roster of celebrity knitters with her book Knit 2 Together: Patterns and Stories for Serious Knitting Fun. (She also gets to add to the pile of books whose titles are of the form Catchy title: Long boring subtitle.)
"The most important choice in writing is not what you say. It's what you don't say." Eric Gunnerson gave me that advice when I was writing my book. It's sort of the writing version of "You don't know what you do until you know what you don't do."
That's why I'll write
Of course, you probably wonder this magical pfl comes from. It comes from the Multilanguage Object in mlang. IMLangFontLink2 *pfl; CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_ALL, IID_IMLangFontLink2, (void**)&pfl); ... pfl->Release();
Of course, you probably wonder this magical pfl comes from. It comes from the Multilanguage Object in mlang.
pfl
IMLangFontLink2 *pfl; CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_ALL, IID_IMLangFontLink2, (void**)&pfl); ... pfl->Release();
and not
The pfl variable we've been using is an interface pointer to the IMLangFontLink2 interface. We obtain this pointer by calling the CoCreateInstance function, asking for the object whose class ID is CLSID_CMultiLanguage (defined in the mlang.h header file) and specifying the interface ID (IID) of IID_IMLangFontLink2. The interface ID is a 128-bit value that uniquely identifies an interface; we use it here to specify that we wish to have access to the IMLangFontLink2 interface. Since COM uses explicit reference counting, we must remember to call the IUnknown::Release method when we are finished with the interface pointer. Each call to the IUnknown::Release method decrements the reference count by one, and when the reference count drops to zero, the object is destroyed. IMLangFontLink2 *pfl; CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_ALL, IID_IMLangFontLink2, (void**)&pfl); ... pfl->Release();
The pfl variable we've been using is an interface pointer to the IMLangFontLink2 interface. We obtain this pointer by calling the CoCreateInstance function, asking for the object whose class ID is CLSID_CMultiLanguage (defined in the mlang.h header file) and specifying the interface ID (IID) of IID_IMLangFontLink2. The interface ID is a 128-bit value that uniquely identifies an interface; we use it here to specify that we wish to have access to the IMLangFontLink2 interface. Since COM uses explicit reference counting, we must remember to call the IUnknown::Release method when we are finished with the interface pointer. Each call to the IUnknown::Release method decrements the reference count by one, and when the reference count drops to zero, the object is destroyed.
IMLangFontLink2
CoCreateInstance
CLSID_CMultiLanguage
mlang.h
IID_IMLangFontLink2
IUnknown::Release
This is why I hate reading technical books. People think it's better to write fifty words when ten are enough, that you should explain everything in excruciatingly tedious detail just in case there's a reader out there who sees the word CoCreateInstance and says, "Gosh, I don't know what that is, and I'm going to declare this book useless unless it explains everything from first principles."
What next? "The left open brace begins a block of statements"?