0

使用している古いレガシ アプリのメッセージ ハンドラーを変更したいのですが、それ以上のソースがありません。ソースを持っている dll で、ウィンドウ メッセージをインターセプトしてアプリに渡したいと考えています。これは可能ですか?私は次の行に沿って何かを試しました:

WNDPROC lpfnWndProc = NULL;

void GetHandler()
{
     HINSTANCE hInstance = GetModuleHandle(NULL);
     HWND hWnd = GetActiveWindow();

     WCHAR lpClassName[1024];

     GetClassName(hWnd,lpClassName,1024);

     WNDCLASSEX wc;

     GetClassInfoEx(hInstance, lpClassName, &wc);

     lpfnWndProc = wc.lpfnWndProc;

     wc.lpfnWndProc = NewMessageProc;

     RegisterClassEx(&wc);
}

ただし、GetActiveWindow は失敗し、NULL を返します。これを行う簡単な方法はありますか。事実、単純に別のメッセージ ハンドラを追加できれば幸いです。

4

2 に答える 2

2

特定のコントロールをサブクラス化するか、特定のウィンドウ クラスのすべてのウィンドウをサブクラス化するかは明確ではありません。

特定のコントロールをサブクラス化する場合は、MSDN の「コントロールのサブクラス化」セクションで、ComCtl32.dll バージョン 6 以降と、コントロールのウィンドウ プロシージャを直接置き換える従来の手順の両方について、その方法について説明しています。

特定のウィンドウ クラスのすべてのコントロールをサブクラス化したい場合は、SetClassLongPtr. これは、その後そのウィンドウ クラスで作成されたウィンドウにのみ影響することに注意してください。SetClassLongPtrを呼び出すときにウィンドウ ハンドルが必要であり、ウィンドウ クラスのサブクラス化の適用性が制限されるため、これはちょっとしたキャッチ 22 です。

投稿したコードに関しては、いくつかの問題があります。

への呼び出しは、間違った、つまり呼び出し元のアプリケーションのものをGetModuleHandle取得します。HINSTANCEウィンドウ クラスを登録するモジュールのモジュール ハンドルが必要なので、コントロールを実装する .dll の名前を渡す必要があります。

呼び出し元GetActiveWindowのスレッドが実際にアクティブなウィンドウを持っているかどうかに応じて、呼び出しが値を返す場合と返さない場合があります。あなたの場合は明らかにそうではないので、ウィンドウハンドルを取得する別の手段が必要ですFindWindowEx.

への最後の呼び出しRegisterClassExは、あなたが考えていることをしません。既存のウィンドウ クラスと同じ名前のウィンドウ クラスを再登録することはできないため、単純に失敗します。SetClassLongPtr上記のように、代わりに呼び出す必要があります。

于 2013-11-10T12:03:45.790 に答える
1

SetWindowSubclass動作を変更したいウィンドウのHWNDを取得した後に実際に使用します。SetWindowLong は、CommCtrl.dll バージョン 6 が登場した頃にウィンドウの WndProc を変更する方法として廃止されました。MSDN は、歴史の特定の部分とその動機についてすべてを教えてくれます。SetWindowSubclass を調べるだけです。

現状では、呼び出し元のスレッドにアクティブなウィンドウがあると仮定すると、WndProc が異なる場合でも、コードはターゲット ウィンドウと同じ属性を持つ新しいウィンドウ クラスを作成するだけです。既存のウィンドウの wndproc は設定されません。 (したがって、SetWindowLong と SetWindowSubclass について言及します)

編集:または、少なくとも、その点で私が行った見落としはありません。以下のコメントで指摘されているように、この RegisterClass への呼び出しは実際には失敗します。同じ className を複数回登録することはできません。

 

 

また、おそらく関数も確認する必要があります。FindWindow関数に NULLlpWindowNameと、ターゲット ウィンドウの (既知の) クラス名を指定するだけです。目的のウィンドウが返されたものではない場合は、 を使用できますEnumWindowsGetClassNameに提供するコールバック関数を呼び出すだけでEnumWindows、クラス名がターゲット ウィンドウのクラス名と一致する任意またはすべてのウィンドウをサブクラス化できます。

このウィンドウがサブクラス化されると、必要に応じて元のウィンドウ プロシージャにメッセージを渡し、必要に応じてそのメッセージを消費できます。

于 2013-11-10T11:41:58.507 に答える