Convert Windows Message IDs to Text

In visual studio, you can add uMsg,wm in command window or immediate window to get the string representation of the message ID given by uMsg.

source : http://www.codeguru.com/cpp/v-s/debug/article.php/c1267/Convert-message-ID-to-a-string.htm (comments section)

PS: This is same link as mentioned in jack's answer. A user had commented there on the link. This technique has helped me very much in debugging Windows messages (no modification and recompilation of code is required), and therefore merits a separate answer.


Hereafter is code to convert WM_ and other Win32 message codes to text. Includes options to ignore certain messages (eg. WM_MOUSEMOVE) and to dump a list of messages received at the end. (NB: This list only goes up to 1024 (WM_USER) due to the 30K limit on this box. Also there are many duplicates in the list thereafter.)

// Usage -----
#include "win_msg.h"

void ShowMessageText(UINT msg)
{
  wchar_t str[1024];
  wchar_t* win_msgtext = (wchar_t*)GetMessageText(msg);
  if (win_msgtext)
  {
    //printf(L"WndProc: msg = %x (%s)\n", msg, win_msgtext);
    wsprintf(str, L"WndProc: msg = %x (%s)\n", msg, win_msgtext);
    OutputDebugString(str);
  }
}

To list messages used (and generate an 'ignore' list) call:
  ShowUsedMessages();

  
// win_msg.h file ----------
#define SHOW_USED_MESSAGES 1

wchar_t* GetMessageText(unsigned int msg);

#ifdef SHOW_USED_MESSAGES
void ShowUsedMessages(void);
#endif

// win_msg.cpp -----------
#include "stdafx.h"
#include "win_msg.h"

// List here messages to ignore (-1 signifies end of list)
// if -999 occurs at the start of the list, ALL messages except these are ignored (ie. inverts)
//int msgs_to_ignore[] = { -1 };
int msgs_to_ignore[] = {//-999,
  0x20, 0x84, 0xA0, 0x113, 0x200
};
// 0x0020 - WM_SETCURSOR (45)
// 0x0084 - WM_NCHITTEST (26)
// 0x0113 - WM_TIMER (46)
// 0x0135 - WM_CTLCOLORBTN (8)
// 0x0200 - WM_MOUSEFIRST (26)

typedef struct {
  unsigned int code;
  wchar_t* text;
} XMSGITEM;

// These from https://wiki.winehq.org/List_Of_Windows_Messages
XMSGITEM xmsglist[] =
{
  { 0, L"WM_NULL"},
  { 1, L"WM_CREATE" },
  { 2, L"WM_DESTROY" },
  { 3, L"WM_MOVE" },
  { 5, L"WM_SIZE" },
  { 6, L"WM_ACTIVATE" },
  { 7, L"WM_SETFOCUS" },
  { 8, L"WM_KILLFOCUS" },
  { 10, L"WM_ENABLE" },
  { 11, L"WM_SETREDRAW" },
  { 12, L"WM_SETTEXT" },
  { 13, L"WM_GETTEXT" },
  { 14, L"WM_GETTEXTLENGTH" },
  { 15, L"WM_PAINT" },
  { 16, L"WM_CLOSE" },
  { 17, L"WM_QUERYENDSESSION" },
  { 18, L"WM_QUIT" },
  { 19, L"WM_QUERYOPEN" },
  { 20, L"WM_ERASEBKGND" },
  { 21, L"WM_SYSCOLORCHANGE" },
  { 22, L"WM_ENDSESSION" },
  { 24, L"WM_SHOWWINDOW" },
  { 25, L"WM_CTLCOLOR" },
  { 26, L"WM_WININICHANGE" },
  { 27, L"WM_DEVMODECHANGE" },
  { 28, L"WM_ACTIVATEAPP" },
  { 29, L"WM_FONTCHANGE" },
  { 30, L"WM_TIMECHANGE" },
  { 31, L"WM_CANCELMODE" },
  { 32, L"WM_SETCURSOR" },
  { 33, L"WM_MOUSEACTIVATE" },
  { 34, L"WM_CHILDACTIVATE" },
  { 35, L"WM_QUEUESYNC" },
  { 36, L"WM_GETMINMAXINFO" },
  { 38, L"WM_PAINTICON" },
  { 39, L"WM_ICONERASEBKGND" },
  { 40, L"WM_NEXTDLGCTL" },
  { 42, L"WM_SPOOLERSTATUS" },
  { 43, L"WM_DRAWITEM" },
  { 44, L"WM_MEASUREITEM" },
  { 45, L"WM_DELETEITEM" },
  { 46, L"WM_VKEYTOITEM" },
  { 47, L"WM_CHARTOITEM" },
  { 48, L"WM_SETFONT" },
  { 49, L"WM_GETFONT" },
  { 50, L"WM_SETHOTKEY" },
  { 51, L"WM_GETHOTKEY" },
  { 55, L"WM_QUERYDRAGICON" },
  { 57, L"WM_COMPAREITEM" },
  { 61, L"WM_GETOBJECT" },
  { 65, L"WM_COMPACTING" },
  { 68, L"WM_COMMNOTIFY" },
  { 70, L"WM_WINDOWPOSCHANGING" },
  { 71, L"WM_WINDOWPOSCHANGED" },
  { 72, L"WM_POWER" },
  { 73, L"WM_COPYGLOBALDATA" },
  { 74, L"WM_COPYDATA" },
  { 75, L"WM_CANCELJOURNAL" },
  { 78, L"WM_NOTIFY" },
  { 80, L"WM_INPUTLANGCHANGEREQUEST" },
  { 81, L"WM_INPUTLANGCHANGE" },
  { 82, L"WM_TCARD" },
  { 83, L"WM_HELP" },
  { 84, L"WM_USERCHANGED" },
  { 85, L"WM_NOTIFYFORMAT" },
  { 123, L"WM_CONTEXTMENU" },
  { 124, L"WM_STYLECHANGING" },
  { 125, L"WM_STYLECHANGED" },
  { 126, L"WM_DISPLAYCHANGE" },
  { 127, L"WM_GETICON" },
  { 128, L"WM_SETICON" },
  { 129, L"WM_NCCREATE" },
  { 130, L"WM_NCDESTROY" },
  { 131, L"WM_NCCALCSIZE" },
  { 132, L"WM_NCHITTEST" },
  { 133, L"WM_NCPAINT" },
  { 134, L"WM_NCACTIVATE" },
  { 135, L"WM_GETDLGCODE" },
  { 136, L"WM_SYNCPAINT" },
  { 160, L"WM_NCMOUSEMOVE" },
  { 161, L"WM_NCLBUTTONDOWN" },
  { 162, L"WM_NCLBUTTONUP" },
  { 163, L"WM_NCLBUTTONDBLCLK" },
  { 164, L"WM_NCRBUTTONDOWN" },
  { 165, L"WM_NCRBUTTONUP" },
  { 166, L"WM_NCRBUTTONDBLCLK" },
  { 167, L"WM_NCMBUTTONDOWN" },
  { 168, L"WM_NCMBUTTONUP" },
  { 169, L"WM_NCMBUTTONDBLCLK" },
  { 171, L"WM_NCXBUTTONDOWN" },
  { 172, L"WM_NCXBUTTONUP" },
  { 173, L"WM_NCXBUTTONDBLCLK" },
  { 176, L"EM_GETSEL" },
  { 177, L"EM_SETSEL" },
  { 178, L"EM_GETRECT" },
  { 179, L"EM_SETRECT" },
  { 180, L"EM_SETRECTNP" },
  { 181, L"EM_SCROLL" },
  { 182, L"EM_LINESCROLL" },
  { 183, L"EM_SCROLLCARET" },
  { 185, L"EM_GETMODIFY" },
  { 187, L"EM_SETMODIFY" },
  { 188, L"EM_GETLINECOUNT" },
  { 189, L"EM_LINEINDEX" },
  { 190, L"EM_SETHANDLE" },
  { 191, L"EM_GETHANDLE" },
  { 192, L"EM_GETTHUMB" },
  { 193, L"EM_LINELENGTH" },
  { 194, L"EM_REPLACESEL" },
  { 195, L"EM_SETFONT" },
  { 196, L"EM_GETLINE" },
  { 197, L"EM_LIMITTEXT" },
  { 197, L"EM_SETLIMITTEXT" },
  { 198, L"EM_CANUNDO" },
  { 199, L"EM_UNDO" },
  { 200, L"EM_FMTLINES" },
  { 201, L"EM_LINEFROMCHAR" },
  { 202, L"EM_SETWORDBREAK" },
  { 203, L"EM_SETTABSTOPS" },
  { 204, L"EM_SETPASSWORDCHAR" },
  { 205, L"EM_EMPTYUNDOBUFFER" },
  { 206, L"EM_GETFIRSTVISIBLELINE" },
  { 207, L"EM_SETREADONLY" },
  { 209, L"EM_SETWORDBREAKPROC" },
  { 209, L"EM_GETWORDBREAKPROC" },
  { 210, L"EM_GETPASSWORDCHAR" },
  { 211, L"EM_SETMARGINS" },
  { 212, L"EM_GETMARGINS" },
  { 213, L"EM_GETLIMITTEXT" },
  { 214, L"EM_POSFROMCHAR" },
  { 215, L"EM_CHARFROMPOS" },
  { 216, L"EM_SETIMESTATUS" },
  { 217, L"EM_GETIMESTATUS" },
  { 224, L"SBM_SETPOS" },
  { 225, L"SBM_GETPOS" },
  { 226, L"SBM_SETRANGE" },
  { 227, L"SBM_GETRANGE" },
  { 228, L"SBM_ENABLE_ARROWS" },
  { 230, L"SBM_SETRANGEREDRAW" },
  { 233, L"SBM_SETSCROLLINFO" },
  { 234, L"SBM_GETSCROLLINFO" },
  { 235, L"SBM_GETSCROLLBARINFO" },
  { 240, L"BM_GETCHECK" },
  { 241, L"BM_SETCHECK" },
  { 242, L"BM_GETSTATE" },
  { 243, L"BM_SETSTATE" },
  { 244, L"BM_SETSTYLE" },
  { 245, L"BM_CLICK" },
  { 246, L"BM_GETIMAGE" },
  { 247, L"BM_SETIMAGE" },
  { 248, L"BM_SETDONTCLICK" },
  { 255, L"WM_INPUT" },
  { 256, L"WM_KEYDOWN" },
  { 256, L"WM_KEYFIRST" },
  { 257, L"WM_KEYUP" },
  { 258, L"WM_CHAR" },
  { 259, L"WM_DEADCHAR" },
  { 260, L"WM_SYSKEYDOWN" },
  { 261, L"WM_SYSKEYUP" },
  { 262, L"WM_SYSCHAR" },
  { 263, L"WM_SYSDEADCHAR" },
  { 264, L"WM_KEYLAST" },
  { 265, L"WM_UNICHAR" },
  { 265, L"WM_WNT_CONVERTREQUESTEX" },
  { 266, L"WM_CONVERTREQUEST" },
  { 267, L"WM_CONVERTRESULT" },
  { 268, L"WM_INTERIM" },
  { 269, L"WM_IME_STARTCOMPOSITION" },
  { 270, L"WM_IME_ENDCOMPOSITION" },
  { 271, L"WM_IME_COMPOSITION" },
  { 271, L"WM_IME_KEYLAST" },
  { 272, L"WM_INITDIALOG" },
  { 273, L"WM_COMMAND" },
  { 274, L"WM_SYSCOMMAND" },
  { 275, L"WM_TIMER" },
  { 276, L"WM_HSCROLL" },
  { 277, L"WM_VSCROLL" },
  { 278, L"WM_INITMENU" },
  { 279, L"WM_INITMENUPOPUP" },
  { 280, L"WM_SYSTIMER" },
  { 287, L"WM_MENUSELECT" },
  { 288, L"WM_MENUCHAR" },
  { 289, L"WM_ENTERIDLE" },
  { 290, L"WM_MENURBUTTONUP" },
  { 291, L"WM_MENUDRAG" },
  { 292, L"WM_MENUGETOBJECT" },
  { 293, L"WM_UNINITMENUPOPUP" },
  { 294, L"WM_MENUCOMMAND" },
  { 295, L"WM_CHANGEUISTATE" },
  { 296, L"WM_UPDATEUISTATE" },
  { 297, L"WM_QUERYUISTATE" },
  { 306, L"WM_CTLCOLORMSGBOX" },
  { 307, L"WM_CTLCOLOREDIT" },
  { 308, L"WM_CTLCOLORLISTBOX" },
  { 309, L"WM_CTLCOLORBTN" },
  { 310, L"WM_CTLCOLORDLG" },
  { 311, L"WM_CTLCOLORSCROLLBAR" },
  { 312, L"WM_CTLCOLORSTATIC" },
  { 512, L"WM_MOUSEFIRST" },
  { 512, L"WM_MOUSEMOVE" },
  { 513, L"WM_LBUTTONDOWN" },
  { 514, L"WM_LBUTTONUP" },
  { 515, L"WM_LBUTTONDBLCLK" },
  { 516, L"WM_RBUTTONDOWN" },
  { 517, L"WM_RBUTTONUP" },
  { 518, L"WM_RBUTTONDBLCLK" },
  { 519, L"WM_MBUTTONDOWN" },
  { 520, L"WM_MBUTTONUP" },
  { 521, L"WM_MBUTTONDBLCLK" },
  { 521, L"WM_MOUSELAST" },
  { 522, L"WM_MOUSEWHEEL" },
  { 523, L"WM_XBUTTONDOWN" },
  { 524, L"WM_XBUTTONUP" },
  { 525, L"WM_XBUTTONDBLCLK" },
  { 528, L"WM_PARENTNOTIFY" },
  { 529, L"WM_ENTERMENULOOP" },
  { 530, L"WM_EXITMENULOOP" },
  { 531, L"WM_NEXTMENU" },
  { 532, L"WM_SIZING" },
  { 533, L"WM_CAPTURECHANGED" },
  { 534, L"WM_MOVING" },
  { 536, L"WM_POWERBROADCAST" },
  { 537, L"WM_DEVICECHANGE" },
  { 544, L"WM_MDICREATE" },
  { 545, L"WM_MDIDESTROY" },
  { 546, L"WM_MDIACTIVATE" },
  { 547, L"WM_MDIRESTORE" },
  { 548, L"WM_MDINEXT" },
  { 549, L"WM_MDIMAXIMIZE" },
  { 550, L"WM_MDITILE" },
  { 551, L"WM_MDICASCADE" },
  { 552, L"WM_MDIICONARRANGE" },
  { 553, L"WM_MDIGETACTIVE" },
  { 560, L"WM_MDISETMENU" },
  { 561, L"WM_ENTERSIZEMOVE" },
  { 562, L"WM_EXITSIZEMOVE" },
  { 563, L"WM_DROPFILES" },
  { 564, L"WM_MDIREFRESHMENU" },
  { 640, L"WM_IME_REPORT" },
  { 641, L"WM_IME_SETCONTEXT" },
  { 642, L"WM_IME_NOTIFY" },
  { 643, L"WM_IME_CONTROL" },
  { 644, L"WM_IME_COMPOSITIONFULL" },
  { 645, L"WM_IME_SELECT" },
  { 646, L"WM_IME_CHAR" },
  { 648, L"WM_IME_REQUEST" },
  { 656, L"WM_IMEKEYDOWN" },
  { 656, L"WM_IME_KEYDOWN" },
  { 657, L"WM_IMEKEYUP" },
  { 657, L"WM_IME_KEYUP" },
  { 672, L"WM_NCMOUSEHOVER" },
  { 673, L"WM_MOUSEHOVER" },
  { 674, L"WM_NCMOUSELEAVE" },
  { 675, L"WM_MOUSELEAVE" },
  { 768, L"WM_CUT" },
  { 769, L"WM_COPY" },
  { 770, L"WM_PASTE" },
  { 771, L"WM_CLEAR" },
  { 772, L"WM_UNDO" },
  { 773, L"WM_RENDERFORMAT" },
  { 774, L"WM_RENDERALLFORMATS" },
  { 775, L"WM_DESTROYCLIPBOARD" },
  { 776, L"WM_DRAWCLIPBOARD" },
  { 777, L"WM_PAINTCLIPBOARD" },
  { 778, L"WM_VSCROLLCLIPBOARD" },
  { 779, L"WM_SIZECLIPBOARD" },
  { 780, L"WM_ASKCBFORMATNAME" },
  { 781, L"WM_CHANGECBCHAIN" },
  { 782, L"WM_HSCROLLCLIPBOARD" },
  { 783, L"WM_QUERYNEWPALETTE" },
  { 784, L"WM_PALETTEISCHANGING" },
  { 785, L"WM_PALETTECHANGED" },
  { 786, L"WM_HOTKEY" },
  { 791, L"WM_PRINT" },
  { 792, L"WM_PRINTCLIENT" },
  { 793, L"WM_APPCOMMAND" },
  { 856, L"WM_HANDHELDFIRST" },
  { 863, L"WM_HANDHELDLAST" },
  { 864, L"WM_AFXFIRST" },
  { 895, L"WM_AFXLAST" },
  { 896, L"WM_PENWINFIRST" },
  { 897, L"WM_RCRESULT" },
  { 898, L"WM_HOOKRCRESULT" },
  { 899, L"WM_GLOBALRCCHANGE" },
  { 899, L"WM_PENMISCINFO" },
  { 900, L"WM_SKB" },
  { 901, L"WM_HEDITCTL" },
  { 901, L"WM_PENCTL" },
  { 902, L"WM_PENMISC" },
  { 903, L"WM_CTLINIT" },
  { 904, L"WM_PENEVENT" },
  { 911, L"WM_PENWINLAST" },
  { 1024, L"WM_USER" }
};

// 1003 messages
#define NUM_XMSGS (sizeof(xmsglist) / sizeof(XMSGITEM))
bool ignore_msg[NUM_XMSGS];
static int xmsgs_initialized = 0;

#ifdef SHOW_USED_MESSAGES
int used_freq[NUM_XMSGS];
#endif

//-------------------------------------------------
// returns -1 if not found
int msgid_to_index(unsigned int msg)
{
  static unsigned int first, cur, last; //138nS
  //register unsigned int first,cur,last;   //173nS

  // Use bchop to find message code
  first = 0;
  last = NUM_XMSGS;

  while (1)
  {
    cur = (first + last) / 2;

    if (msg < xmsglist[cur].code)
    {
      if (cur == last)
        return (-1);          // not found
      else
        last = cur;
    }
    else
    {
      if (msg == xmsglist[cur].code)  //found
      {
        return (cur);
      }

      if (cur == first)
        return (-1);          // not found
      else
        first = cur;
    }
  }
}

//-------------------------------------------------
#define MAX_XMIGNORES (sizeof(msgs_to_ignore) / sizeof(int))

void initialise_xmsgs(void)
{
  int msg,index;
  bool invert = 0;

  if (msgs_to_ignore[0] == -999) invert = 1;

  for (int i = 0; i < NUM_XMSGS; i++)
  {
    ignore_msg[i] = invert; 
#ifdef SHOW_USED_MESSAGES
    used_freq[i] = 0;
#endif
  }

  for (int i = 0; i < MAX_XMIGNORES; i++)
  {
    msg = msgs_to_ignore[i];
    if (msg == -1) break;

    index = msgid_to_index(msg);
    if (index != -1)
    {
      if (index < NUM_XMSGS)
      {
        ignore_msg[index] = invert ^ 1;
      }
      else
      {
        index = NUM_XMSGS;
      }
    }
  }
  xmsgs_initialized = 1;
}

//-------------------------------------------------
wchar_t* GetMessageText(unsigned int msg)
{
  int index;

  // Setup ignore list on first call
  if (!xmsgs_initialized)
  {
    initialise_xmsgs();
  }

  index = msgid_to_index(msg);
  if (index == -1) return (NULL);//not found - bad msg id

#ifdef SHOW_USED_MESSAGES
  used_freq[index]++;
#endif

  if (ignore_msg[index])
  {
    return (NULL);
  }
  return (xmsglist[index].text);
}

//-------------------------------------------------
#ifdef SHOW_USED_MESSAGES
void ShowUsedMessages(void)
{
  wchar_t str[1024];
  wchar_t* p = str;
  int count = 0;
  int lastmsg;

  // Find last message - to exclude ',' at end
  for (int i = 0; i < NUM_XMSGS; i++)
  {
    if (used_freq[i]) lastmsg = i;
  }
  
  // Pass 1 - output table for inclusion
  OutputDebugString(L"\nint msgs_to_ignore[] = {\n");

  for (int i = 0; i < NUM_XMSGS; i++)
  {
    if (used_freq[i])
    {
      p += wsprintf(p, L"0x%X", xmsglist[i].code);
      count++;

      if (i == lastmsg)
        count = 8;
      else
        *p++ = ',';

      if (count >= 8)
      {
        *p++ = '\n';
        *p++ = '\0';
        OutputDebugString(str);
        p = str;
        count = 0;
      }
    }
  }
  OutputDebugString(L"};\n");

  // Pass 2 - add message text and frequencies
  for (int i = 0; i < NUM_XMSGS; i++)
  {
    if (used_freq[i])
    {
      wsprintf(str, L"// 0x%04X - %s (%d)\n", xmsglist[i].code, xmsglist[i].text, used_freq[i]);
      OutputDebugString(str);
    }
  }
}
#endif

Spy++ has a huge message ID lookup table inside its source.