ウインドウのウインドウプロシージャを別のものに書き換えることです。独自のウインドウプロシージャを持っています。コントロールの動作を拡張したい場合は非常に便利です。通知されない処理を検出したい場合にだけ、サブクラス化を使用することになります。ウインドウプロシージャの書き換えは、SetWindowLongPtrで行うことができます。GWLP_WNDPROCを指定した場合はウインドウプロシージを設定する意味になります。第3引数のものに書き換えられたことになります。このNewButtonProcの実装は、具体的にはどのようになるのでしょうか。この方法について考える必要があります。ウインドウのデフォルトの処理が失われたということです。これは言い換えれば、書き換える前のウインドウプロシージャはデフォルトの実装を持っていることも意味します。デフォルトの処理を実行できることになります。ウインドウプロシージャの取得は、GetWindowLongPtrで行います。元のウインドウプロシージャを呼び出しは、CallWindowProcを通じて行います。lParam);lpPrevWndFuncは、元のウインドウプロシージャを指定します。hWndは、ウインドウハンドルを指定します。Msgは、メッセージを指定します。wParamは、WPARAM値を指定します。lParamは、LPARAM値を指定します。今回のプログラムは、ボタンをサブクラス化し、ボタン上におけるマウスの右ボタンの押下を検出します。TEXT("右ボタンが押されました。lParam);}WM_CREATEではボタンを作成するとともに、ボタンのサブクラス化も行います。その後にSetWindowLongPtrで新しいウインドウプロシージャを設定します。これはボタンが破棄される前に元のウインドウプロシージャへ戻すためです。元に戻さなくても特に問題はありません。NewButtonProcでは、マウスの右ボタンの押下を検出するためにWM_RBUTTONDOWNを処理しています。デフォルトの処理を行えるようにしています。NewButtonProcでは、WM_LBUTTONDOWNを処理することもできますが、これには意味がないことに注意してください。サブクラス化をしなくても左ボタンの押下は検出することができるからです。これはスーパークラス化によっても実現することができます。独自のウインドウプロシージャに送られるようになります。TEXT("右ボタンが押されました。lParam);}まず、既存のウインドウクラスの情報を取得するためにGetClassInfoExを呼び出して、WNDCLASSEX構造体を初期化します。第1引数にはインスタンスハンドルを指定し、第2引数には既存のウインドウクラスの名前を指定します。次に、取得した既存のウインドウプロシージャのアドレスを変数に保存しておきます。これは、独自のウインドウプロシージャでCallWindowProcを呼び出す際に必要になります。既存のウインドウクラスを基に新しいウインドウクラスを作成することになります。lpszClassNameに独自のウインドウクラスの名前を指定します。RegisterClassExが成功した場合はBUTTONEXというウインドウクラスが登録されたことを意味します。ウインドウへのメッセージはNewButtonProcで処理できるようになります。先のCreateWindowExの最終引数には、元のウインドウプロシージャのアドレスを指定しています。これを通じてNewButtonProcに元のウインドウプロシージャのアドレスを渡すようにしています。これは必ずWM_NCCREATEでなければなりません。WM_CREATEでアドレスを受け取ってしまうと、それ以前のメッセージ(WM_NCCREATEなど)が送られた場合にCallWindowProcの第1引数がNULLになってしまうからです。スーパークラス化を使用したほうがよいと思われます。コントロールの数によって処理が増えることはなくなります。