2009-11-28 8 views
10

私はその画面に描画できるようにサードパーティのアプリケーションをフックしようとしています。画面への描画は簡単で、私はそれに助けは必要ありませんが、WH_GETMESSAGEを処理するためにSetWindowsHookExを使うことに問題があるようです。私は最後の2つのパラメータのために何を渡すかを理解できません。SetWindowsHookEx in C#

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace WindowDrawer 
{ 
    public partial class Form1 : Form 
    { 
     private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam); 
     static IntPtr hHook; 
     IntPtr windowHandle; 
     uint processHandle; 

     HookProc PaintHookProcedure;  

     [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] 
     static extern System.IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName); 

     [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)] 
     static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId); 

     [System.Runtime.InteropServices.DllImport("user32.dll")] 
     static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); 

     // When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter 
     [System.Runtime.InteropServices.DllImport("user32.dll")] 
     static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); 

     [System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet =System.Runtime.InteropServices.CharSet.Auto)] 
     public static extern IntPtr GetModuleHandle(string lpModuleName); 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 

      PaintHookProcedure = new HookProc(PaintHookProc); 
      windowHandle = FindWindowByCaption(0, "Untitled - Notepad"); 
      uint threadID = GetWindowThreadProcessId(windowHandle, out processHandle); 
      IntPtr hMod = System.Runtime.InteropServices.Marshal.GetHINSTANCE(typeof(Form1).Module); 

      // HERE IS THE PROBLEM. WHAT THE HECK DO I PASS INTO THE LAST 2 PARAMS? I get a null pointer 
      hHook = SetWindowsHookEx(WH_GETMESSAGE, PaintHookProcedure, hMod, threadID); 


     } 

     public int PaintHookProc(int nCode, IntPtr wParam, IntPtr lParam) 
     { 
      // Do some painting here. 
      return CallNextHookEx(hHook, nCode, wParam, lParam); 
     } 

     private const int WM_PAINT = 15; 
     private const int WH_GETMESSAGE = 3; 
    } 





} 

答えて

12

SetWindowsHookEx詳細最後の2つのパラメータを:

  • hMod

フックプロシージャを含むDLLのハンドル[IN]はlpfn パラメータによって指されます。 dwThreadId パラメータが現在のプロセスによって で作成されたスレッドを指定し、フック プロシージャが現在のプロセスに関連付けられたコード 内にある場合、hModパラメータは に設定されていなければなりません。

  • dwThreadId

[In]はフックプロシージャ が関連付けられる スレッドの識別子を指定します。このパラメータが がゼロの場合、フックプロシージャは、 呼び出しスレッドと同じデスクトップで実行されている既存のすべてのスレッド に関連付けられた です。

.NET DLLを必要な方法で使用できるかどうかは確かですが、確かに試すことができます。

グラブhModMarshal.GetHINSTANCE(typeof(Form1).Module)およびdwThreadId経由でProcess.Threads。または、グローバルフック(現在のデスクトップですべてのGetMessage()コールのフック)を実行したいがパフォーマンスペナルティに注意する場合は、dwThreadIdを0に設定します。

+0

あなたのアイデア。私はまだSetWindowsHookEx(WH_GETMESSAGE、PaintHookProcedure、hMod、threadID)== 0; – Darthg8r

+1

別のDLLにPaintHookProcedureをパッケージする必要があるという明確な可能性があります。これは.NETの使用を妨げます。 GetLastError()でエラーメッセージコードを取得し、問題の内容を確認します。 –

+2

GetLastError()はMarshal.GetLastWin32Error()を意味します。 p/GetLastError()を直接呼び出しても信頼できません。 –

2

私はあなたがGetModuleHandleを起動し、それがSetWindowsHookExの第三パラメータに返すハンドルを使用/ Pに必要と考えています。また、サードパーティのアプリケーションで特定のスレッドを1つもフックしたくないので、0が4番目のパラメータに対して正しいと確信しています。

これがうまくいかない場合は、MSDNのSetWindowsHookExが正しい方向に向けるかもしれません。 thusly

+0

のGetModuleHandle(文字列lpModuleName);??私は反映するために、上記のコードをモッド(。あなたの実行可能ファイル)私はそれにexeファイルの名前を何を渡すか – Darthg8r

+0

峠 'NULL'と、それは、呼び出しプロセスからハンドルを引くよ –

3

APIの助けを借りて「別のプロセスにDLLを注入する」ことを指定するパラメータ値を使用している場合は、それを呼び出すためのアンマネージドDLLを作成します。

2

私はこれが古い質問であることを知っていますが、私はこれが役に立つと思う人がいることを望んでいます。

「グローバルフックでサポートされていません。私はあなたが以下は、これは動作しません示唆intIntPtr

[System.Runtime.InteropServices.DllImport("user32.dll")] 
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); 
7

を混合していると思います。ネットフレームワーク。 WH_KEYBOARD_LL低レベルのフックとWH_MOUSE_LL低レベルのフックを除き、あなたは、Microsoft .NET Frameworkでグローバルフックを実装することはできません。」私にとってこの作品は、13を使用"How to set a Windows hook in Visual C# .NET"

-1

から

...

private static IntPtr SetHook(LowLevelKeyboardProc proc) 
     { 
      using (Process curProcess = Process.GetCurrentProcess()) 
      using (ProcessModule curModule = curProcess.MainModule) 
      { 
       return SetWindowsHookEx(13, proc, 
       GetModuleHandle(curModule.ModuleName), 0); 
      } 
     }