Window messages can only pass around 2 integers (the
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.
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).