1

私は現在、かなりの量のフックを含み、「Steamオーバーレイ」と同じようにインタラクティブ製品のオーバーレイとして機能するように設計されたプロジェクトに取り組んでいます。

フック部分は実際に完成しています。DLLインジェクションを実行し、DirectXをフックし、それ自体をテクスチャにレンダリングしてから、フックされているアプリケーションでそのテクスチャをレンダリングする「非表示」のWPFアプリケーションがあります。

プログラムの構造

私たちが抱えている問題は後半です。オーバーレイ用の入力情報を取得します。図からわかるように、簡単な例はボタンが押されていることです。私がやりたいのは、DirectXアプリケーションへのすべての入力メッセージ(WM_x)を実際にキャプチャしてから、WPFアプリケーションにオーバーレイに関連するメッセージと関連しないメッセージを決定させることです。

WNDPROC私はDirectXアプリケーションのを使用してフックすることができました...

IntPtr _oldWindProc = GetWindowLong(MainWindowHandle, Win32Helper.GWL_WNDPROC);
WndProcDelegate _myProc = new Win32Helper.WndProc(WndProc);
SetWindowLong(MainWindowHandle, Win32Helper.GWL_WNDPROC, _myProc );

...そしてこれはうまくいくようです。この時点で、すべてのWM_xメッセージをWPFアプリケーションに戻すことができます。しかし、それは私が立ち往生しているところです。私が試したところPostMessage、Spy ++はメッセージを受信するWPFウィンドウを表示します(実際、WPFウィンドウ内にフックを設定すると同じことがわかります)が、これは意図したとおりに機能しないようです。だから、私は何が欠けていますか?応答する必要がある特定のWindowsメッセージはありますか?WPFアプリケーションが正しい場所で「WM_LBUTTONDOWN」を受信し、ボタンが押されるのと同じくらい簡単だと素朴に思いました。

任意のガイダンスをいただければ幸いです。

更新:実際の問題について少し詳しく説明したかもしれません。メッセージを意図した宛先であるかのようにWPFにリダイレクトしたいと思います。私はすでにメッセージをフックして、DirectXアプリケーションに移動するのをブロックしました。問題は、それらをWPFアプリケーションにシームレスに渡す方法です。

4

2 に答える 2

1

dllを使用しSetWindowsHookExてdirectxアプリをフックし、そのメッセージをメインアプリのサブクラス化されたウィンドウに戻します。私はこれをC++で実行しましたが、pinvokeなどを使用してC#で実行できるはずです。C++のコードは次のとおりです。

__declspec(dllexport) int _stdcall InstallHook(DWORD dwThreadId, HWND ExtrnHandle, HWND Apphandle)
{
    if (hHook==0)
            hWndApp = Apphandle;
            hWndHooked = ExtrnHandle;
            hHook = SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC) GetMsgProc, (HINSTANCE) hInstance, dwThreadId);
        if (hHook==0) return GetLastError();
    return 0;
}

これを使用してフックを解除します。

 __declspec(dllexport) int UnInstallHook(void)
{
    LRESULT result;
    if (hHook != 0){
        result = UnhookWindowsHookEx(hHook);
        if (result == 0) return GetLastError();
        hHook = 0;
    }
    return 0;
}

次に、dllでこのコールバックを使用して、メッセージをアプリに返します。

LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    MSG *lpMsg;

    if (nCode==HC_ACTION){
        lpMsg = (MSG *) lParam;
        //see if this is the window we are monitoring
        if (lpMsg->hwnd == hWndHooked){
            //forward the message to App
            ChangeMessage=false;
            SendMessage(hWndApp, lpMsg->message, lpMsg->wParam, lpMsg->lParam);
            if (ChangeMessage==true){//Did App make changes to the data?
                lpMsg->message = Shared_uMsg;
                lpMsg->wParam = Shared_wParam;
                lpMsg->lParam = Shared_lParam;

            }//end if change message

        }//end if correct hWnd
    }//end if nCode==Action     
    return(CallNextHookEx(hHook, nCode, wParam, lParam));
}

また、fyi、これはdll .cppファイルの上部にあるコード、宣言、共有データを設定する関数などです。

#include "afxdisp.h" //this does #include <windows.h>
#include <shellapi.h>
#include "WINUSER.H"    
#include <fstream>
#include <iostream>
using namespace std;

#define WM_MOUSEWHEEL 0x020A 
#define COPY2CLIPBOARD 1 //for copying data from msflexgrid
#define COPY2FILE      2

/*---------------------------------------------
          Shared Variables
This data is shared between both prcesses.  The
VB App has access to these variables through the
function SetSharedData
---------------------------------------------*/
#pragma data_seg(".shared")
    bool ChangeMessage = false;
    int Shared_uMsg = 0;
    int Shared_wParam = 0;
    int Shared_lParam = 0;
    int CopyMode = COPY2FILE;
    HWND hWndApp = 0; //handle to subclassed Window
    HWND hWndHooked = 0;//handle to the hooked window
    HHOOK   hHook = 0;      // Hook handle for WH_GETMESSAGE

#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")

//---------------------------------------------
// Global Variables, specific to each process
//---------------------------------------------
    HINSTANCE   hInstance;  // Global instance handle for DLL



//--------------------------------------------
//        DLL entry-point
//--------------------------------------------
BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpvReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
            hInstance = hinstDLL;//save dll handle for each process
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);

__declspec(dllexport) void _stdcall SetSharedData(int uMsg, WPARAM wParam, LPARAM lParam)
{
        Shared_uMsg = uMsg;
        Shared_wParam = wParam;
        Shared_lParam = lParam;
        ChangeMessage = true;
}
于 2012-06-18T16:28:10.157 に答える
0

これが意図したとおりに機能しないという根本的な理由が多すぎたため、必要な特定のイベント(基本的にはマウスイベント)に手動でパッチを適用することにしました。

于 2012-06-28T10:49:23.977 に答える