Holy cow, I wrote a book!
Today, I'm not actually going to say anything new. I'm just going to collate information I've already written under a better title to improve search engine optimization.
A customer reported that they did the following but found that it didn't work:
#define MDM_SETITEMCOUNT WM_USER INT_PTR CALLBACK MyDlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam) { switch (wm) { ... case MDM_SETITEMCOUNT: SetDlgItemInt(hwnd, IDC_ITEMCOUNT, (UINT)wParam, FALSE); return TRUE; ... } return FALSE; }
"I send the MDM_SETITEMCOUNT message to my dialog, but the value doesn't stick. At random times, the value resets back to zero."
MDM_SETITEMCOUNT
As we saw some time ago, window messages in the WM_USER range belong to the window class. In the case of a dialog box, the window class is the dialog class, and the owner of the class is the window manager itself. An application which tries to use the WM_USER message is using window messages it does not own.
WM_USER
It so happens that the dialog manager already defined the WM_USER message:
#define DM_GETDEFID (WM_USER+0)
We saw this problem some time ago when we tried to find a message we could use for custom use in a dialog box.
What the customer is seeing is that whenever the dialog manager sends a DM_GETDEFID message to the dialog box to get the default control ID, the MyDlgProc function mistakenly thinks that it's a MDM_SETITEMCOUNT message and sets the item count to whatever happens to be in the wParam (which happens to be zero). On top of that, it claims to have handled the message, which means that the current value of DWL_MSGRESULT is returned to the sender (probably zero), so the dialog manager thinks that there is no default ID on the dialog.
DM_GETDEFID
MyDlgProc
wParam
DWL_MSGRESULT
The solution, as noted in that same article, is to use WM_APP instead of WM_USER. Because you don't have permission to define messages in the WM_USER range if you aren't the owner of the window class.
WM_APP