types of variables in windows

Question!

as long as there are different variables types with different sizes why windows maps 2 values in one variable using macros and shift operator eg:

this is a sample of win32 windows procedure:

//...
case WM_COMMAND:
{
    switch(LOWORD(wParam))
    {
        case IDC_LISTBOX:
        {
            switch(HIWORD(wParam))
            {
                //handle message
            }
        }
        break;
    }
}
break;

simply why windows doesn't use two variable of type short instead? or does this has some privileges?

thank you guys



Answers

Your example shows a code snippet that processes messages on the windows message queue.

There are a large number of different object types which can be sent between windows and windows objects, and the message structure has to cope with all these different messaging requirements. For example

  • For a toolbar notification NM_CHAR, windows has to pass the address of some structure with additional information in lParam.
  • For setting a hotkey, with WM_SETHOTKEY, windows need only a key value and the lower part of wParam is sufficient for that
  • For processing a command with WM_COMMAND, windows need more ore less information depending on the command.

In an ideal C++ world, we could have implemented a polymorphic data structure for the messages, with only the relevant fields for the needed data. But the winapi is not C++: it is designed for C and for compatibility with a broad number of languages than can interoperate with C.

In an ideal C world, we could have worked with a union, which would have required to first make a test on the message type (shared between all the union members) before doing further processing. For instance in the WM_COMMAND processing, you'd first check the common message type.

In addition if you work with unions, you'd copy the full union if you have to reissue a message, reusing its parameters. So you might copy things that are not needed. It's a small overhead, but the message loop (and in general OS functions) is something that is executed a huge number of time. So every nanosecond matters. And it's more efficient to work only with the data that is needed, and pack it into words and double words, which 32 and 64 bit processors can handle at their highest speed.



Window messages can only pass around 2 integers (the wParam and lParam parameters).

Integer values by themselves do not require any special marshaling across module/process boundaries, they can be passed around as-is. They are also very small to pas around, store in message queues, etc.

For WM_COMMAND in particular, lParam may contain an HWND value, so the other message values (notification code and identifier) can only be passed in wParam only. They are small enough to be stuffed into wParam directly, thus making it easy to pass around 3 values where only 2 values are allowed.

The alternative requires allocating memory for a struct that contains the separate integers, and then pass a pointer to that struct around in one of the message parameters. And many window messages do exactly that, but usually only when the sender and receiver are in the same process, otherwise it requires marshaling the struct data across module/process boundaries, which is a lot of overhead for simple messaging.

It also puts the burden on the receiver to free the allocated memory, since WM_COMMAND is a posted message that goes through the receiving window's message queue. The sender does not wait for the message to be processed, and thus would not be able to free the struct memory after posting the message. The allocated memory would have to stay alive in memory until the message is finally processed by the receiving window procedure.

Sent messages, on the other hand, go directly to a window procedure and block the sender until processed, so they do not have to worry this, the sender can free the memory after the message is sent. But making all multi-value messages, especially status messages, do this would be a big bottleneck on the system.

In general, it is easier and less overhead to stuff shorter integers into a larger integer whenever possible, especially in posted messages (though sent messages can certainly do it, too).



If I am reading this correctly, Message would contain a List<MessageUser>.

If that's the case then this should get you close:

var List<Message> messages = 
    ( from m 
      in db.Messages 
      where 
          m.UserID == userid || m.MessageUsers.Any(mu => mu.UserID == userID) 
      select m).ToList();
By : Sam Axe


This video can help you solving your question :)
By: admin