プログラムを動かして理解するWindowメッセージ

# はじめに

ウィンドウメッセージについて理解するために、実際にプログラムを動かして確認してみました。なお、C言語やC言語を使用したWindowsプログラミングのことは詳しくないため、間違っている点があるかもしれません。  

# メッセージについて

Windowsアプリケーションは[イベントドリブン](#イベント駆動)であり、システムがメッセージを渡すのを待ちます。  

<details><summary>ウィンドウメッセージ一覧</summary>

[システム定義メッセージ](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-messages-and-message-queues#system-defined-messages)の表の一番下の`WM`の箇所  

|値|メッセージ識別子|
|:-----------|:-----------|
|0x0000|[`WM_NULL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NULL)|
|0x0001|[`WM_CREATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CREATE)|
|0x0002|[`WM_DESTROY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DESTROY)|
|0x0003|[`WM_MOVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MOVE)|
|0x0005|[`WM_SIZE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SIZE)|
|0x0006|[`WM_ACTIVATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ACTIVATE)|
|0x0007|[`WM_SETFOCUS`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SETFOCUS)|
|0x0008|[`WM_KILLFOCUS`](https://learn.microsoft.com/ja-jp/search/?terms=WM_KILLFOCUS)|
|0x000A|[`WM_ENABLE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ENABLE)|
|0x000B|[`WM_SETREDRAW`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SETREDRAW)|
|0x000C|[`WM_SETTEXT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SETTEXT)|
|0x000D|[`WM_GETTEXT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETTEXT)|
|0x000E|[`WM_GETTEXTLENGTH`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETTEXTLENGTH)|
|0x000F|[`WM_PAINT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PAINT)|
|0x0010|[`WM_CLOSE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CLOSE)|
|0x0011|[`WM_QUERYENDSESSION`](https://learn.microsoft.com/ja-jp/search/?terms=WM_QUERYENDSESSION)|
|0x0012|[`WM_QUIT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_QUIT)|
|0x0013|[`WM_QUERYOPEN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_QUERYOPEN)|
|0x0014|[`WM_ERASEBKGND`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ERASEBKGND)|
|0x0015|[`WM_SYSCOLORCHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SYSCOLORCHANGE)|
|0x0016|[`WM_ENDSESSION`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ENDSESSION)|
|0x0018|[`WM_SHOWWINDOW`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SHOWWINDOW)|
|0x001A|[`WM_WININICHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_WININICHANGE)|
|0x001B|[`WM_DEVMODECHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DEVMODECHANGE)|
|0x001C|[`WM_ACTIVATEAPP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ACTIVATEAPP)|
|0x001D|[`WM_FONTCHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_FONTCHANGE)|
|0x001E|[`WM_TIMECHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_TIMECHANGE)|
|0x001F|[`WM_CANCELMODE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CANCELMODE)|
|0x0020|[`WM_SETCURSOR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SETCURSOR)|
|0x0021|[`WM_MOUSEACTIVATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MOUSEACTIVATE)|
|0x0022|[`WM_CHILDACTIVATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CHILDACTIVATE)|
|0x0023|[`WM_QUEUESYNC`](https://learn.microsoft.com/ja-jp/search/?terms=WM_QUEUESYNC)|
|0x0024|[`WM_GETMINMAXINFO`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETMINMAXINFO)|
|0x0026|[`WM_PAINTICON`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PAINTICON)|
|0x0027|[`WM_ICONERASEBKGND`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ICONERASEBKGND)|
|0x0028|[`WM_NEXTDLGCTL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NEXTDLGCTL)|
|0x002A|[`WM_SPOOLERSTATUS`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SPOOLERSTATUS)|
|0x002B|[`WM_DRAWITEM`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DRAWITEM)|
|0x002C|[`WM_MEASUREITEM`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MEASUREITEM)|
|0x002D|[`WM_DELETEITEM`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DELETEITEM)|
|0x002E|[`WM_VKEYTOITEM`](https://learn.microsoft.com/ja-jp/search/?terms=WM_VKEYTOITEM)|
|0x002F|[`WM_CHARTOITEM`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CHARTOITEM)|
|0x0030|[`WM_SETFONT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SETFONT)|
|0x0031|[`WM_GETFONT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETFONT)|
|0x0032|[`WM_SETHOTKEY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SETHOTKEY)|
|0x0033|[`WM_GETHOTKEY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETHOTKEY)|
|0x0037|[`WM_QUERYDRAGICON`](https://learn.microsoft.com/ja-jp/search/?terms=WM_QUERYDRAGICON)|
|0x0039|[`WM_COMPAREITEM`](https://learn.microsoft.com/ja-jp/search/?terms=WM_COMPAREITEM)|
|0x003D|[`WM_GETOBJECT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETOBJECT)|
|0x0041|[`WM_COMPACTING`](https://learn.microsoft.com/ja-jp/search/?terms=WM_COMPACTING)|
|0x0044|[`WM_COMMNOTIFY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_COMMNOTIFY)|
|0x0046|[`WM_WINDOWPOSCHANGING`](https://learn.microsoft.com/ja-jp/search/?terms=WM_WINDOWPOSCHANGING)|
|0x0047|[`WM_WINDOWPOSCHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_WINDOWPOSCHANGED)|
|0x0048|[`WM_POWER`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POWER)|
|0x004A|[`WM_COPYDATA`](https://learn.microsoft.com/ja-jp/search/?terms=WM_COPYDATA)|
|0x004B|[`WM_CANCELJOURNAL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CANCELJOURNAL)|
|0x004E|[`WM_NOTIFY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NOTIFY)|
|0x0050|[`WM_INPUTLANGCHANGEREQUEST`](https://learn.microsoft.com/ja-jp/search/?terms=WM_INPUTLANGCHANGEREQUEST)|
|0x0051|[`WM_INPUTLANGCHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_INPUTLANGCHANGE)|
|0x0052|[`WM_TCARD`](https://learn.microsoft.com/ja-jp/search/?terms=WM_TCARD)|
|0x0053|[`WM_HELP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_HELP)|
|0x0054|[`WM_USERCHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_USERCHANGED)|
|0x0055|[`WM_NOTIFYFORMAT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NOTIFYFORMAT)|
|0x007B|[`WM_CONTEXTMENU`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CONTEXTMENU)|
|0x007C|[`WM_STYLECHANGING`](https://learn.microsoft.com/ja-jp/search/?terms=WM_STYLECHANGING)|
|0x007D|[`WM_STYLECHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_STYLECHANGED)|
|0x007E|[`WM_DISPLAYCHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DISPLAYCHANGE)|
|0x007F|[`WM_GETICON`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETICON)|
|0x0080|[`WM_SETICON`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SETICON)|
|0x0081|[`WM_NCCREATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCCREATE)|
|0x0082|[`WM_NCDESTROY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCDESTROY)|
|0x0083|[`WM_NCCALCSIZE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCCALCSIZE)|
|0x0084|[`WM_NCHITTEST`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCHITTEST)|
|0x0085|[`WM_NCPAINT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCPAINT)|
|0x0086|[`WM_NCACTIVATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCACTIVATE)|
|0x0087|[`WM_GETDLGCODE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETDLGCODE)|
|0x0088|[`WM_SYNCPAINT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SYNCPAINT)|
|0x00A0|[`WM_NCMOUSEMOVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCMOUSEMOVE)|
|0x00A1|[`WM_NCLBUTTONDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCLBUTTONDOWN)|
|0x00A2|[`WM_NCLBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCLBUTTONUP)|
|0x00A3|[`WM_NCLBUTTONDBLCLK`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCLBUTTONDBLCLK)|
|0x00A4|[`WM_NCRBUTTONDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCRBUTTONDOWN)|
|0x00A5|[`WM_NCRBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCRBUTTONUP)|
|0x00A6|[`WM_NCRBUTTONDBLCLK`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCRBUTTONDBLCLK)|
|0x00A7|[`WM_NCMBUTTONDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCMBUTTONDOWN)|
|0x00A8|[`WM_NCMBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCMBUTTONUP)|
|0x00A9|[`WM_NCMBUTTONDBLCLK`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCMBUTTONDBLCLK)|
|0x00AB|[`WM_NCXBUTTONDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCXBUTTONDOWN)|
|0x00AC|[`WM_NCXBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCXBUTTONUP)|
|0x00AD|[`WM_NCXBUTTONDBLCLK`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCXBUTTONDBLCLK)|
|0x00FE|[`WM_INPUT_DEVICE_CHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_INPUT_DEVICE_CHANGE)|
|0x00FF|[`WM_INPUT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_INPUT)|
|0x0100|[`WM_KEYDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_KEYDOWN)|
|0x0101|[`WM_KEYUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_KEYUP)|
|0x0102|[`WM_CHAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CHAR)|
|0x0103|[`WM_DEADCHAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DEADCHAR)|
|0x0104|[`WM_SYSKEYDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SYSKEYDOWN)|
|0x0105|[`WM_SYSKEYUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SYSKEYUP)|
|0x0106|[`WM_SYSCHAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SYSCHAR)|
|0x0107|[`WM_SYSDEADCHAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SYSDEADCHAR)|
|0x0108|[`WM_KEYLAST`](https://learn.microsoft.com/ja-jp/search/?terms=WM_KEYLAST)|
|0x0109|[`WM_UNICHAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_UNICHAR)|
|0x010D|[`WM_IME_STARTCOMPOSITION`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_STARTCOMPOSITION)|
|0x010E|[`WM_IME_ENDCOMPOSITION`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_ENDCOMPOSITION)|
|0x010F|[`WM_IME_COMPOSITION`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_COMPOSITION)|
|0x0110|[`WM_INITDIALOG`](https://learn.microsoft.com/ja-jp/search/?terms=WM_INITDIALOG)|
|0x0111|[`WM_COMMAND`](https://learn.microsoft.com/ja-jp/search/?terms=WM_COMMAND)|
|0x0112|[`WM_SYSCOMMAND`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SYSCOMMAND)|
|0x0113|[`WM_TIMER`](https://learn.microsoft.com/ja-jp/search/?terms=WM_TIMER)|
|0x0114|[`WM_HSCROLL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_HSCROLL)|
|0x0115|[`WM_VSCROLL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_VSCROLL)|
|0x0116|[`WM_INITMENU`](https://learn.microsoft.com/ja-jp/search/?terms=WM_INITMENU)|
|0x0117|[`WM_INITMENUPOPUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_INITMENUPOPUP)|
|0x0119|[`WM_GESTURE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GESTURE)|
|0x011A|[`WM_GESTURENOTIFY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GESTURENOTIFY)|
|0x011F|[`WM_MENUSELECT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MENUSELECT)|
|0x0120|[`WM_MENUCHAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MENUCHAR)|
|0x0121|[`WM_ENTERIDLE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ENTERIDLE)|
|0x0122|[`WM_MENURBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MENURBUTTONUP)|
|0x0123|[`WM_MENUDRAG`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MENUDRAG)|
|0x0124|[`WM_MENUGETOBJECT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MENUGETOBJECT)|
|0x0125|[`WM_UNINITMENUPOPUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_UNINITMENUPOPUP)|
|0x0126|[`WM_MENUCOMMAND`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MENUCOMMAND)|
|0x0127|[`WM_CHANGEUISTATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CHANGEUISTATE)|
|0x0128|[`WM_UPDATEUISTATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_UPDATEUISTATE)|
|0x0129|[`WM_QUERYUISTATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_QUERYUISTATE)|
|0x0132|[`WM_CTLCOLORMSGBOX`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CTLCOLORMSGBOX)|
|0x0133|[`WM_CTLCOLOREDIT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CTLCOLOREDIT)|
|0x0134|[`WM_CTLCOLORLISTBOX`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CTLCOLORLISTBOX)|
|0x0135|[`WM_CTLCOLORBTN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CTLCOLORBTN)|
|0x0136|[`WM_CTLCOLORDLG`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CTLCOLORDLG)|
|0x0137|[`WM_CTLCOLORSCROLLBAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CTLCOLORSCROLLBAR)|
|0x0138|[`WM_CTLCOLORSTATIC`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CTLCOLORSTATIC)|
|0x0200|[`WM_MOUSEMOVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MOUSEMOVE)|
|0x0201|[`WM_LBUTTONDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_LBUTTONDOWN)|
|0x0202|[`WM_LBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_LBUTTONUP)|
|0x0203|[`WM_LBUTTONDBLCLK`](https://learn.microsoft.com/ja-jp/search/?terms=WM_LBUTTONDBLCLK)|
|0x0204|[`WM_RBUTTONDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_RBUTTONDOWN)|
|0x0205|[`WM_RBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_RBUTTONUP)|
|0x0206|[`WM_RBUTTONDBLCLK`](https://learn.microsoft.com/ja-jp/search/?terms=WM_RBUTTONDBLCLK)|
|0x0207|[`WM_MBUTTONDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MBUTTONDOWN)|
|0x0208|[`WM_MBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MBUTTONUP)|
|0x0209|[`WM_MBUTTONDBLCLK`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MBUTTONDBLCLK)|
|0x020A|[`WM_MOUSEWHEEL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MOUSEWHEEL)|
|0x020B|[`WM_XBUTTONDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_XBUTTONDOWN)|
|0x020C|[`WM_XBUTTONUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_XBUTTONUP)|
|0x020D|[`WM_XBUTTONDBLCLK`](https://learn.microsoft.com/ja-jp/search/?terms=WM_XBUTTONDBLCLK)|
|0x020E|[`WM_MOUSEHWHEEL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MOUSEHWHEEL)|
|0x0210|[`WM_PARENTNOTIFY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PARENTNOTIFY)|
|0x0211|[`WM_ENTERMENULOOP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ENTERMENULOOP)|
|0x0212|[`WM_EXITMENULOOP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_EXITMENULOOP)|
|0x0213|[`WM_NEXTMENU`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NEXTMENU)|
|0x0214|[`WM_SIZING`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SIZING)|
|0x0215|[`WM_CAPTURECHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CAPTURECHANGED)|
|0x0216|[`WM_MOVING`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MOVING)|
|0x0218|[`WM_POWERBROADCAST`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POWERBROADCAST)|
|0x0219|[`WM_DEVICECHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DEVICECHANGE)|
|0x0220|[`WM_MDICREATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDICREATE)|
|0x0221|[`WM_MDIDESTROY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDIDESTROY)|
|0x0222|[`WM_MDIACTIVATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDIACTIVATE)|
|0x0223|[`WM_MDIRESTORE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDIRESTORE)|
|0x0224|[`WM_MDINEXT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDINEXT)|
|0x0225|[`WM_MDIMAXIMIZE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDIMAXIMIZE)|
|0x0226|[`WM_MDITILE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDITILE)|
|0x0227|[`WM_MDICASCADE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDICASCADE)|
|0x0228|[`WM_MDIICONARRANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDIICONARRANGE)|
|0x0229|[`WM_MDIGETACTIVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDIGETACTIVE)|
|0x0230|[`WM_MDISETMENU`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDISETMENU)|
|0x0231|[`WM_ENTERSIZEMOVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ENTERSIZEMOVE)|
|0x0232|[`WM_EXITSIZEMOVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_EXITSIZEMOVE)|
|0x0233|[`WM_DROPFILES`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DROPFILES)|
|0x0234|[`WM_MDIREFRESHMENU`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MDIREFRESHMENU)|
|0x0238|[`WM_POINTERDEVICECHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERDEVICECHANGE)|
|0x0239|[`WM_POINTERDEVICEINRANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERDEVICEINRANGE)|
|0x023A|[`WM_POINTERDEVICEOUTOFRANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERDEVICEOUTOFRANGE)|
|0x0240|[`WM_TOUCH`](https://learn.microsoft.com/ja-jp/search/?terms=WM_TOUCH)|
|0x0241|[`WM_NCPOINTERUPDATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCPOINTERUPDATE)|
|0x0242|[`WM_NCPOINTERDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCPOINTERDOWN)|
|0x0243|[`WM_NCPOINTERUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCPOINTERUP)|
|0x0245|[`WM_POINTERUPDATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERUPDATE)|
|0x0246|[`WM_POINTERDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERDOWN)|
|0x0247|[`WM_POINTERUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERUP)|
|0x0249|[`WM_POINTERENTER`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERENTER)|
|0x024A|[`WM_POINTERLEAVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERLEAVE)|
|0x024B|[`WM_POINTERACTIVATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERACTIVATE)|
|0x024C|[`WM_POINTERCAPTURECHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERCAPTURECHANGED)|
|0x024D|[`WM_TOUCHHITTESTING`](https://learn.microsoft.com/ja-jp/search/?terms=WM_TOUCHHITTESTING)|
|0x024E|[`WM_POINTERWHEEL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERWHEEL)|
|0x024F|[`WM_POINTERHWHEEL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERHWHEEL)|
|0x0251|[`WM_POINTERROUTEDTO`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERROUTEDTO)|
|0x0252|[`WM_POINTERROUTEDAWAY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERROUTEDAWAY)|
|0x0253|[`WM_POINTERROUTEDRELEASED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_POINTERROUTEDRELEASED)|
|0x0281|[`WM_IME_SETCONTEXT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_SETCONTEXT)|
|0x0282|[`WM_IME_NOTIFY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_NOTIFY)|
|0x0283|[`WM_IME_CONTROL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_CONTROL)|
|0x0284|[`WM_IME_COMPOSITIONFULL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_COMPOSITIONFULL)|
|0x0285|[`WM_IME_SELECT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_SELECT)|
|0x0286|[`WM_IME_CHAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_CHAR)|
|0x0288|[`WM_IME_REQUEST`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_REQUEST)|
|0x0290|[`WM_IME_KEYDOWN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_KEYDOWN)|
|0x0291|[`WM_IME_KEYUP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_IME_KEYUP)|
|0x02A0|[`WM_NCMOUSEHOVER`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCMOUSEHOVER)|
|0x02A1|[`WM_MOUSEHOVER`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MOUSEHOVER)|
|0x02A2|[`WM_NCMOUSELEAVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_NCMOUSELEAVE)|
|0x02A3|[`WM_MOUSELEAVE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_MOUSELEAVE)|
|0x02B1|[`WM_WTSSESSION_CHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_WTSSESSION_CHANGE)|
|0x02E0|[`WM_DPICHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DPICHANGED)|
|0x02E2|[`WM_DPICHANGED_BEFOREPARENT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DPICHANGED_BEFOREPARENT)|
|0x02E3|[`WM_DPICHANGED_AFTERPARENT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DPICHANGED_AFTERPARENT)|
|0x02E4|[`WM_GETDPISCALEDSIZE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETDPISCALEDSIZE)|
|0x0300|[`WM_CUT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CUT)|
|0x0301|[`WM_COPY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_COPY)|
|0x0302|[`WM_PASTE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PASTE)|
|0x0303|[`WM_CLEAR`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CLEAR)|
|0x0304|[`WM_UNDO`](https://learn.microsoft.com/ja-jp/search/?terms=WM_UNDO)|
|0x0305|[`WM_RENDERFORMAT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_RENDERFORMAT)|
|0x0306|[`WM_RENDERALLFORMATS`](https://learn.microsoft.com/ja-jp/search/?terms=WM_RENDERALLFORMATS)|
|0x0307|[`WM_DESTROYCLIPBOARD`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DESTROYCLIPBOARD)|
|0x0308|[`WM_DRAWCLIPBOARD`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DRAWCLIPBOARD)|
|0x0309|[`WM_PAINTCLIPBOARD`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PAINTCLIPBOARD)|
|0x030A|[`WM_VSCROLLCLIPBOARD`](https://learn.microsoft.com/ja-jp/search/?terms=WM_VSCROLLCLIPBOARD)|
|0x030B|[`WM_SIZECLIPBOARD`](https://learn.microsoft.com/ja-jp/search/?terms=WM_SIZECLIPBOARD)|
|0x030C|[`WM_ASKCBFORMATNAME`](https://learn.microsoft.com/ja-jp/search/?terms=WM_ASKCBFORMATNAME)|
|0x030D|[`WM_CHANGECBCHAIN`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CHANGECBCHAIN)|
|0x030E|[`WM_HSCROLLCLIPBOARD`](https://learn.microsoft.com/ja-jp/search/?terms=WM_HSCROLLCLIPBOARD)|
|0x030F|[`WM_QUERYNEWPALETTE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_QUERYNEWPALETTE)|
|0x0310|[`WM_PALETTEISCHANGING`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PALETTEISCHANGING)|
|0x0311|[`WM_PALETTECHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PALETTECHANGED)|
|0x0312|[`WM_HOTKEY`](https://learn.microsoft.com/ja-jp/search/?terms=WM_HOTKEY)|
|0x0317|[`WM_PRINT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PRINT)|
|0x0318|[`WM_PRINTCLIENT`](https://learn.microsoft.com/ja-jp/search/?terms=WM_PRINTCLIENT)|
|0x0319|[`WM_APPCOMMAND`](https://learn.microsoft.com/ja-jp/search/?terms=WM_APPCOMMAND)|
|0x031A|[`WM_THEMECHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_THEMECHANGED)|
|0x031D|[`WM_CLIPBOARDUPDATE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_CLIPBOARDUPDATE)|
|0x031E|[`WM_DWMCOMPOSITIONCHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DWMCOMPOSITIONCHANGED)|
|0x031F|[`WM_DWMNCRENDERINGCHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DWMNCRENDERINGCHANGED)|
|0x0320|[`WM_DWMCOLORIZATIONCOLORCHANGED`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DWMCOLORIZATIONCOLORCHANGED)|
|0x0321|[`WM_DWMWINDOWMAXIMIZEDCHANGE`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DWMWINDOWMAXIMIZEDCHANGE)|
|0x0323|[`WM_DWMSENDICONICTHUMBNAIL`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DWMSENDICONICTHUMBNAIL)|
|0x0326|[`WM_DWMSENDICONICLIVEPREVIEWBITMAP`](https://learn.microsoft.com/ja-jp/search/?terms=WM_DWMSENDICONICLIVEPREVIEWBITMAP)|
|0x033F|[`WM_GETTITLEBARINFOEX`](https://learn.microsoft.com/ja-jp/search/?terms=WM_GETTITLEBARINFOEX)|
|0x0345|[`WM_TOOLTIPDISMISS`](https://learn.microsoft.com/ja-jp/search/?terms=WM_TOOLTIPDISMISS)|

</details>

## メッセージの流れ

Windowsアプリケーションに送られたメッセージは最終的に[ウィンドウプロシージャ](#ウィンドウプロシージャ)に送られて処理されますが、そこに行くまでの経路にはメッセージキューを経由するものとそうでないものの2つがあります。  

* [メッセージのルーティング](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-messages-and-message-queues#message-routing)/ [キーボード入力モデル](https://learn.microsoft.com/ja-jp/windows/win32/inputdev/about-keyboard-input#keyboard-input-model)  
* [メッセージ処理](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-messages-and-message-queues#message-handling) / [メッセージ ループ](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/window-messages#the-message-loop) / [文字メッセージ](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/keyboard-input#character-messages)  
* [ウィンドウを閉じる - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/closing-the-window)  
* [メッセージの投稿と送信](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-messages-and-message-queues#posting-and-sending-messages)  

![flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193449/59d0bd89-c3e7-162a-aee2-ce66fa8f5151.png)  
![table.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193449/ada2085c-3103-c804-3855-3248b4b5fb14.png)  

## メッセージの値

[ウィンドウ メッセージ (Win32 と C++ の概要) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/window-messages)  

> メッセージは、特定のイベントを指定する単なる数値コードです。  

例えば、マウスの左ボタンが押された場合は`0x0201`という値が送られてきます。`winuser.h`にはこの値に対応した記号定数が[#define](https://learn.microsoft.com/ja-jp/cpp/preprocessor/hash-define-directive-c-cpp?view=msvc-170)されています。`0x0201`であれば`WM_LBUTTONDOWN`になります。  

```cpp
...
#define WM_MOUSEMOVE 0x0200
#define WM_LBUTTONDOWN 0x0201
#define WM_LBUTTONUP 0x0202
...
```

### 値の範囲
メッセージには`WM_LBUTTONDOWN`（`0x0201`）のようにシステムで定義されているものだけでなく、アプリケーションが独自に使うためにアプリケーションによって作成されるものもあります。メッセージの値は以下のように用途によって使用できる範囲が定められています。   

[アプリケーション定義のメッセージ](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-messages-and-message-queues#application-defined-messages) / [WM_USER](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/wm-user) / [WM_APP](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/wm-app#remarks)  
[メッセージの共有](https://wisdom.sakura.ne.jp/system/winapi/win32/win155.html) / [RegisterWindowMessage関数](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerwindowmessagew)  

![value.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193449/81c470de-fc3e-f94d-b6c0-d2848aec4431.png)  

# 実際に確認する

開発環境は以下と同じです。  
[MinGW+C言語でWindows用Dllを作成する #Windows - Qiita](https://qiita.com/nekotadon/items/3da07aa1d20017f9bd16)  

* 確認用のプレーンコードは[最小限のwindowsプログラム](#最小限のwindowsプログラム)を参照。  
* ソースコードのファイル名は`winlog.cpp`とし、コンパイルは`g++ winlog.cpp -mwindows -o winlog.exe`  

## 全てのメッセージを確認する

[Windows 10で始めるC言語開発(31) WindowsでC言語開発!　メッセージループを追っていく | TECH+（テックプラス）](https://news.mynavi.jp/techplus/article/c-for-windows-31/2)  

確認用の[プレーンコード](#最小限のwindowsプログラム)に対して、ログをファイルに出力するように変更しています。全コードについては、[全てのメッセージを出力するプログラム](#全てのメッセージを出力するプログラム)を参照願います。  

|ファイル名|出力する内容|
|:-----------|:-----------|
|`AllLog.txt`|ウィンドウプロシージャが受け取ったメッセージ<br>及び、Win32API関数名（関数を呼ぶ前に出力）|
|`MessageLoopLog.txt`|メッセージループで受け取ったメッセージ|

実際にコンパイルして動作させると、例えば以下のように出力されます。  

```
//AllLog.txt
Before RegisterClass
Before CreateWindowEx
[#0000] message: 0x0024
[#0001] message: 0x0081
[#0002] message: 0x0083
[#0003] message: 0x0001
Before ShowWindow
...

//MessageLoopLog.txt
...
[#0059] message: 0x0200
[#0062] message: 0x0200
[#0065] message: 0x0200
...
```

数値では分かりにくいので[メッセージの数値を文字列に変換](#メッセージの数値を文字列に変換)します。  

```
//AllLog_fix.txt
Before RegisterClass
Before CreateWindowEx
[#0000] message: WM_GETMINMAXINFO
[#0001] message: WM_NCCREATE
[#0002] message: WM_NCCALCSIZE
[#0003] message: WM_CREATE
Before ShowWindow
...

//MessageLoopLog_fix.txt
...
[#0059] message: WM_MOUSEMOVE
[#0062] message: WM_MOUSEMOVE
[#0065] message: WM_MOUSEMOVE
...
```

[`CreateWindowExW`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-createwindowexw)を呼び出すと、`WM_CREATE`などのメッセージが送信されていることが分かります。また、[`WM_CREATE`](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/wm-create)に記載の通り、`CreateWindow`関数が戻る前に、`WM_CREATE`が送信されていることも分かります。   

[WinMerge](https://winmerge.org/?lang=ja)等で`AllLog_fix.txt`と`MessageLoopLog_fix.txt`を比較すると、基本的に「ウィンドウプロシージャの受け取ったメッセージ」＝「メッセージループで受け取ったメッセージ」＋αでしたが、そうでないものもありました。また、`0xC***` という[アプリケーション間通信用](#値の範囲)のメッセージもありました。やはり実際に確認してみると理解が深まると思います。  

## GetMessageの挙動を確認する

[ウィンドウ メッセージ (Win32 と C++ の概要) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/window-messages#the-message-loop)  

> キューが空の場合、関数は別のメッセージがキューに登録されるまでブロックします。  

と記載されているので、実際に[`GetMessage`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getmessage)の挙動を確認してみます。確認用の[プレーンコード](#最小限のwindowsプログラム)を変更し、メッセージループに入った回数をアプリケーションウィンドウのタイトルに表示するようにしています。全コードについては、[メッセージループ突入回数を表示するプログラム](#メッセージループ突入回数を表示するプログラム)を参照願います。  

アプリケーションを起動して、マウスカーソルを動かすと回数がアップしていることが分かります。但し、何もしないと回数は変わりません。  

## TranslateMessageの挙動を確認する
 
[キーボード入力 (はじめに Win32 および C++ を使用) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/keyboard-input)  

> キーボード入力について考える場合は、キー ストロークが文字と同じではないことに注意することが重要です。 たとえば、A キーを押すと、次のいずれかの文字が発生する可能性があります。  
> a A á 

> キー ストロークは、... TranslateMessage 関数によって文字に変換されます。 この関数は、キーダウン メッセージを調べて、それらを文字に変換します。  

[`TranslateMessage`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-translatemessage)によって、例えばShiftを押しながらAを押すと文字"A"の`WM_CHAR`メッセージが生成され、Shiftを押さずにAを押すと文字"a"の`WM_CHAR`メッセージが生成されるとのことなので、実際に`TranslateMessage`の挙動と`TranslateMessage`があるときとないときのメッセージを比較してみます。

確認用の[プレーンコード](#最小限のwindowsプログラム)を変更し、  
* キー入力にかかわるメッセージのみを出力するようにしています。
* [`WM_KEYDOWN`](https://learn.microsoft.com/ja-jp/windows/win32/inputdev/wm-keydown)メッセージに付加されて送られてくる[仮想キーコード](https://learn.microsoft.com/ja-jp/windows/win32/inputdev/virtual-key-codes)の情報や、[`WM_CHAR`](https://learn.microsoft.com/ja-jp/windows/win32/inputdev/wm-char)メッセージに付加されて送られてくる文字コードの情報も併せて出力するようにしています。  
* ANSI版も作成できるように文字列の定義を変更しています。詳細は[文字列の操作](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/working-with-strings)を参照。  

全コードについては、[TranslateMessageの挙動を確認するプログラム](#translatemessageの挙動を確認するプログラム)を参照願います。  

実際にコンパイルして動作させ、[メッセージの数値を文字列に変換](#メッセージの数値を文字列に変換)すると、  

```
//a
message: WM_KEYDOWN 0x41 //Aキーダウン
message: WM_CHAR 0x61    //"a"文字メッセージ
message: WM_KEYUP 0x41   //Aキーアップ

//A
message: WM_KEYDOWN 0x10 //Shiftダウン
message: WM_KEYDOWN 0x41 //Aキーダウン
message: WM_CHAR 0x41    //"A"文字メッセージ
message: WM_KEYUP 0x41   //Aキーアップ
message: WM_KEYUP 0x10   //Shiftアップ

//か
message: WM_KEYDOWN 0xE5 //IME PROCESS キー
message: WM_KEYUP 0x4B   //Kキーアップ
message: WM_KEYDOWN 0xE5 //IME PROCESS キー
message: WM_KEYUP 0x41   //Aキーアップ
message: WM_KEYDOWN 0xE5 //IME PROCESS キー
message: WM_CHAR 0x304B  //"か"文字メッセージ
```
文字メッセージが生成されているのが分かります。このプログラムは`UNICODE`を`define`しており、[`RegisterClassW`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerclassw)でウィンドウクラス登録されるためUnicodeで文字を受け取ります。IMEオンで`K` `A`と入力するとUnicodeの「か」である`304B`を受け取っていることが分かります。なお`UNICODE`を`define`せず、  

```cpp
#ifdef UNICODE
#undef UNICODE
#endif
```
とすると文字メッセージはShift-JISの「か」である`82A9`になっていました。  

```
//Shift-JISの「か」
message: WM_CHAR 0x82
message: WM_CHAR 0xA9
```

`TranslateMessage(&msg);`を削除した場合は、  
```
//a
message: WM_KEYDOWN 0x41 //Aキーダウン
message: WM_KEYUP 0x41   //Aキーアップ
```
文字メッセージ`WM_CHAR`が生成されていないことが分かります。

**参考URL**  
* [Unicode文字一覧表 - instant tools](https://tools.m-bsys.com/ex/unicode_table.php)  
* [文字コード表 シフトJIS(Shift_JIS)](http://charset.7jp.net/sjis.html)  

# 用語説明

## イベント駆動

[メッセージとメッセージ キューについて - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-messages-and-message-queues)  
[イベント駆動型プログラミング - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E9%A7%86%E5%8B%95%E5%9E%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)  

例えば、Windowsアプリケーション上でキーが押された場合、システム（Windows）はアプリケーションに対し「キーが押された」というメッセージを渡します。Windowsアプリケーションはこのメッセージを受け取ることでキーが押されたことを認識し、押されたときの処理を行います。  

このように何かの事象、動作が起こったことをトリガーとして処理を実行する場合、「イベントドリブン（イベント駆動）です」と表現します。Windowsアプリケーションはイベントドリブンです。システムがメッセージを渡すのを待ちます。  

## ウィンドウプロシージャ

[ウィンドウ プロシージャについて - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-window-procedures)  

Windowsアプリケーションを作成する場合、「ウィンドウプロシージャ」と呼ばれるアプリケーション※に送られてきたすべてのメッセージを処理する関数を実装します。システム（Windows）はアプリケーションに対するメッセージがある場合、この関数を呼びます。  

Windowsアプリケーションでは、「マウスがクリックされた場合はこのような処理をする」といったコードをこの関数内に記述することでマウスクリックに応答する動作を実現できます。  

上記で「Windowsアプリケーションはメッセージを受け取ることでキーが押されたことを認識し」と記載しましたが、実際にアプリケーション作成時にすることはメッセージに応答する処理を関数内に記載するだけです。関数の呼び出しはシステム（Windows）が行います。  

※より丁寧に言うと[アプリケーションローカルクラス](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-window-classes#application-local-classes)、つまり実行可能ファイルが通常1つ持つ[ウィンドウクラス](#ウィンドウクラス)に紐づく[ウィンドウ](#ウィンドウ)  

## ウィンドウクラス

[ウィンドウ クラスについて - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-window-classes)  
[ウィンドウの作成 - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/creating-a-window#window-classes)  

ウィンドウクラスという名前ですが、C++でいうクラスではありません。ウィンドウクラスという概念は分かりにくいですが、アプリケーション[ウィンドウ](#ウィンドウ)であれ、ボタン[ウィンドウ](#ウィンドウ)であれ[ウィンドウ](#ウィンドウ)を作成するには、何はともあれ先立ってウィンドウクラスが必要です。ウィンドウクラスを登録するには[`RegisterClass`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerclassw)を使用します。  

間違った理解にはなりますが、メッセージに関して理解するだけであれば、

* ウィンドウクラス ：町  
* ウィンドウプロシージャ：町に唯一ある郵便局  
* ウィンドウ：住人  
* メッセージ：郵便物

くらいの捉え方でよいと思います。住人宛ての郵便物を処理するためには受け取って処理する郵便局が必要ですが、そのためには郵便局を持つ町を作って町に住む必要があります。ウィンドウを作成する場合、まずはウィンドウプロシージャを持つウィンドウクラスを登録します。その後、それに紐づかせる形でウィンドウを作成します。ウィンドウクラスの持つウィンドウプロシージャはそのクラスに紐づくウィンドウに対する全てのメッセージを処理します。  

実際は現実のように郵便局（ウィンドウプロシージャ）が受け取った郵便物（メッセージ）がその後住人（ウィンドウ）のもとに行くわけではないですし、ウィンドウクラスを登録するときに使う「ウィンドウクラスの属性を格納する[WNDCLASS構造体](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/ns-winuser-wndclassw)」にはウィンドウプロシージャ以外の様々な設定が必要であるため、「ウィンドウクラスとはそれに紐づくウィンドウが共通で持つ仕様を定義しているもの」というような理解のほうが、より正しい理解になるとは思います。  

**参考URL** 
* [ウインドウクラスの登録 - インコのWindowsSDK](http://gurigumi.s349.xrea.com/programming/visualcpp/intro3.html)  
* [ウィンドウの作成 - Windows API 入門](http://kaitei.net/winapi/creating-windows/#windows-class)  

## ウィンドウ

[ウィンドウとは - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/what-is-a-window-)  

一般的にウィンドウといえば、例えばメモ帳を起動したときなどに表示されるウィンドウのことを想像します。実際にこれはアプリケーションウィンドウと呼ばれるウィンドウですが、Windowsプログラミングの場合はボタンなどのコントロールもウィンドウです。  

## メッセージループ

[ウィンドウ メッセージ (Win32 と C++ の概要) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/window-messages#the-message-loop)  
[Windows Messaging Architecture | Xavier's space](https://xavierantony.wordpress.com/2010/08/24/windows-messaging-architecture/)  

キーボードやマウスなどのユーザー操作によって発生するメッセージはメッセージキューに投稿（POST）されます。このメッセージキューにメッセージがあれば取得し、それを[ウィンドウプロシージャ](#ウィンドウプロシージャ)に送ることを繰り返すのがメッセージループです。具体的には[`GetMessage`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getmessage)でメッセージキューからメッセージを取得し、[`DispatchMessage`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-dispatchmessage)でメッセージを[ウィンドウプロシージャ](#ウィンドウプロシージャ)に送ります。  

例えばC#では[`Application.Run`](https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.application.run?view=windowsdesktop-8.0)メソッドによってメッセージループを開始させます。  

**参考URL** 
* [ウィンドウプロシージャ - Windows API 入門](http://kaitei.net/winapi/window-procedures/#mssage-loop)  
* [Visual Studio 2008のひな型コードを理解する（2/4） - ＠IT](https://atmarkit.itmedia.co.jp/fdotnet/easyvs2008/easyvs200804/easyvs200804_02.html)  

# ソースコード

## 最小限のWindowsプログラム

確認用プログラムのひな型となる最小限のWindowsアプリケーション用コードです。  

[モジュール 1 初めての Windows プログラム - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/your-first-windows-program)  

1. アプリケーション[ウィンドウ](#ウィンドウ)を作成する前に、まずは[`RegisterClass`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerclassw)を使用して[ウィンドウクラス](#ウィンドウクラス)を登録します。
    1. まずは[`RegisterClass`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerclassw)の引数である[WNDCLASSW構造体](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/ns-winuser-wndclassw)を作成します。  
    1. [WNDCLASSEX 構造体の未使用のメンバーは、0 または NULL に初期化する必要がある](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-window-classes#elements-of-a-window-class)ため[初期化子](https://learn.microsoft.com/ja-jp/cpp/cpp/initializers?view=msvc-170)で初期化します。  
    1. [クラス名、ウィンドウプロシージャ、インスタンスのみが必須設定項目](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-window-classes#elements-of-a-window-class)であるためこの3つを設定します。  
    1. 必須項目の設定だけでも問題ありませんが、マウスカーソルは通常の矢印カーソルとしたいため、[カーソル](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-window-classes#class-cursor)については[`LoadCursor`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-loadcursorw)を使用して矢印カーソルに設定します。  
1. [`CreateWindowEx`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-createwindowexw)を使用して[ウィンドウ](#ウィンドウ)を作成します。  
1. [`ShowWindow`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-showwindow)と[`UpdateWindow`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-updatewindow)を使用してウィンドウを表示します。[`ShowWindow`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-showwindow)の引数には[WinMainアプリケーションのエントリポイント](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/winmain--the-application-entry-point)の引数である`nCmdShow`を指定します。  
1. メッセージループを作成します。Windowsアプリケーションも例えばコンソールアプリケーションである、  
    ```cpp
    #include <stdio.h>

    int main(void)
    {
        printf("Hello World");
        return 0;
    }
    ```
    と同じで、最後まで行くとプログラムが終了しますが、メッセージループがあることでこのループを抜けない限りプログラムは終了しません。メッセージループでは、  
    ```cpp
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    ```
    1. [`GetMessage`](#getmessageの挙動を確認する)でメッセージキューからメッセージを取得  
    1. [`TranslateMessage`](#translatemessageの挙動を確認する)で文字メッセージを生成  
    1. [ウィンドウプロシージャ](#ウィンドウプロシージャ)にメッセージを送るように[`DispatchMessage`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-dispatchmessage)でシステムに指示  
    
    を繰り返します。[`GetMessage`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getmessage)の戻り値は、

    * [`WM_QUIT`](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/wm-quit)メッセージ以外を取得した場合は`0`以外  
    * [`WM_QUIT`](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/wm-quit)メッセージを取得した場合は`0`  
    * エラーが発生した場合は`-1`  
    
    のため、[`WM_QUIT`](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/wm-quit)以外のメッセージを受け取っている限り（`>0`の場合）ループを繰り返します。

1. [ウィンドウプロシージャ](#ウィンドウプロシージャ)を記載します。基本的に[`DefWindowProc`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-defwindowprocw)を使用して、[処理しないメッセージには既定の処理を実施します](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/writing-the-window-procedure#default-message-handling)。[ウィンドウが破棄されると、WM_DESTROYメッセージを受け取る](https://learn.microsoft.com/ja-jp/windows/win32/learnwin32/closing-the-window)ので、[`PostQuitMessage`](https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-postquitmessage)を使って[`WM_QUIT`](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/wm-quit)メッセージをメッセージキューに投稿（POST）します。

```cpp
/*
winlog.cpp
g++ winlog.cpp -mwindows -o winlog.exe
*/
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
{
    // 1.ウィンドウクラスの登録
    const wchar_t CLASS_NAME[] = L"ClassName";

    WNDCLASS wc = {};                         // メンバの初期化
    wc.lpszClassName = CLASS_NAME;            // クラス名
    wc.lpfnWndProc = WindowProc;              // ウィンドウ プロシージャ のアドレス
    wc.hInstance = hInstance;                 // インスタンス ハンドル
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); // カーソル

    RegisterClass(&wc);

    // 2.ウィンドウの作成
    HWND hwnd = CreateWindowEx(
        0,                            // 拡張ウィンドウ スタイル
        CLASS_NAME, L"WindowName",    // クラス名、ウィンドウ名
        WS_OVERLAPPEDWINDOW,          // ウィンドウスタイル
        CW_USEDEFAULT, CW_USEDEFAULT, // ウィンドウの表示位置(x,y)
        CW_USEDEFAULT, CW_USEDEFAULT, // ウィンドウの幅と高さ
        NULL,                         // 親ウィンドウのハンドル
        NULL,                         // メニューのハンドル
        hInstance,                    // インスタンスハンドル
        NULL);                        // 追加のデータ

    if (hwnd == NULL)
    {
        return 0;
    }

    // 3.ウィンドウの表示
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 4.メッセージループ
    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

// 5.ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
```

## 全てのメッセージを出力するプログラム

```cpp
/*
winlog.cpp
g++ winlog.cpp -mwindows -o winlog.exe
*/
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void LogMessage(LPCWSTR fPath, UINT uMsg);
void LogString(LPCWSTR fPath, LPCWSTR str);

int counter = 0;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
{
    // 1.ウィンドウクラスの登録
    const wchar_t CLASS_NAME[] = L"ClassName";

    WNDCLASS wc = {};                         // メンバのゼロ初期化
    wc.lpszClassName = CLASS_NAME;            // クラス名
    wc.lpfnWndProc = WindowProc;              // ウィンドウ プロシージャ のアドレス
    wc.hInstance = hInstance;                 // インスタンス ハンドル
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); // カーソル

    LogString(L"AllLog.txt", L"Before RegisterClass\n");
    RegisterClass(&wc);

    // 2.ウィンドウの作成
    LogString(L"AllLog.txt", L"Before CreateWindowEx\n");
    HWND hwnd = CreateWindowEx(
        0,                            // 拡張ウィンドウ スタイル
        CLASS_NAME, L"WindowName",    // クラス名、ウィンドウ名
        WS_OVERLAPPEDWINDOW,          // ウィンドウスタイル
        CW_USEDEFAULT, CW_USEDEFAULT, // ウィンドウの表示位置(x,y)
        CW_USEDEFAULT, CW_USEDEFAULT, // ウィンドウの幅と高さ
        NULL,                         // 親ウィンドウのハンドル
        NULL,                         // メニューのハンドル
        hInstance,                    // インスタンスハンドル
        NULL);                        // 追加のデータ

    if (hwnd == NULL)
    {
        return 0;
    }

    // 3.ウィンドウの表示
    LogString(L"AllLog.txt", L"Before ShowWindow\n");
    ShowWindow(hwnd, nCmdShow);
    LogString(L"AllLog.txt", L"Before UpdateWindow\n");
    UpdateWindow(hwnd);

    // 4.メッセージループ
    LogString(L"AllLog.txt", L"Before Message Loop\n");
    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        LogMessage(L"MessageLoopLog.txt", msg.message);
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

// 5.ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LogMessage(L"AllLog.txt", uMsg);
    counter++;
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

// ファイルにログを出力（メッセージ出力用）
void LogMessage(LPCWSTR fPath, UINT uMsg)
{
    FILE *fp;
    if (_wfopen_s(&fp, fPath, L"a, ccs=UTF-8") == 0)
    {
        fwprintf_s(fp, L"[#%04d] message: 0x%04X\n", counter, uMsg);
        fclose(fp);
    }
}

// ファイルにログを出力（Win32API関数名出力用）
void LogString(LPCWSTR fPath, LPCWSTR str)
{
    FILE *fp;
    if (_wfopen_s(&fp, fPath, L"a, ccs=UTF-8") == 0)
    {
        fwprintf_s(fp, str);
        fclose(fp);
    }
}
```
## メッセージループ突入回数を表示するプログラム

```cpp
/*
winlog.cpp
g++ winlog.cpp -mwindows -o winlog.exe
*/
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
{
    // 1.ウィンドウクラスの登録
    const wchar_t CLASS_NAME[] = L"ClassName";

    WNDCLASS wc = {};                         // メンバの初期化
    wc.lpszClassName = CLASS_NAME;            // クラス名
    wc.lpfnWndProc = WindowProc;              // ウィンドウ プロシージャ のアドレス
    wc.hInstance = hInstance;                 // インスタンス ハンドル
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); // カーソル

    RegisterClass(&wc);

    // 2.ウィンドウの作成
    HWND hwnd = CreateWindowEx(
        0,                            // 拡張ウィンドウ スタイル
        CLASS_NAME, L"WindowName",    // クラス名、ウィンドウ名
        WS_OVERLAPPEDWINDOW,          // ウィンドウスタイル
        CW_USEDEFAULT, CW_USEDEFAULT, // ウィンドウの表示位置(x,y)
        CW_USEDEFAULT, CW_USEDEFAULT, // ウィンドウの幅と高さ
        NULL,                         // 親ウィンドウのハンドル
        NULL,                         // メニューのハンドル
        hInstance,                    // インスタンスハンドル
        NULL);                        // 追加のデータ

    if (hwnd == NULL)
    {
        return 0;
    }

    // 3.ウィンドウの表示
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 4.メッセージループ
    MSG msg = {};
    int counter = 0;
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        // メッセージループ突入回数を表示
        if (counter <= 10000)
        {
            counter++;
        }
        wchar_t str_counter[256];
        swprintf_s(str_counter, L"%d", counter);
        SetWindowTextW(hwnd, str_counter);

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

// 5.ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
```
## TranslateMessageの挙動を確認するプログラム

```cpp
/*
winlog.cpp
g++ winlog.cpp -mwindows -o winlog.exe
*/
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <intsafe.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void LogMessage(LPCWSTR fPath, UINT uMsg, WPARAM wParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
{
    // 1.ウィンドウクラスの登録
    const TCHAR CLASS_NAME[] = TEXT("ClassName");

    WNDCLASS wc = {};                         // メンバの初期化
    wc.lpszClassName = CLASS_NAME;            // クラス名
    wc.lpfnWndProc = WindowProc;              // ウィンドウ プロシージャ のアドレス
    wc.hInstance = hInstance;                 // インスタンス ハンドル
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); // カーソル

    RegisterClass(&wc);

    // 2.ウィンドウの作成
    HWND hwnd = CreateWindowEx(
        0,                              // 拡張ウィンドウ スタイル
        CLASS_NAME, TEXT("WindowName"), // クラス名、ウィンドウ名
        WS_OVERLAPPEDWINDOW,            // ウィンドウスタイル
        CW_USEDEFAULT, CW_USEDEFAULT,   // ウィンドウの表示位置(x,y)
        CW_USEDEFAULT, CW_USEDEFAULT,   // ウィンドウの幅と高さ
        NULL,                           // 親ウィンドウのハンドル
        NULL,                           // メニューのハンドル
        hInstance,                      // インスタンスハンドル
        NULL);                          // 追加のデータ

    if (hwnd == NULL)
    {
        return 0;
    }

    // 3.ウィンドウの表示
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 4.メッセージループ
    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        if (WM_KEYFIRST <= msg.message && msg.message <= WM_KEYLAST)
        {
            LogMessage(L"KeyMessage.txt", msg.message, msg.wParam);
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

// 5.ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

// ファイルにログを出力（メッセージ出力用）
void LogMessage(LPCWSTR fPath, UINT uMsg, WPARAM wParam)
{
    FILE *fp;
    if (_wfopen_s(&fp, fPath, L"a, ccs=UTF-8") == 0)
    {
        INT16 key = 0;
        if (wParam)
        {
            UIntPtrToInt16(wParam, &key);
        }
        fwprintf_s(fp, L"message: 0x%04X 0x%02X\n", uMsg, key);
        fclose(fp);
    }
}
```

## メッセージの数値を文字列に変換

`hex2string.cs`というファイル名で保存して、コマンドライン上で
```bat
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe hex2string.cs
```
でコンパイルします。`hex2string.exe`にテキストファイルをドロップすると`0x0200`などの数値を`WM_MOUSEMOVE`に置き換えます。

```cs
/*
hex2string.cs
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe hex2string.cs
*/
using System.Text;
using System.IO;

namespace hex2string
{
    internal class Program
    {
        static void Main(string[] args)
        {
            foreach (string arg in args)
            {
                string filepath = arg;
                string text = File.ReadAllText(filepath, new UTF8Encoding(false));

                text = text.Replace("0x0000", "WM_NULL");
                text = text.Replace("0x0001", "WM_CREATE");
                text = text.Replace("0x0002", "WM_DESTROY");
                text = text.Replace("0x0003", "WM_MOVE");
                text = text.Replace("0x0005", "WM_SIZE");
                text = text.Replace("0x0006", "WM_ACTIVATE");
                text = text.Replace("0x0007", "WM_SETFOCUS");
                text = text.Replace("0x0008", "WM_KILLFOCUS");
                text = text.Replace("0x000A", "WM_ENABLE");
                text = text.Replace("0x000B", "WM_SETREDRAW");
                text = text.Replace("0x000C", "WM_SETTEXT");
                text = text.Replace("0x000D", "WM_GETTEXT");
                text = text.Replace("0x000E", "WM_GETTEXTLENGTH");
                text = text.Replace("0x000F", "WM_PAINT");
                text = text.Replace("0x0010", "WM_CLOSE");
                text = text.Replace("0x0011", "WM_QUERYENDSESSION");
                text = text.Replace("0x0012", "WM_QUIT");
                text = text.Replace("0x0013", "WM_QUERYOPEN");
                text = text.Replace("0x0014", "WM_ERASEBKGND");
                text = text.Replace("0x0015", "WM_SYSCOLORCHANGE");
                text = text.Replace("0x0016", "WM_ENDSESSION");
                text = text.Replace("0x0018", "WM_SHOWWINDOW");
                text = text.Replace("0x001A", "WM_WININICHANGE");
                text = text.Replace("0x001B", "WM_DEVMODECHANGE");
                text = text.Replace("0x001C", "WM_ACTIVATEAPP");
                text = text.Replace("0x001D", "WM_FONTCHANGE");
                text = text.Replace("0x001E", "WM_TIMECHANGE");
                text = text.Replace("0x001F", "WM_CANCELMODE");
                text = text.Replace("0x0020", "WM_SETCURSOR");
                text = text.Replace("0x0021", "WM_MOUSEACTIVATE");
                text = text.Replace("0x0022", "WM_CHILDACTIVATE");
                text = text.Replace("0x0023", "WM_QUEUESYNC");
                text = text.Replace("0x0024", "WM_GETMINMAXINFO");
                text = text.Replace("0x0026", "WM_PAINTICON");
                text = text.Replace("0x0027", "WM_ICONERASEBKGND");
                text = text.Replace("0x0028", "WM_NEXTDLGCTL");
                text = text.Replace("0x002A", "WM_SPOOLERSTATUS");
                text = text.Replace("0x002B", "WM_DRAWITEM");
                text = text.Replace("0x002C", "WM_MEASUREITEM");
                text = text.Replace("0x002D", "WM_DELETEITEM");
                text = text.Replace("0x002E", "WM_VKEYTOITEM");
                text = text.Replace("0x002F", "WM_CHARTOITEM");
                text = text.Replace("0x0030", "WM_SETFONT");
                text = text.Replace("0x0031", "WM_GETFONT");
                text = text.Replace("0x0032", "WM_SETHOTKEY");
                text = text.Replace("0x0033", "WM_GETHOTKEY");
                text = text.Replace("0x0037", "WM_QUERYDRAGICON");
                text = text.Replace("0x0039", "WM_COMPAREITEM");
                text = text.Replace("0x003D", "WM_GETOBJECT");
                text = text.Replace("0x0041", "WM_COMPACTING");
                text = text.Replace("0x0044", "WM_COMMNOTIFY");
                text = text.Replace("0x0046", "WM_WINDOWPOSCHANGING");
                text = text.Replace("0x0047", "WM_WINDOWPOSCHANGED");
                text = text.Replace("0x0048", "WM_POWER");
                text = text.Replace("0x004A", "WM_COPYDATA");
                text = text.Replace("0x004B", "WM_CANCELJOURNAL");
                text = text.Replace("0x004E", "WM_NOTIFY");
                text = text.Replace("0x0050", "WM_INPUTLANGCHANGEREQUEST");
                text = text.Replace("0x0051", "WM_INPUTLANGCHANGE");
                text = text.Replace("0x0052", "WM_TCARD");
                text = text.Replace("0x0053", "WM_HELP");
                text = text.Replace("0x0054", "WM_USERCHANGED");
                text = text.Replace("0x0055", "WM_NOTIFYFORMAT");
                text = text.Replace("0x007B", "WM_CONTEXTMENU");
                text = text.Replace("0x007C", "WM_STYLECHANGING");
                text = text.Replace("0x007D", "WM_STYLECHANGED");
                text = text.Replace("0x007E", "WM_DISPLAYCHANGE");
                text = text.Replace("0x007F", "WM_GETICON");
                text = text.Replace("0x0080", "WM_SETICON");
                text = text.Replace("0x0081", "WM_NCCREATE");
                text = text.Replace("0x0082", "WM_NCDESTROY");
                text = text.Replace("0x0083", "WM_NCCALCSIZE");
                text = text.Replace("0x0084", "WM_NCHITTEST");
                text = text.Replace("0x0085", "WM_NCPAINT");
                text = text.Replace("0x0086", "WM_NCACTIVATE");
                text = text.Replace("0x0087", "WM_GETDLGCODE");
                text = text.Replace("0x0088", "WM_SYNCPAINT");
                text = text.Replace("0x00A0", "WM_NCMOUSEMOVE");
                text = text.Replace("0x00A1", "WM_NCLBUTTONDOWN");
                text = text.Replace("0x00A2", "WM_NCLBUTTONUP");
                text = text.Replace("0x00A3", "WM_NCLBUTTONDBLCLK");
                text = text.Replace("0x00A4", "WM_NCRBUTTONDOWN");
                text = text.Replace("0x00A5", "WM_NCRBUTTONUP");
                text = text.Replace("0x00A6", "WM_NCRBUTTONDBLCLK");
                text = text.Replace("0x00A7", "WM_NCMBUTTONDOWN");
                text = text.Replace("0x00A8", "WM_NCMBUTTONUP");
                text = text.Replace("0x00A9", "WM_NCMBUTTONDBLCLK");
                text = text.Replace("0x00AB", "WM_NCXBUTTONDOWN");
                text = text.Replace("0x00AC", "WM_NCXBUTTONUP");
                text = text.Replace("0x00AD", "WM_NCXBUTTONDBLCLK");
                text = text.Replace("0x00FE", "WM_INPUT_DEVICE_CHANGE");
                text = text.Replace("0x00FF", "WM_INPUT");
                text = text.Replace("0x0100", "WM_KEYDOWN");
                text = text.Replace("0x0101", "WM_KEYUP");
                text = text.Replace("0x0102", "WM_CHAR");
                text = text.Replace("0x0103", "WM_DEADCHAR");
                text = text.Replace("0x0104", "WM_SYSKEYDOWN");
                text = text.Replace("0x0105", "WM_SYSKEYUP");
                text = text.Replace("0x0106", "WM_SYSCHAR");
                text = text.Replace("0x0107", "WM_SYSDEADCHAR");
                text = text.Replace("0x0108", "WM_KEYLAST");
                text = text.Replace("0x0109", "WM_UNICHAR");
                text = text.Replace("0x010D", "WM_IME_STARTCOMPOSITION");
                text = text.Replace("0x010E", "WM_IME_ENDCOMPOSITION");
                text = text.Replace("0x010F", "WM_IME_COMPOSITION");
                text = text.Replace("0x0110", "WM_INITDIALOG");
                text = text.Replace("0x0111", "WM_COMMAND");
                text = text.Replace("0x0112", "WM_SYSCOMMAND");
                text = text.Replace("0x0113", "WM_TIMER");
                text = text.Replace("0x0114", "WM_HSCROLL");
                text = text.Replace("0x0115", "WM_VSCROLL");
                text = text.Replace("0x0116", "WM_INITMENU");
                text = text.Replace("0x0117", "WM_INITMENUPOPUP");
                text = text.Replace("0x0119", "WM_GESTURE");
                text = text.Replace("0x011A", "WM_GESTURENOTIFY");
                text = text.Replace("0x011F", "WM_MENUSELECT");
                text = text.Replace("0x0120", "WM_MENUCHAR");
                text = text.Replace("0x0121", "WM_ENTERIDLE");
                text = text.Replace("0x0122", "WM_MENURBUTTONUP");
                text = text.Replace("0x0123", "WM_MENUDRAG");
                text = text.Replace("0x0124", "WM_MENUGETOBJECT");
                text = text.Replace("0x0125", "WM_UNINITMENUPOPUP");
                text = text.Replace("0x0126", "WM_MENUCOMMAND");
                text = text.Replace("0x0127", "WM_CHANGEUISTATE");
                text = text.Replace("0x0128", "WM_UPDATEUISTATE");
                text = text.Replace("0x0129", "WM_QUERYUISTATE");
                text = text.Replace("0x0132", "WM_CTLCOLORMSGBOX");
                text = text.Replace("0x0133", "WM_CTLCOLOREDIT");
                text = text.Replace("0x0134", "WM_CTLCOLORLISTBOX");
                text = text.Replace("0x0135", "WM_CTLCOLORBTN");
                text = text.Replace("0x0136", "WM_CTLCOLORDLG");
                text = text.Replace("0x0137", "WM_CTLCOLORSCROLLBAR");
                text = text.Replace("0x0138", "WM_CTLCOLORSTATIC");
                text = text.Replace("0x0200", "WM_MOUSEMOVE");
                text = text.Replace("0x0201", "WM_LBUTTONDOWN");
                text = text.Replace("0x0202", "WM_LBUTTONUP");
                text = text.Replace("0x0203", "WM_LBUTTONDBLCLK");
                text = text.Replace("0x0204", "WM_RBUTTONDOWN");
                text = text.Replace("0x0205", "WM_RBUTTONUP");
                text = text.Replace("0x0206", "WM_RBUTTONDBLCLK");
                text = text.Replace("0x0207", "WM_MBUTTONDOWN");
                text = text.Replace("0x0208", "WM_MBUTTONUP");
                text = text.Replace("0x0209", "WM_MBUTTONDBLCLK");
                text = text.Replace("0x020A", "WM_MOUSEWHEEL");
                text = text.Replace("0x020B", "WM_XBUTTONDOWN");
                text = text.Replace("0x020C", "WM_XBUTTONUP");
                text = text.Replace("0x020D", "WM_XBUTTONDBLCLK");
                text = text.Replace("0x020E", "WM_MOUSEHWHEEL");
                text = text.Replace("0x0210", "WM_PARENTNOTIFY");
                text = text.Replace("0x0211", "WM_ENTERMENULOOP");
                text = text.Replace("0x0212", "WM_EXITMENULOOP");
                text = text.Replace("0x0213", "WM_NEXTMENU");
                text = text.Replace("0x0214", "WM_SIZING");
                text = text.Replace("0x0215", "WM_CAPTURECHANGED");
                text = text.Replace("0x0216", "WM_MOVING");
                text = text.Replace("0x0218", "WM_POWERBROADCAST");
                text = text.Replace("0x0219", "WM_DEVICECHANGE");
                text = text.Replace("0x0220", "WM_MDICREATE");
                text = text.Replace("0x0221", "WM_MDIDESTROY");
                text = text.Replace("0x0222", "WM_MDIACTIVATE");
                text = text.Replace("0x0223", "WM_MDIRESTORE");
                text = text.Replace("0x0224", "WM_MDINEXT");
                text = text.Replace("0x0225", "WM_MDIMAXIMIZE");
                text = text.Replace("0x0226", "WM_MDITILE");
                text = text.Replace("0x0227", "WM_MDICASCADE");
                text = text.Replace("0x0228", "WM_MDIICONARRANGE");
                text = text.Replace("0x0229", "WM_MDIGETACTIVE");
                text = text.Replace("0x0230", "WM_MDISETMENU");
                text = text.Replace("0x0231", "WM_ENTERSIZEMOVE");
                text = text.Replace("0x0232", "WM_EXITSIZEMOVE");
                text = text.Replace("0x0233", "WM_DROPFILES");
                text = text.Replace("0x0234", "WM_MDIREFRESHMENU");
                text = text.Replace("0x0238", "WM_POINTERDEVICECHANGE");
                text = text.Replace("0x0239", "WM_POINTERDEVICEINRANGE");
                text = text.Replace("0x023A", "WM_POINTERDEVICEOUTOFRANGE");
                text = text.Replace("0x0240", "WM_TOUCH");
                text = text.Replace("0x0241", "WM_NCPOINTERUPDATE");
                text = text.Replace("0x0242", "WM_NCPOINTERDOWN");
                text = text.Replace("0x0243", "WM_NCPOINTERUP");
                text = text.Replace("0x0245", "WM_POINTERUPDATE");
                text = text.Replace("0x0246", "WM_POINTERDOWN");
                text = text.Replace("0x0247", "WM_POINTERUP");
                text = text.Replace("0x0249", "WM_POINTERENTER");
                text = text.Replace("0x024A", "WM_POINTERLEAVE");
                text = text.Replace("0x024B", "WM_POINTERACTIVATE");
                text = text.Replace("0x024C", "WM_POINTERCAPTURECHANGED");
                text = text.Replace("0x024D", "WM_TOUCHHITTESTING");
                text = text.Replace("0x024E", "WM_POINTERWHEEL");
                text = text.Replace("0x024F", "WM_POINTERHWHEEL");
                text = text.Replace("0x0251", "WM_POINTERROUTEDTO");
                text = text.Replace("0x0252", "WM_POINTERROUTEDAWAY");
                text = text.Replace("0x0253", "WM_POINTERROUTEDRELEASED");
                text = text.Replace("0x0281", "WM_IME_SETCONTEXT");
                text = text.Replace("0x0282", "WM_IME_NOTIFY");
                text = text.Replace("0x0283", "WM_IME_CONTROL");
                text = text.Replace("0x0284", "WM_IME_COMPOSITIONFULL");
                text = text.Replace("0x0285", "WM_IME_SELECT");
                text = text.Replace("0x0286", "WM_IME_CHAR");
                text = text.Replace("0x0288", "WM_IME_REQUEST");
                text = text.Replace("0x0290", "WM_IME_KEYDOWN");
                text = text.Replace("0x0291", "WM_IME_KEYUP");
                text = text.Replace("0x02A0", "WM_NCMOUSEHOVER");
                text = text.Replace("0x02A1", "WM_MOUSEHOVER");
                text = text.Replace("0x02A2", "WM_NCMOUSELEAVE");
                text = text.Replace("0x02A3", "WM_MOUSELEAVE");
                text = text.Replace("0x02B1", "WM_WTSSESSION_CHANGE");
                text = text.Replace("0x02E0", "WM_DPICHANGED");
                text = text.Replace("0x02E2", "WM_DPICHANGED_BEFOREPARENT");
                text = text.Replace("0x02E3", "WM_DPICHANGED_AFTERPARENT");
                text = text.Replace("0x02E4", "WM_GETDPISCALEDSIZE");
                text = text.Replace("0x0300", "WM_CUT");
                text = text.Replace("0x0301", "WM_COPY");
                text = text.Replace("0x0302", "WM_PASTE");
                text = text.Replace("0x0303", "WM_CLEAR");
                text = text.Replace("0x0304", "WM_UNDO");
                text = text.Replace("0x0305", "WM_RENDERFORMAT");
                text = text.Replace("0x0306", "WM_RENDERALLFORMATS");
                text = text.Replace("0x0307", "WM_DESTROYCLIPBOARD");
                text = text.Replace("0x0308", "WM_DRAWCLIPBOARD");
                text = text.Replace("0x0309", "WM_PAINTCLIPBOARD");
                text = text.Replace("0x030A", "WM_VSCROLLCLIPBOARD");
                text = text.Replace("0x030B", "WM_SIZECLIPBOARD");
                text = text.Replace("0x030C", "WM_ASKCBFORMATNAME");
                text = text.Replace("0x030D", "WM_CHANGECBCHAIN");
                text = text.Replace("0x030E", "WM_HSCROLLCLIPBOARD");
                text = text.Replace("0x030F", "WM_QUERYNEWPALETTE");
                text = text.Replace("0x0310", "WM_PALETTEISCHANGING");
                text = text.Replace("0x0311", "WM_PALETTECHANGED");
                text = text.Replace("0x0312", "WM_HOTKEY");
                text = text.Replace("0x0317", "WM_PRINT");
                text = text.Replace("0x0318", "WM_PRINTCLIENT");
                text = text.Replace("0x0319", "WM_APPCOMMAND");
                text = text.Replace("0x031A", "WM_THEMECHANGED");
                text = text.Replace("0x031D", "WM_CLIPBOARDUPDATE");
                text = text.Replace("0x031E", "WM_DWMCOMPOSITIONCHANGED");
                text = text.Replace("0x031F", "WM_DWMNCRENDERINGCHANGED");
                text = text.Replace("0x0320", "WM_DWMCOLORIZATIONCOLORCHANGED");
                text = text.Replace("0x0321", "WM_DWMWINDOWMAXIMIZEDCHANGE");
                text = text.Replace("0x0323", "WM_DWMSENDICONICTHUMBNAIL");
                text = text.Replace("0x0326", "WM_DWMSENDICONICLIVEPREVIEWBITMAP");
                text = text.Replace("0x033F", "WM_GETTITLEBARINFOEX");
                text = text.Replace("0x0345", "WM_TOOLTIPDISMISS");

                string dir = Path.GetDirectoryName(filepath);
                string filename = Path.GetFileNameWithoutExtension(filepath);

                File.WriteAllText(dir + @"\" + filename + "_fix.txt", text, new UTF8Encoding(false));
            }
        }
    }
}
```

# その他参考URL

メッセージについて  
* [メッセージとメッセージ キューについて - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-messages-and-message-queues#windows-messages)  
* [C言語 #defineとは？ 記号定数 | プログラミングランド](https://skpme.com/259/)  
* [定数](http://www.ohshiro.tuis.ac.jp/~ohshiro/ooprog/c_const_struct_typedef/const.html)  
* [記号定数 | Programming Place Plus　用語集](https://programming-place.net/ppp/contents/glossary/ka/symbolic_constant.html)  
* [Named Constants](http://www.cs.ecu.edu/karl/2530/fall19/Notes/lec05C.html)  

HTMLテーブル作成  
* [レスポンシブも対応！綺麗で見やすい表のデザイン11個[HTML&CSS] | SEO対策なら株式会社ペコプラ](https://pecopla.net/web-column/table-design)  
* [CSSで下線を引く方法とは?二重線・破線・波線・蛍光線など徹底解説! | 侍エンジニアブログ](https://www.sejuku.net/blog/82884)  

ログ出力用
* [fopen_s、_wfopen_s | Microsoft Learn](https://learn.microsoft.com/ja-jp/cpp/c-runtime-library/reference/fopen-s-wfopen-s?view=msvc-170)  
* [fprintf_s、_fprintf_s_l、fwprintf_s、_fwprintf_s_l | Microsoft Learn](https://learn.microsoft.com/ja-jp/cpp/c-runtime-library/reference/fprintf-s-fprintf-s-l-fwprintf-s-fwprintf-s-l?view=msvc-170)  
* [fclose、_fcloseall | Microsoft Learn](https://learn.microsoft.com/ja-jp/cpp/c-runtime-library/reference/fclose-fcloseall?view=msvc-170)  
* [UIntPtrToInt16 関数 (intsafe.h) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/api/intsafe/nf-intsafe-uintptrtoint16)  
* [Windows Data Types (BaseTsd.h) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types)