windows_同一プロセス内のメッセージボックスを変更してみる
windowsの環境でsetWindowHookExを使って同一プロセス内のメッセージボックス表示の処理をhookし内容を変更できるようにしたいと思います。別のソフトでのメッセージボックス表示内容を変更できるようになったら面白そうですが、まずは同一プロセス内のメッセージボックスに対して変更できるようになりたいと思います。
プロジェクトはvisual c++で作成します。
MsgBoxをhookする部分のファイルはいかのようになりました。
MsgBoxHook.cpp
#include "stdafx.h" #include "MsgBoxHook.h" HHOOK hMsgBoxHook; LRESULT CALLBACK MsgBoxHookProc(int nCode, WPARAM wp, LPARAM lp) { if (nCode >= 0) { if (nCode == HCBT_ACTIVATE) { // テキストラベルの内容を書き換える HWND label = ::GetDlgItem((HWND)wp, 0xFFFF); SetWindowText(label, "Hook"); // OK(IDOK)の内容を書き換える CHAR okLabel[51] = { 0 }; GetDlgItemText((HWND)wp, IDOK, okLabel, sizeof(okLabel) - 1); SetDlgItemText((HWND)wp, IDOK, strcat(okLabel, "(HOOK)")); // キャンセルボタン(IDCANCEL)の内容を書き換える CHAR cancelLabel[51] = { 0 }; GetDlgItemText((HWND)wp, IDCANCEL, cancelLabel, sizeof(cancelLabel) - 1); SetDlgItemText((HWND)wp, IDCANCEL, strcat(cancelLabel, "(HOOK)")); } } return CallNextHookEx(hMsgBoxHook, nCode, wp, lp); } bool MsgBoxHookStart(HWND hWnd) { HINSTANCE hInst; hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); hMsgBoxHook = SetWindowsHookEx(WH_CBT, //フック関数のタイプ (HOOKPROC)MsgBoxHookProc, //フックプロシージャのアドレス hInst, //フックプロシージャが入っているインスタンスハンドル GetCurrentThreadId()); //フックされるスレッド 0ならすべてのスレッド if (hMsgBoxHook == NULL) { MessageBox(hWnd, "フック開始に失敗", "Error", MB_OK); return false; } else { return true; } } bool MsgBoxHookEnd(HWND hWnd) { if (UnhookWindowsHookEx(hMsgBoxHook) != 0) { return true; } else { MessageBox(hWnd, "フック解除に失敗", "Error", MB_OK); return false; } }
SetWindowsHookExはMsgBoxHookStart関数内で呼び出しています。フックする関数のタイプとしてWH_CBTを指定していますが、これはウィンドウの生成などに対応しているらしいです。今回は実行するソフト内のみで有効なので、フックされるスレッドとしてGetCurrentThreadId()を指定しています。ここですべてのスレッドを指定しようとして0を渡してもhookには失敗するかと思います。
hookを終了するUnhookWindowsHookExはMsgBoxHookEnd関数内で呼び出しています。
メッセージボックスをフックする関数はMsgBoxHookProcで定義しており、メッセージボックスのテキスト、ok、キャンセルボタンの内容を変更するようにしています。 これのヘッダファイルは以下のようになりました。
MsgBoxHook.h
#pragma once #include<Windows.h> bool MsgBoxHookStart(HWND hWnd); bool MsgBoxHookEnd(HWND hWnd);
それからhookの開始、終了、それから今回はメッセージボックスを表示する必要があるので、以下のようなフォームを作成して動かせば確認できるかと思います。
Form1.h
#pragma once #include "MsgBoxHook.h" #pragma comment(lib, "User32.lib") namespace CppCLR_WinformsProjekt { using namespace System; using namespace System::ComponentModel;a using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; /// <summary> /// Zusammenfassung f・ Form1 /// </summary> public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: Konstruktorcode hier hinzuf・en. // } protected: /// <summary> /// Verwendete Ressourcen bereinigen. /// </summary> ~Form1() { if (components) { delete components; } } private: System::Windows::Forms::Button^ button1; private: System::Windows::Forms::Button^ button2; private: System::Windows::Forms::Label^ label1; private: System::Windows::Forms::Button^ button3; protected: private: /// <summary> /// Erforderliche Designervariable. /// </summary> System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary> /// Erforderliche Methode f・ die Designerunterst・zung. /// Der Inhalt der Methode darf nicht mit dem Code-Editor ge舅dert werden. /// </summary> void InitializeComponent(void) { this->button1 = (gcnew System::Windows::Forms::Button()); this->button2 = (gcnew System::Windows::Forms::Button()); this->label1 = (gcnew System::Windows::Forms::Label()); this->button3 = (gcnew System::Windows::Forms::Button()); this->SuspendLayout(); // // button1 // this->button1->Location = System::Drawing::Point(33, 53); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(101, 40); this->button1->TabIndex = 0; this->button1->Text = L"start"; this->button1->UseVisualStyleBackColor = true; this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click); // // button2 // this->button2->Location = System::Drawing::Point(152, 53); this->button2->Name = L"button2"; this->button2->Size = System::Drawing::Size(101, 40); this->button2->TabIndex = 1; this->button2->Text = L"stop"; this->button2->UseVisualStyleBackColor = true; this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click); // // label1 // this->label1->AutoSize = true; this->label1->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 22)); this->label1->Location = System::Drawing::Point(37, 9); this->label1->Name = L"label1"; this->label1->Size = System::Drawing::Size(156, 30); this->label1->TabIndex = 2; this->label1->Text = L"HOOK OFF"; this->label1->Click += gcnew System::EventHandler(this, &Form1::label1_Click); // // button3 // this->button3->Location = System::Drawing::Point(33, 100); this->button3->Name = L"button3"; this->button3->Size = System::Drawing::Size(220, 48); this->button3->TabIndex = 3; this->button3->Text = L"click"; this->button3->UseVisualStyleBackColor = true; this->button3->Click += gcnew System::EventHandler(this, &Form1::button3_Click_1); // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 12); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(283, 160); this->Controls->Add(this->button3); this->Controls->Add(this->label1); this->Controls->Add(this->button2); this->Controls->Add(this->button1); this->Name = L"Form1"; this->Text = L"Form1"; this->ResumeLayout(false); this->PerformLayout(); } #pragma endregion private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { HWND hWnd = static_cast<HWND>(this->Handle.ToPointer()); if( MsgBoxHookStart(hWnd)) { this->label1->Text = L"HOOK ON"; } } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { HWND hWnd = static_cast<HWND>(this->Handle.ToPointer()); if (MsgBoxHookEnd(hWnd)) { this->label1->Text = L"HOOK OFF"; } } private: System::Void richTextBox1_TextChanged(System::Object^ sender, System::EventArgs^ e) { } private: System::Void label1_Click(System::Object^ sender, System::EventArgs^ e) { } private: System::Void button3_Click_1(System::Object^ sender, System::EventArgs^ e) { MessageBox::Show("not hook", "not hook", MessageBoxButtons::OKCancel, MessageBoxIcon::Asterisk); } }; }