2013-12-19 85 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); 
      } 
     } 
    } 
相关问题