You can't use the WM_USER message in a dialog box

Raymond Chen

Today, I’m not actually going to say anything new.I’m just going to collate information I’ve already writtenunder a better title to improve search engine optimization.

A customer reported that they did the following but foundthat 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_SET­ITEM­COUNT messageto my dialog, but the value doesn’t stick.At random times, the value resets back to zero.”

As we saw some time ago,window messages in the WM_USER range belong to thewindow 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 theWM_USER message is using window messages it does not own.

It so happens that the dialog manager already defined theWM_USER message:

#define DM_GETDEFID         (WM_USER+0)

We saw this problem some time agowhen we tried to find a message we could use for custom usein a dialog box.

What the customer is seeing is that whenever the dialog managersends a DM_GET­DEF­ID message to the dialog boxto get the default control ID,the MyDlgProc function mistakenly thinks that it’saMDM_SET­ITEM­COUNT message andsets the item count to whatever happens to be in thewParam (which happens to be zero).On top of that, it claims to have handled the message,which means that the current value ofDWL_MSG­RESULT is returned to the sender(probably zero),so the dialog manager thinks that there is no default ID on the dialog.

The solution,as noted in that same article, is to use WM_APPinstead of WM_USER.Because you don’t have permission to define messages in theWM_USER range if you aren’t the owner of the window class.