If the prototypes of DispatchMessageA and DispatchMessageW are identical, why have both?

Raymond Chen

There are a number of functions, mostly in the window manager, which have both ANSI and Unicode variants, even though the prototypes are identical.

LRESULT WINAPI DispatchMessageW(const MSG*);
LRESULT WINAPI DispatchMessageA(const MSG*);

BOOL WINAPI TranslateMessageW(const MSG*);
BOOL WINAPI TranslateMessageA(const MSG*);

int WINAPI TranslateAcceleratorW(HWND, HACCEL, LPMSG);
int WINAPI TranslateAcceleratorA(HWND, HACCEL, LPMSG);

HACCEL WINAPI CreateAcceleratorTableW(LPACCEL, int);
HACCEL WINAPI CreateAcceleratorTableA(LPACCEL, int);

Why can’t these pairs of functions be combined into a single function? Clearly there’s no CHAR/WCHAR mismatch, seeing as the parameters are identical.

While it’s true that there is no type mismatch, there is still a character set dependency.

For the MSG-based functions, the system needs to know whether the message was obtained via Get­MessageW/Peek­MessageW or via Get­MessageA/Peek­MessageA. If the message is WM_CHAR, then the meaning of the WPARAM changes depending on the character set of the function that obtained the MSG. If you used Get­MessageW/Peek­MessageW, then the WPARAM is a Unicode code unit, but if you used Get­MessageA/Peek­MessageA, then it’s an ANSI code unit.

The case of Create­Accelerator­Table is more subtle. Even though the same ACCEL structure is used for both ANSI and Unicode, the meaning of one of the fields changes:

typedef struct tagACCEL {
  BYTE fVirt;
  WORD key;
  WORD cmd;
} ACCEL, *LPACCEL;

If the FVIRTKEY flag is not set in the fVirt member, then the key member contains a character code, and that’s the place where a character set dependency sneaks in.

0 comments

Comments are closed. Login to edit/delete your existing comments

Feedback usabilla icon