2013-12-19 86 views
1

我正在使用CefGlue來製作一個帶有嵌入式webkit瀏覽器的應用程序,並且我需要在瀏覽器窗口中偵聽mousemovements。 winforms控件不會將鼠標事件傳遞給控件,​​所以我不能聽它們。截取另一個窗口的窗口消息

但是,我發現了一個包含解決方案的bug /功能請求,但是如何實現它卻超出了我,我不熟悉直接在WinAPI中工作。開發人員說我需要:

。特定於操作系統(windows) - 瀏覽器創建後(CefLifeSpanHandler.OnAfterCreated)獲取窗口句柄和子類(窗口子類化技術)。其實現在我們有原生 窗口與類CefBrowserWindow(返回 CefBrowser.GetHost()。GetWindowHandle()),然後子窗口 Chrome_WidgetWin_0,然後Chrome_RenderWidgetHostHWND。對於攔截WM_MOUSEMOVE的 ,您在Chrome_WidgetWin_0 窗口中感興趣,可以通過CefBrowserWindow輕鬆獲取該窗口。只需用Spy ++玩 即可查看。

https://bitbucket.org/xilium/xilium.cefglue/issue/4/mouse-events-unaccessible

我做了一些google搜索,但我不知道如何連接到這一點。我有我的表格上這樣的功能:

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
    protected override void WndProc(ref Message m) { 
     base.WndProc(ref m); 

     switch (m.Msg) { 
      case WM_MOUSEMOVE: 
       Console.WriteLine("Mouse move!"); 
       break; 
      default: 
       Console.WriteLine(m.ToString()); 
       break; 
     } 
    } 

但我從來沒有看到鼠標移動,當我在控制。我懷疑我需要聽取CefBrowser.GetHost().GetWindowHandle()的WndProc,但我不知道該怎麼做。

+1

參見[NativeWindow類](http://msdn.microsoft.com/en-us/library/system.windows.forms.nativewindow(V = vs.110 )的.aspx) – LarsTech

回答

3

我找到了解決方案。我從WebLifeSpanHandler的OnAfterCreated事件中調用此函數。

 browser.Created += (sender, eventargs) => { 
      Console.WriteLine("Created."); 
      BrowserWindowPointer = browser.CefBrowser.GetHost().GetWindowHandle(); 
      Console.WriteLine("BrowserWindowPointer: " + BrowserWindowPointer); 
      uint BrowserThreadId = GetWindowThreadProcessId(BrowserWindowPointer, IntPtr.Zero); 
      Console.WriteLine("Browser PID: " + BrowserThreadId); 

      MouseHookProcedure = new HookProc(this.MouseHookProc); 

      hHookMouse = SetWindowsHookEx(WH_MOUSE, 
         MouseHookProcedure, 
         (IntPtr)0, 
         BrowserThreadId); 

      if (hHookMouse == 0) { 
       Console.WriteLine("MouseHook Failed. Making cursor always visible."); 
       Cursor.Show(); 
      } 

      KeyboardHookProcedure = new HookProc(this.KeyboardHookProc); 
      hHookKeyboard = SetWindowsHookEx(WH_KEYBOARD, 
         KeyboardHookProcedure, 
         (IntPtr)0, 
         BrowserThreadId); 
     }; 

我一直在尋找的功能是GetWindowThreadProcessId,我可以使用所提供的窗口句柄通過browser.CefBrowser.GetHost().GetWindowHandle()

有一點要注意的是,掛鉤過程需要有某種較大的範圍。 C#沒有看到它掛鉤到本機進程中,並且將垃圾收集它,如果你讓它超出範圍。爲了解決這個問題,我做了他們的類屬性。

支持文件:

我的兩個鉤子(不好的代碼,我不這樣做與編組數據的任何東西):

private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam) { 
     //Marshall the data from the callback. 
     MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct)); 

     if (nCode < 0) { 
      return CallNextHookEx(hHookMouse, nCode, wParam, lParam); 
     } else { 
      if (wParam.ToInt32() == WM_MOUSEMOVE) { 
       Screensaver_OnMouseMove(this, null); 
      } 
      return CallNextHookEx(hHookMouse, nCode, wParam, lParam); 
     } 
    } 

    private int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam) { 
     //Marshall the data from the callback. 
     KeyboardHookStruct keyInfo = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); 
     int VK_ESCAPE = 0x1B; 

     if (nCode < 0) { 
      return CallNextHookEx(hHookKeyboard, nCode, wParam, lParam); 
     } else { 
      int keyCode = wParam.ToInt32(); 

      if (keyCode == VK_ESCAPE) { 
       Application.Exit(); 
      } 

      return CallNextHookEx(hHookKeyboard, nCode, wParam, lParam); 
     } 

    } 

這是實習醫生和揭露鉤所需的代碼,這是一流水平範圍:

public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam); 

    //Declare the hook handle as an int. 
    static int hHookMouse = 0; 
    static int hHookKeyboard = 0; 

    //Declare the mouse hook constant. 
    //For other hook types, you can obtain these values from Winuser.h in the Microsoft SDK. 
    private const int WH_KEYBOARD = 2; 
    private const int WH_MOUSE = 7; 
    private const int WM_MOUSEMOVE = 0x0200; 

    //Declare the wrapper managed POINT class. 
    [StructLayout(LayoutKind.Sequential)] 
    public class POINT { 
     public int x; 
     public int y; 
    } 

    //Declare the wrapper managed MouseHookStruct class. 
    [StructLayout(LayoutKind.Sequential)] 
    public class MouseHookStruct { 
     public POINT pt; 
     public int hwnd; 
     public int wHitTestCode; 
     public int dwExtraInfo; 
    } 
    public struct KeyboardHookStruct { 
     public int vkCode; 
     public int scanCode; 
     public int flags; 
     public int time; 
     public int dwExtraInfo; 
    } 

    //This is the Import for the SetWindowsHookEx function. 
    //Use this function to install a thread-specific hook. 
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
    public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, uint threadId); 

    //This is the Import for the UnhookWindowsHookEx function. 
    //Call this function to uninstall the hook. 
    [DllImport("user32.dll", CharSet = CharSet.Auto, 
    CallingConvention = CallingConvention.StdCall)] 
    public static extern bool UnhookWindowsHookEx(int idHook); 

    //This is the Import for the CallNextHookEx function. 
    //Use this function to pass the hook information to the next hook procedure in chain. 
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
    public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam); 

    [DllImport("user32.dll")] 
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); 

    public HookProc KeyboardHookProcedure { get; set; } 

    public HookProc MouseHookProcedure { get; set; } 

我不知道這是完全需要的,特別是因爲線程被鉤到會消失在接近,但只是良好的措施,不要忘了清理你的鉤子你後聽完了。我這樣做對我的窗體的Dispose方法:

protected override void Dispose(bool disposing) { 
     base.Dispose(); 

     if (disposing) { 
      if (hHookKeyboard != 0) { 
       UnhookWindowsHookEx(hHookKeyboard); 
      } 
      if (hHookMouse != 0) { 
       UnhookWindowsHookEx(hHookMouse); 
      } 
     } 
    } 
相關問題