I am working on an MFC project, which has the following code:
NMHDR pNMHDR;
pNMHDR.hwndFrom = GetSafeHwnd();
pNMHDR.idFrom = GetDlgCtrlID();
pNMHDR.code = EN_CHANGE;
GetParent()->SendMessage(WM_NOTIFY, (EN_CHANGE << 16) | GetDlgCtrlID(), ( LPARAM ) &pNMHDR);
Please help me in understanding what (EN_CHANGE << 16) | GetDlgCtrlID()
does.
CodePudding user response:
Per the EN_CHANGE
documentation for standard EDIT controls:
wParam
The LOWORD contains the identifier of the edit control. The HIWORD specifies the notification code.
So, the code is taking the constant EN_CHANGE
, shifting its bits to the left 16 places, and then OR'ing the bits of the control ID. Thus, EN_CHANGE
ends up in bits 16-31, and the control ID ends up in bits 0-15:
WPARAM
-----------------------------------------------------------------
| EN_CHANGE | CtrlID |
-----------------------------------------------------------------
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
However, the code should be using the MAKEWPARAM()
macro instead of shifting OR'ing bits manually, eg:
GetParent()->SendMessage(WM_NOTIFY, MAKEWPARAM(GetDlgCtrlID(), EN_CHANGE), (LPARAM) &pNMHDR);
Now, that being said, a standard EDIT control sends EN_CHANGE
via WM_COMMAND
, not WM_NOTIFY
. But a standard windowless RICHEDIT control sends EN_CHANGE
via WM_NOTIFY
, which carries only the control ID by itself in the wParam
parameter. The command ID is carried in the NMHDR
struct pointed at by the lParam
parameter (except, RICHEDIT uses the CHANGENOTIFY
struct, which is unrelated to NMHDR
).
So, this code's use of EN_CHANGE
is clearly non-standard usage, using a customized parameter scheme.