December, 2003

  • The Old New Thing

    Which window style bits belong to whom?

    • 6 Comments

    There are 64 bits of styles in the parameters to CreateWindowEx. Which ones belong to whom?

    Windows defines the meanings of the high word of the dwStyle parameter and all of the bits in the dwExStyle parameter. The low 16 bits of the dwStyle parameter are defined by the implementor of the window class (by the person who calls RegisterClass).

    In Windows 95, we found several apps that noticed that some bits in the dwExStyle weren't being used, so they decided to use them for themselves. Then when we added meanings to those bits (such as WS_EX_TOOLWINDOW), these programs started acting funny.

    So don't be like those programs. Don't use bits that don't belong to you.

    If you need more than 16 bits of style information, you can design your class so additional information is passed in the lpParam parameter (the last one) to CreateWindow/Ex, which can be received from the lpCreateParams member of the CREATSTRUCT structure. Alternatively, you can set additional styles with a custom message, such as listview's LVM_SETEXTENDEDLISTVIEWSTYLE message.
  • The Old New Thing

    The New Old New Thing

    • 10 Comments
    This is the (future) new home of The Old New Thing. Just kicking the tires right now.
  • The Old New Thing

    Which message numbers belong to whom?

    • 18 Comments

    Valid window messages break down into four categories.

    0 .. 0x3FF (WM_USER-1): System-defined messages.

    The meanings of these messages are defined by the operating system and cannot be changed. Do not invent new messages here. Since the meanings are defined by Windows, the operating system understands how to parse the WPARAM and LPARAM parameters and can marshal the messages between processes (or knows to refuse to do so).

    0x400 .. 0x7FFF (WM_USER .. WM_APP-1): Class-defined messages.

    The meanings of these messages is determined by the implementor of the window class. (Informally: By the person who calls RegisterClass for that window class.) For example, the WM_USER+1 message means TB_ENABLEBUTTON if the window is a toolbar control, but it means TTM_ACTIVATE if it is a tooltip control, and it means DM_SETDEFID if it is a dialog box. If you created your own control, it would mean something else completely different. Since anybody can create a message in this range, the operating system does not know what the parameters mean and cannot perform automatic marshalling.

    0x8000 .. 0xBFFF (WM_APP ... MAXINTATOM-1): Application-defined messages.

    The meanings of these messages is determined by the application that created the window. (Informally: By the person who calls CreateWindow.) This message region was created in Windows 95 to ensure that applications which subclass a window and generate custom messages will not interfere with new messages created by the window class in future versions. Again, since anybody can create a message in this range, the operating system does not know what the parameters mean and cannot perform automatic marshalling.

    0xC000 .. 0xFFFF (MAXINTATOM .. MAXWORD): Registered messages.

    The meanings of these messages is determined by the caller of RegisterWindowMessage. Note that the numerical value of registered messages can change from run to run, so you must use RegisterWindowMessage to obtain the message number. Once again, since anybody can create a message in this range, the operating system does not know what the parameters mean and cannot perform automatic marshalling.

  • The Old New Thing

    What did the letters "NT" originally stand for?

    • 4 Comments
    Finally, the real story of what the letters "N" and "T" originally stood for is now public, so I can stop being coy about it. (Via LockerGnome.)
  • The Old New Thing

    What are these strange values returned from GWLP_WNDPROC?

    • 10 Comments

    GetWindowLongPtr(hwnd, GWLP_WNDPROC) [or GetWindowLong(hwnd, GWL_WNDPROC) if you haven't yet made your code 64-bit compatible] is supposed to return the current window procedure. Why do I sometimes get wacko values?

    Because sometimes "you can't handle the truth".

    If the current window procedure is incompatible with the caller of GetWindowLongPtr, then the real function pointer cannot be returned since you can't call it. Instead, a "magic cookie" is returned. The sole purpose of this cookie is to be recognized by CallWindowProc so it can translate the message parameters into the format that the window procedure expects.

    For example, suppose that you are running Windows XP and the window is a UNICODE window, but a component compiled as ANSI calls GetWindowLong(hwnd, GWL_WNDPROC). The raw window procedure can't be returned, because the caller is using ANSI window messages, but the window procedure expects UNICODE window messages. So instead, a magic cookie is returned. When you pass this magic cookie to CallWindowProc, it recognizes it as a "Oh, I need to convert the message from ANSI to UNICODE and then give the UNICODE message to that window procedure over there."

    As another example, suppose that you are running Windows 95 and the window was created by a 32-bit component, but a 16-bit component calls GetWindowLong(hwnd, GWLP_WNDPROC). Again, the raw 32-bit window procedure can't be returned since the message needs to be converted from 16-bit to 32-bit. (And besides, a 16-bit program can't jump to a 32-bit flat address.) So instead, again, a magic cookie is returned which CallWindowProc recognizes as a "Oh, I need to convert the message from 16-bit to 32-bit and then give the converted message to that window procedure over there."

    (These conversions are known as "thunks".)

    So remember, the only things you can do with the values you get from GetWindowLongPtr(hwnd, GWLP_WNDPROC) are to (1) pass them to CallWindowProc, or (2) pass them back to SetWindowLongPtr(hwnd, GWLP_WNDPROC).
Page 5 of 5 (45 items) 12345