August, 2009

  • The Old New Thing

    City noises and their effects on songbirds

    • 7 Comments

    Robins in Sheffield sing at night because it's too noisy in the daytime. That reminds me that when I was in Antigua, Guatemala, I was told that the songbirds in the city have started mimicking car alarms. Apparently this is also happening in Oregon with birds mimicking car alarms and cell phone ring tones.

  • 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

    Restating the obvious about the WM_NOTIFY message

    • 5 Comments

    It appears that people seemed to appreciate restating the obvious about the WM_COMMAND message, so I'll try it again with the WM_NOTIFY message.

    The WM_NOTIFY message is typically used by a control to communicate with its parent, either to provide information, request it, or both. Although that is the typical use, there are exceptions. For example, property sheets send the WM_NOTIFY to their children. Property sheets are this sort-of backwards model, where the common controls provide the parent window (the property sheet) and applications provide the child windows (the property sheet pages). The window manager doesn't care who sends the message to whom, as long as the sender and recipient are in the same process.

    The message cannot cross a process boundary because WM_NOTIFY is basically a sender-defined version of WM_USER. Anybody can define a new notification code and associate it with any structure they want (as long as the structure begins with a NMHDR). The window manager can't marshal the structure between processes because the structure is defined by the control, not the window manager.

    A little elaboration of that "sender-defined version of WM_USER": As we saw, the meaning of WM_USER messages is determined by the implementor of the window class. In other words, the code receiving the message decides what WM_USER means. That works great if you're some external code that wants to send a message to a known window class. But what if you're external code that wants to send a message to an unknown window class? For example, you're a list view control and you want to tell your parent about some event. You want to send a message to the parent window, but which message? You can't send anything in the WM_USER range because each parent window defines independently what those messages mean, and it's highly unlikely that all the parent windows are going to agree that WM_USER+205 means the same thing. For similar reasons, the WM_APP range is no good. A registered message would work, but if you have hundreds of potential events, then a hundred registered messages is a bit heavy-handed. The old-school answer to this was the WM_COMMAND message, whose notification code is defined by the sending control. Unfortunately, the notification code is all you get; the other parameters are busy doing other things. Enter WM_NOTIFY, which is basically WM_COMMAND on steroids: The NMHDR structure contains everything that was in the WM_COMMAND message, and since it's a structure, you can embed the NMHDR inside a larger structure to provide (and possibly receive) more information.

    Okay, end of strange digression.

    The NMHDR structure itself is a convention, in the same way that the parameters to WM_COMMAND are a convention. The hwndFrom member is supposed to be the control that generated the notification, but there's no enforcement.

    First, there's no way to enforce it. A window doesn't send a message; code sends a message. You can check the thread that is executing the code that is sending a message, but you don't know which window that code is associated with.

    "Well, the window that is sending the message is the one that most recently received a message."

    That doesn't work because you can have code associated with one window call code associated with another window without actually sending a message. In fact, you probably do this all the time:

    class CFrame : public CWindow {
    ...
     LRESULT OnCommand(...);
    ...
     CGraphWindow *m_pwndGraph;
    };
    
    LRESULT CFrame::OnCommand(...)
    {
     switch (idFrom) {
     case IDC_CPU: // user clicked the "CPU" button
      m_pwndGraph->ChangeMode(CPU); // change to a CPU graph
      ...
    }
    

    Suppose that CGraphWindow::ChangeMode function calls SendMessage as part of its processing. Which window "sent" this message? Since you have the power to read code, the message was conceptually sent by CGraphWindow, but the most recently received message is a WM_COMMAND sent to the frame window.

    Your method call is just a transfer of control inside your program. The window manager doesn't know what's going on. All it knows is that it delivered a WM_COMMAND message to the frame window, and then some mystery code executed, and the next thing you know, somebody is sending a message. It doesn't have the source code to your program to know that "Oh, that's coming from CGraphWindow::ChangeMode, and to get the window handle for CGraphWindow, I should call CGraphWindow::operator HWND()." (And even if it did, imagine your surprise when your breakpoint on CGraphWindow::operator HWND() gets hit because SendMessage called it!)

    Second, even if there were some psychic way for the window manager to figure out which window is sending the message, you still wouldn't want that. It is common for WM_NOTIFY handlers of complex controls to forward the message to another window. For example, the list view control in report mode receives WM_NOTIFY messages from the header control and forwards them back out to its own parent, so that the list view parent can respond to header notifications. (The parent normally should just let the list view handle it, but the operation is performed in case you're one of those special cases that needs it.)

    Okay, back to what the fields of NMHDR mean. There are only three fixed fields to NMHDR and they pretty much match up with the parameters to WM_COMMAND:

    • hwndFrom is the handle to the window that is the logical source of the notification.
    • idFrom is the control ID corresponding to the window specified by hwndFrom. In other words, idFrom = GetDlgCtrlID(hwndFrom).
    • code is the notification code. The meaning of this notification code depends on the window class of hwndFrom.

    It is an unwritten convention that the notification codes for the common controls are all negative numbers. This leaves positive numbers for applications to use for their own purposes. Not that applications strictly speaking needed the help, because the meaning of the notification code depends on the window that generated the notification, so if you want a brand new 32-bit message number namespace, just register a new window class, and boom, a whole new range of codes becomes available just to you. (Even though the notification code values do not need to be unique across window classes, the common controls team tries to keep the system-defined notification codes from overlapping, just to make debugging easier.)

    The idFrom member is provided as a convenience to the window receiving the message so that it can use a simple switch statement to figure out who is sending the notification.

    Once you figure out which notification you're receiving, you can use the documentation for that notification to see which structure is associated with the notification. This answers Norman Diamond's complaint that he couldn't figure out what to cast it to. For example, if the notification is LVN_ITEMCHANGING, well, let's see, the documentation for LVN_ITEMCHANGING says,

    LVN_ITEMCHANGING
    pnmv = (LPNMLISTVIEW) lParam;

    pnmv: Pointer to an NMLISTVIEW structure that identifies the item and specifies which of its attributes are changing.

    In other words, your code goes something like this:

    case LVN_ITEMCHANGING:
     pnmv = (LPNMLISTVIEW) lParam;
     ... do stuff with pnmv ...
    

    I'm not sure how much more explicit the documentation could be made to be. All it was missing was the word case in front.

  • 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

    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

    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

    The format rectangle is recalculated whenever the window resizes, and that's a good thing

    • 5 Comments

    Reader asmguru62 asks why a custom format rectangle of a multi-line edit control is lost when the edit control is resized. That's right, the format rectangle is recalculated whenever the window resizes, and that's a good thing.

    Imagine if it weren't recalculated. You create a multi-line edit control. Like many programs, you might create it at a temporary size while you try to figure out what its real size should be. You might even resize the control dynamically as the container is resized. (After all, everybody wants resizable dialogs.) What you definitely don't want is the format rectangle of the edit control to be locked to the size the window was originally created at.

    "Well, yeah," asmguru62 says, "sure that may be desirable if the application is using the default margins, but if the margins have been customized, then shouldn't those margins be preserved?"

    First, who says that your call to EM_SETRECT was to established fixed-size margins? All the function knows is that you said "Put the text inside this rectangle." It has no idea how you computed that rectangle. Did you subtract a fixed number of pixels? Did you use a percentage? Did you set the rectangle to force the text into a rectangle whose width and height form the golden mean?

    Second, if you want to set the margins, then set the margins. The EM_SETMARGINS message lets you specify the size of the left and right margins of a multi-line edit control. The edit control will take your margins into account when it recalculates its format rectangle after a resize.

    In other words, EM_SETRECT is the low-level function that lets you manipulate the edit control's internal formatting rectangle, the same rectangle that the edit control itself manipulates in response to the things that edit controls naturally respond to. There is no fancy inference engine here that says, "Let me attempt to reverse-engineer how this rectangle is related to the client rectangle so I can carry forward this computation when I recalculate the format rectangle." Think of it as reaching in and directly whacking one of the edit control's private member variables.

    If you want something higher-level, then use EM_SETMARGINS.

  • The Old New Thing

    It's not just on the Internet that nobody knows you don't have a real office

    • 13 Comments

    Sure, your company don't have an office, but that's okay. You can rent a fake one, with a fake receptionist, fake staff, and fake conference rooms, and whenever somebody stops by asking for you, the receptionist is trained to say that you're "out".

  • The Old New Thing

    Why can't I declare a type that derives from a generic type parameter?

    • 18 Comments

    A lot of questions about C# generics come from the starting point that they are just a cutesy C# name for C++ templates. But while the two may look similar in the source code, they are actually quite different.

    C++ templates are macros on steroids. No code gets generated when a template is "compiled"; the compiler merely hangs onto the source code, and when you finally instantiate it, the actual type is inserted and code generation takes place.

    // C++ template
    template<class T>
    class Abel
    {
    public:
     int DoBloober(T t, int i) { return t.Bloober(i); }
    };
    

    This is a perfectly legal (if strange) C++ template class. But when the compiler encounters this template, there are a whole bunch of things left unknown. What is the return type of T::Bloober? Can it be converted to an int? Is T::Bloober a static method? An instance method? A virtual instance method? A method on a virtual base class? What is the calling convention? Does T::Bloober take an int argument? Or maybe it's a double? Even stranger, it might accept a Canoe which gets converted from an int by a converting constructor. Or maybe it's a function that takes two parameters, but the second parameter has a default value.

    Nobody knows the answers to these questions, not even the compiler. It's only when you decide to instantiate the template

    Abel<Baker> abel;
    

    that these burning questions can be answered, overloaded operators can be resolved, conversion operators can be hunted down, parameters can get pushed on the stack in the correct order, and the correct type of call instruction can be generated.

    In fact, the compiler doesn't even care whether or not Baker has a Bloober method, as long as you never call Abel<Baker>::DoBloober!

    void f()
    {
     Abel<int> a; // no error!
    }
    
    void g()
    {
     Abel<int> a;
     a.DoBloober(0, 1); // error here
    }
    
    Only if you actually call the method does the compiler start looking for how it can generate code for the DoBloober method.

    C# generics aren't like that.

    Unlike C++, where a non-instantiated template exists only in the imaginary world of potential code that could exist but doesn't, a C# generic results in code being generated, but with placeholders where the type parameter should be inserted.

    This is why you can use generics implemented in another assembly, even without the source code to that generic. This is why a generic can be recompiled without having to recompile all the assemblies that use that generic. The code for the generic is generated when the generic is compiled. By comparison no code is generated for C++ templates until the template is instantiated.

    What this means for C# generics is that if you want to do something with your type parameter, it has to be something that the compiler can figure out how to do without knowing what T is. Let's look at the example that generated today's question.

    class Foo<T>
    {
     class Bar : T
     { ... }
    }
    

    This is flagged as an error by the compiler:

    error CS0689: Cannot derive from 'T' because it is a type parameter
    

    Deriving from a generic type parameter is explicitly forbidden by 25.1.1 of the C# language specification. Consider:

    class Foo<T>
    {
     class Bar : T
     {
       public void FlubberMe()
       {
         Flubber(0);
       }
     }
    }
    

    The compiler doesn't have enough information to generate the IL for the FlubberMe method. One possibility is

    ldarg.0        // "this"
    ldc.i4.0    // integer 0 - is this right?
    call T.Flubber // is this the right type of call?
    

    The line ldc.i4.0 is a guess. If the method T.Flubber were actually void Flubber(long l), then the line would have to be ldc.i4.0; conv.i8 to load an 8-byte integer onto the stack instead of a 4-byte integer. Or perhaps it's void Flubber(object o), in which case the zero needs to be boxed.

    And what about that call instruction? Should it be a call or callvirt?

    And what if the method returned a value, say, string Flubber(int i)? Now the compiler also has to generate code to discard the return value from the top of the stack.

    Since the source code for a generic is not included in the assembly, all these questions have to be answered at the time the generic is compiled. Besides, you can write a generic in Managed C++ and use it from VB.NET. Even saving the source code won't be much help if the generic was implemented in a language you don't have the compiler for!

  • The Old New Thing

    Landing the Space Shuttle is hard enough as it is

    • 17 Comments

    I was at The Museum of Flight and was waiting my turn at the Space Shuttle landing simulator. A six-year-old settled into the control seat, and as the simulation began I heard him ask his father, "Where are the bad guys?"

    I'm pretty sure the Space Shuttle doesn't come with onboard missiles.

    That didn't stop the kid from pressing the trigger on the joystick a lot, though.

    By the way, I cratered the Space Shuttle.

Page 2 of 4 (35 items) 1234