Created
December 10, 2013 08:24
Method to watch a child windows messages specifically for use with CefSharp Chromium Embedded Web Browser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Diagnostics; | |
using System.Runtime.InteropServices; | |
using System.Security; | |
using System.Text; | |
using System.Windows.Forms; | |
using CefSharp; | |
using CefSharp.WinForms; | |
namespace WindowsFormsApplication1 | |
{ | |
public partial class Form2 : Form | |
{ | |
private const int GWL_WNDPROC = -4; | |
[DllImport("User32.Dll")] | |
public static extern int GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount); | |
[DllImport("user32.dll")] | |
private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); | |
[DllImport("user32.dll", EntryPoint = "GetWindowLong")] | |
private static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex); | |
[DllImport("user32.dll", EntryPoint = "SetWindowLong")] | |
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); | |
[SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("user32.dll", CharSet = CharSet.Auto)] | |
public static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); | |
[UnmanagedFunctionPointer(CallingConvention.Winapi)] | |
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); | |
[UnmanagedFunctionPointer(CallingConvention.Winapi)] | |
private delegate IntPtr WndProcDelegate(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); | |
public static List<IntPtr> GetChildWindows(IntPtr parent) | |
{ | |
var result = new List<IntPtr>(); | |
var listHandle = GCHandle.Alloc(result); | |
try | |
{ | |
var childProc = new EnumWindowsProc(EnumWindow); | |
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); | |
} | |
finally | |
{ | |
if (listHandle.IsAllocated) | |
{ | |
listHandle.Free(); | |
} | |
} | |
return result; | |
} | |
private static bool EnumWindow(IntPtr handle, IntPtr pointer) | |
{ | |
var gch = GCHandle.FromIntPtr(pointer); | |
var list = gch.Target as List<IntPtr>; | |
if (list == null) | |
{ | |
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); | |
} | |
list.Add(handle); | |
return true; | |
} | |
private readonly WebView _webView; | |
private IntPtr _oldWebViewWndProc; | |
public Form2() | |
{ | |
InitializeComponent(); | |
if (CEF.Initialize(new Settings { PackLoadingDisabled = true })) | |
{ | |
_webView = new WebView("http://www.google.com", new BrowserSettings()) {Dock = DockStyle.Fill}; | |
_webView.PropertyChanged += WebViewPropertyChanged; | |
Controls.Add(_webView); | |
} | |
} | |
private void WebViewPropertyChanged(object sender, PropertyChangedEventArgs e) | |
{ | |
if (e.PropertyName == "IsBrowserInitialized" && _webView.IsBrowserInitialized) | |
{ | |
//this is on the WebView UI thread need to invoke back into the Form UI thread | |
BeginInvoke(new Action(() => | |
{ | |
//get through child windows looking for the WebViewHost | |
foreach (var childWindow in GetChildWindows(Handle)) | |
{ | |
var className = new StringBuilder(100); | |
GetClassName(childWindow, className, className.Capacity); | |
if (className.ToString() == "WebViewHost") | |
{ | |
//add a watcher to the WebView wndproc messages | |
WatchWebViewWndProc(childWindow); | |
} | |
} | |
})); | |
} | |
} | |
private void WatchWebViewWndProc(IntPtr hwnd) | |
{ | |
//get current WndProc to pass message onto | |
_oldWebViewWndProc = GetWindowLong(hwnd, GWL_WNDPROC); | |
//overwrite WebView wndprox with our own | |
SetWindowLong(hwnd, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(new WndProcDelegate(WebViewWndProc))); | |
} | |
private IntPtr WebViewWndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam) | |
{ | |
if (msg == 0x0084) //WM_NCHITEST | |
{ | |
Debug.Print("WEBVIEW WM_NCHITEST"); | |
} | |
//always pass onto original WndProc | |
return CallWindowProc(_oldWebViewWndProc, hWnd, msg, wParam, lParam); | |
} | |
protected override void WndProc(ref Message m) | |
{ | |
if (m.Msg == 0x0083) //WM_NCAlSIZE | |
{ | |
} | |
if (m.Msg == 0x0084) //WM_NCHITEST | |
{ | |
Debug.Print("FORM WM_NCHITEST"); | |
} | |
base.WndProc(ref m); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello. This looks good, however I am using Xilium.Cefglue, which as far as I can tell does not have the WebViewPropertyChanged event. Is there a way to work around that?