August, 2009

  • The Old New Thing

    Programming means that sometimes you have to snap two blocks together

    • 53 Comments

    Part of the challenge of programming (and for some people, the reason why programming is fun in the first place) is looking at the building blocks provided to you and deciding how to assemble them to build something new. After all, if everything you wanted a program to do already existed ready-made, it wouldn't be called programming any more. It would be called shopping.

    Is there an API or a quick way to find out which window the mouse is in?

    I replied, "The LEGO Group does not make a piece for every possible object. Sometimes you just have to take two LEGO blocks and click them together. Here are some interesting blocks: GetCursorPos, WindowFromPoint."

    Thanks for your reply. But WindowFromPoint gives me the window of the object at the location of the cursor. But I'm looking for the top level window containing the cursor.

    Fine, then use a different block.

    I wonder how it is these people manage to write programs at all. I get the impression they write code by asking a million tiny questions and cutting and pasting together all the replies.

    No wait, pasting together the replies counts as snapping blocks together. Maybe they just ask for completed programs.

  • The Old New Thing

    The great thing about regular expression engines is that there are so many to choose from

    • 39 Comments

    Back in the days before perl ruled the earth, regular expressions were one of those weird niche features, one of those things that everybody reimplements when they need it. If you look at the old unix tools, you'll see that even then, there were three different regular expression engines with different syntax. You had grep, egrep, and vi. Probably more.

    The grep regular expression language supported character classes, the dot wildcard, the asterisk operator, the start and end anchors, and grouping. No plus operator, no question mark, no alternation, no repetition counts. The egrep program added support for plus, question mark, and alternation. Meanwhile, somebody went back and added repetition counts to grep but didn't add them to vi; somebody else added the \< and \> metacharacters to vi but didn't add them to sed. POSIX added repetition counts to awk but changed the notation from \{n,m\} to {n,m}. And so on.

    No two programs use the same regular expression language, but they overlap sufficiently that you can often get by with the common subset and not have to worry about which particular flavor you're up against.

    Until you wander into the places where they differ.

    From: John Jones
    Subject: Problem with regular expression

    I'm trying to write a regular expression to match blah blah blah.

    From: Jane Smith
    Subject: RE: Problem with regular expression

    I think this will match what you want: ^Z@1&*B*!34

    I just ran my hand randomly over the keyboard to generate that fake regular expression. The scary thing is, at first glance, it is not obviously not a regular expression!

    From: Chris Brown
    Subject: RE: Problem with regular expression

    Try $)(#$C)*#

    From: John Smith
    Subject: RE: Problem with regular expression

    Thanks, everybody, for your suggestions, but I can't get any of them to work. For example, I can't get any of them to match against this string: blah blah blah blah.

    At this point, people chimed in with other suggestions, confirming that John doubled the backslashes, that sort of thing. John posted his test program, and then the reason was obvious.

    From: Jane Smith
    Subject: RE: Problem with regular expression

    Oh, you're using CAtlRegExp. In that class, \w doesn't match a single character; it matches an entire word. You want to use \a instead.

  • The Old New Thing

    How do you drop on the background of an Explorer window when it is in details view?

    • 38 Comments

    When you set your Explorer to Details view, it can become tricky to drop an item onto the window background (in order to move it into the folder) because Details view sets full row select (starting in Windows Vista). This helps users of tablets and touch screens, because it increases the size of the target when dragging and dropping into a folder. On the other hand, when you have more items than fit on the screen, every pixel in the view corresponds to an item; there is no background any more. So how do you drop on the background?

    If you're using Windows 7, you can take advantage of a little gutter space to the left and right of the columns. There is a gutter to the left of the leftmost column and another gutter to the right of the rightmost column. Windows Vista doesn't have these gutters, but you can create a gutter on the right hand side by resizing your columns narrow, and then resizing the window wider than the sum of all the columns. Yes, it's clumsy.

    Less clumsy is dropping onto the Details panel at the bottom of the window, which works both on Windows Vista and Window 7. Dropping onto the Details panel is treated as a drop on the folder background. And the Details panel is a nice big target for your drag/drop operation, so those of you using a tablet or touch screen should have no trouble finding it. (Those gutters are nice for mouse-based users, but if you've got fat fingers, they're not much help on a touch screen.)

    If you've turned off the Details panel, you can also drop onto the title bar. It's not as big as the Details pane, but it's still bigger than the gutters.

    Finally, there's always the copy/paste approach instead of drag/drop. Multi-select the items you want to transfer, right-click them and select Copy (or Cut, as appropriate), then go to the destination folder, and under the Organize menu, select Paste.

    Except for the gutters, all of these techniques also work for Windows Vista.

    Bonus chatter: Commenter Medinoc complains that, with the switch to full row select, it's very hard to click on the background. Actually, it's not that bad. You can right-click on the blank space of any unselected item. For example, find an unselected item with a name that doesn't fill the entire Name column and look at all that white space to the right. You can right-click there and it will be treated as as a right-click on the background. The full row is still treated as part of the item when dropping, for the benefit of people using tablets and touch screens, or people who simply want to hit a target bigger than a 16×16 icon.

  • The Old New Thing

    Why does Windows wait longer than my screen saver idle timeout before starting the screen saver?

    • 32 Comments

    You may find yourself in a situation where Windows takes longer than your specified screen saver idle timeout to start the screen saver.

    First of all, there are ways for programs to block the screen saver entirely. Calling SetThreadExecutionState(ES_DISPLAY_REQUIRED), is how a program says, "Even though there is no mouse or keyboard input, the screen is indeed in use, so don't blank it or start the screen saver." Media playback programs use this so the screen saver doesn't kick in while you're watching a movie on your DVD, and presentation programs use it so the screen saver doesn't start in the middle of your multi-million-dollar proposal.

    But even if no program has marked the screen as busy, Windows itself will delay activating the screen saver if it detects that you would prefer that it not run for a while.

    If you repeatedly dismiss the screen saver less than one minute after it starts on Windows Vista or later, the operating system says, "Oh, sorry. I thought there was nobody there, but obviously there is. You're probably reading an information-dense document or using your laptop as a flashlight or clock, and you want the screen to stay on even though you aren't generating any input. I'll hold off the screen saver for a little while for you."

    After the second time you do a "fast dismiss" of the screen saver, the screen saver idle time is temporarily incremented by its nominal value. For example, if you set your screen saver timeout to two minutes, then starting with the second fast dismiss, Windows will wait an additional two minutes before trying the screen saver again. Here's a timeline for people who like timelines:

    • At T = 0, you stop generating input.
    • At T = 2m, the screen saver starts. You dismiss it immediately.
    • At T = 4m, the screen saver starts. You dismiss it immediately. This is your second consecutive fast dismiss, so the screen saver timeout is temporarily increased to 4 minutes.
    • At T = 8m, the screen saver starts. You dismiss it immediately. This is your third consecutive fast dismiss, so the screen saver timeout is temporarily increased to 6 minutes.
    • At T = 14m, the screen saver starts. You dismiss it immediately. This is your fourth consecutive fast dismiss, so the screen saver timeout is temporarily increased to 8 minutes.

    As long as you keep fast-dismissing, the delay will increase. Of course, the delay won't grow indefinitely, because you'll eventually hit some other idle timeout, like the system sleep timeout, and then the system will sleep before it gets a chance to run the screen saver.

    If this feature offends you, then you can disable it by setting Adaptive Display to off in the Advanced Power Settings. There are also Group Policies for controlling this feature.

  • The Old New Thing

    Microspeak: Action on

    • 30 Comments

    I have been fortunate to have been spared exposure to this particular corner of Microspeak, but others have not been so lucky.

    Have you actioned on this ask?

    It's not clear whether actioning on something means that you've started it or you've finished it. As a result, this is another case of using jargon to impede communication.

    The inventors of this particular form of Microspeak must be proud of themselves, for not only have they verbed a noun, they coupled it with an unnecessary preposition. But they aren't content to stop there. It wasn't long before the noun that got verbed got re-nouned!

    Here is our list of action-ons.

    The obfuscation is now complete. Nobody knows whether this is a list of things they want to do, a list of things for which management has given their approval, a list of things for which work has begun, or a list of things which have been completed! The only thing that is clear from that sentence is that there's a list of some sort.

    And I'm sure they're working on obfuscating that, too.

  • The Old New Thing

    There's no law that says a meeting can't end early

    • 30 Comments

    Meetings run over all the time. In fact, you might say that that's their natural state. Meetings think gases are lazy. Whereas a gas expands to fill its container, a meeting expands to exceed the size of its container.

    It requires good management skills to keep all your meetings on schedule. And it takes great management skills to get them all to finish early.

    Even someone with poor management skills sometimes valt met je gat in de boter and a meeting will finish early by some fluke. And unfortunately, I've been at meetings where the meeting organizer decides that this is not an acceptable state of affairs.

    "Okay, it looks like we still have ten minutes, so Bob, why don't you tell us about Topic X," where Topic X might be "how your part of the project is doing" or "the meeting you had with Team Y." Whatever it is, it's something that wasn't on the meeting agenda. It's just there to fill time.

    Of course, it takes Bob fifteen minutes to talk about Topic X, because a meeting expands to exceed the size of its container. What started out as a meeting that came in early turned into yet another boring meeting that ran over.

    There's no law that says a meeting can't end early. If you're finished early, then finish early.

  • The Old New Thing

    The operating system doesn't know which language programs are written in - by the time the code hits the CPU, they all look the same

    • 27 Comments

    Reader Will Rayer asks about "the degree to which 'plain vanilla' C Windows API code works under Vista with the native look and feel."

    It works just as well as code written in any other language. The operating system doesn't know which language programs are written in. By the time the code reaches the CPU, they all look the same. It's just a bunch of instructions that occasionally call an API function. You can write it in C, C++, assembly, Delphi, Perl, whatever.

    Of course, some languages are better-suited to calling Win32 than others. Win32 is a C-based API, in the sense that the way you call an exported function is expressed in a C header file, and __stdcall calling convention matches up reasonably well with the way C does things (once you convince your compiler to follow that convention). The way types are passed on the stack or in registers, how return values are represented, the fact that pointers are just the address of some blob of data, these all follow the C way of thinking. It stands to reason that the C language (and languages which follow in C's footsteps, like C++) have a pretty easy time of calling Win32 exported functions.

    But that doesn't mean that those are the only languages. After all, at the end of the day, it's all machine code. If you can write assembly language that pushes the parameters in the right format in the right order, then you can use Win32 from assembly language. (There appears to be a whole subculture devoted to this endeavor.)

    Now, it is indeed the case that COM programming is much more convenient in C++ because the COM object layout matches that of many C++ compilers. But that doesn't mean you can't use some other language to do it. As long as that language knows how to indirect through a vtable, you can use COM objects. Indeed, the COM header files go out of their way to make sure even you old-school C programmers can call COM objects. If you define the COBJMACROS symbol, then you get access to macros like this:

    #define IPersistFile_GetClassID(This,pClassID)      \
        (This)->lpVtbl -> GetClassID(This,pClassID)
    

    This snippet from the objidl.h header file is some syntactical sugar to help C programmers use COM. Under pure C, you would retrieve the CLSID from an IPersistFile interface pointer like this:

    CLSID clsid;
    IPersistFile* ppf = ...;
    HRESULT hr = ppf->lpVtbl->GetClassID(ppf, &clsid);
    

    The above macro at least removes the error potential of passing the wrong this pointer:

    CLSID clsid;
    IPersistFile* ppf = ...;
    HRESULT hr = IPersistFile_GetClassID(ppf, &clsid);
    

    If you want to write your programs in C, you still have a lot of company. Huge chunks of Windows are still written in the C language. Not that you can tell, because once the compiler is done doing its thing, the identity of the source language is long gone.

  • The Old New Thing

    Not beany enough

    • 27 Comments

    The other night, I was playing a friendly game of Scrabble®, and I managed to play BEANIER* (meaning "with a stronger flavor of beans") onto a triple-word score, crossing the B with an open Y, scoring over 100 points in the process. This sufficiently demoralized the other players that the game turned into "play anything that vaguely resembles a word, with creative spelling encouraged."

    It turns out that BEANIER* is not listed in the online versions of the SOWPODS or TWL Scrabble word lists, although I made the move in good faith. If the others had thought to challenge, they would've succeeded.

    My brother and I play Scrabble with very different styles. I'm not so much concerned with scoring (although I certainly try to make high-scoring moves) as I am with having a pretty board with a lot of intersections and clever words. I treat Scrabble as a collaborative effort that happens to have a winner at the end, in the same spirit as shows like My Music or Says You. As a result, I don't pay too much attention to whether I'm opening easy access to a triple-word square, and I will forego a higher-scoring play in favor of one that uses a funny word or which connects two parts of the board. If you look at my scoresheet at the end of the game, it consists of a lot of medium-scoring moves (and a few really pathetic ones), with maybe one "super-move" per game where I play a bingo or otherwise manage to rack up a lot of points at one go.

    My brother's approach is much more methodical. He doesn't play a very flashy game; he just focuses on scoring twenty or more points per move. If you look at his scoresheet, it's just a slow, steady climb to the final tally.

    This means that when we play, it's a competition between the tortoise and the hare. (I'm the hare.) Will my "super-move" be enough to hold off the steady erosion of my lead from the constant barrage of strong moves? Usually, the answer is No. Slow and steady wins the race. But I like to think I have more fun.

  • The Old New Thing

    Actually, FlagsAttribute can't do more; that's why it's an attribute

    • 27 Comments

    A few years ago, Abhinaba wondered why FlagsAttribute didn't also alter the way enumeration values are auto-assigned.

    Because attributes don't change the language. They are instructions to the runtime environment or (in rarer cases) to the compiler. An attribute can instruct the runtime environment to treat the function or class in a particular way. For example, you can use an attribute to tell the runtime environment that you want the program entry point to run in a single-threaded apartment, to tell the runtime environment how to look up your p/invoke function, or to tell the compiler to suppress a particular class of warnings.

    But changing how values for enumerations are assigned, well that actually changes the language. An attribute can't change the operator precedence tables. An attribute can't change the way overloaded functions are resolved. An attribute can't change the statement block tokens from curly braces to square braces. An attribute can't change the IL that gets generated. The code still compiles to the same IL; the attribute just controls the execution environment, such as how the JIT compiler chooses to lay out a structure in memory.

    Attribute or not, enumerations follow the same rule for automatic assignment: An enumeration symbol receives the value one greater than the previous enumeration symbol.

  • The Old New Thing

    Why do new controls tend to use COM instead of window messages?

    • 25 Comments

    Commenter David wonders why new controls tend to use COM instead of window messages. "It seems that there must have been a decision to only develop COM controls after the invention of COM."

    There have been plenty of Win32 controls invented after the invention of COM. In fact, the entire common controls library was developed after the invention of COM. All your old friends like the list view, tree view, and property sheets are good old Win32 controls. But it's true that the newer stuff tends to use COM. Why is that?

    I am not aware of any grand pronouncement on this subject. Each team makes a decision that they feel is best for their customers. But if you think about it, it's not an unreasonable choice: Suppose you were writing a new C++ object. Would you prefer to use this:

    class Thing {
    public:
      enum MESSAGENUMBER {
      MESSAGE_INSERTITEM,
      MESSAGE_DELETEITEM,
      MESSAGE_DELETEALLITEMS,
      MESSAGE_SETLABELTEXT,
      MESSAGE_GETNEXTITEM,
      MESSAGE_ADDBITMAP,
      ...
      };
      LRESULT Message(MESSAGENUMBER m, WPARAM wParam, lPARAM lParam);
    private:
      ...
    };
    

    or would you rather use this:

    class Thing {
    public:
      BOOL InsertItem(Item *item, Item *itemParent, Item *itemInsertAfter);
      BOOL DeleteItem(Item *item);
      BOOL DeleteAllItems();
      BOOL SetLabelText(Item *item, PCWSTR pszText);
      Item *GetNextItem(Item *item);
      BOOL AddBitmap(HINSTANCE hinst, PCWSTR pszResource, COLORREF crTransparent);
      ...
    private:
      ...
    };
    

    It's just less of a hassle using separate member functions, where you don't have to try to pack all your parameters into two parameters (cryptically named WPARAM and LPARAM) on the sending side, and then unpack the parameters on the window procedure side.

    The overhead of sending a message can add up for high-traffic messages. A C++ method call is pretty direct: You set up the parameters and call the method. Whereas when you send a window message, it bounces around inside the window manager until it magically pops out the other side.

    Again, these are my personal remarks and are not the official position of Microsoft on anything. But if you were writing a control, which would you prefer to have to implement? And if you were using a control, which interface would you rather use?

    (That said, I can't think of many common controls that are COM-based. All the ones I know about still use boring window messages.)

Page 1 of 4 (35 items) 1234