Blokada ContextMenu na komponencie WebBrowser
Jeśli używacie kontrolki WebBrowser z Compact Frameworka 2.0 zapewne spotkaliście się z ContextMenu pojawiającym sie za każdym razem gdy przytrzymacie zbyt długo rysik (zdarzenie Tap&Hold). Moim zdaniem jest to dość uciążliwe, w pewnych przypadkach pojawiające się ContextMenu jest wysoce niepożądane. Jako że potrzeba matką wynalazków postanowiłem sam zmierzyć sie z tematem i potyczka ta została zakończona sukcesem
Całość zagadnienia sprowadziła się do wpięcia w procedurę obsługi okna. Na początek gotowy kod.
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Dudzik.Helpers
{
public class WebBrowserExt : System.Windows.Forms.WebBrowser
{
private IntPtr child;
private static WndProcDelegate newWndProc;
private static IntPtr oldWndProc = IntPtr.Zero, oldSipProc = IntPtr.Zero;
internal const int GWL_WNDPROC = -4;
internal const int WM_LBUTTONUP = 0x0202;
[DllImport("coredll")]
extern static IntPtr GetCapture();
[DllImport("coredll.dll", EntryPoint = "GetWindow")]
private static extern IntPtr GetWindow(IntPtr handleWindow, int cmd);
[DllImport("coredll.dll", EntryPoint = "GetWindowLong")]
private static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("coredll.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr newWndProc);
[DllImport("coredll.dll")]
private static extern int PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("coredll.dll")]
private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
protected override void OnHandleCreated(EventArgs e)
{
IntPtr webHandle = GetHWND(this);
child = GetWindow(webHandle, 5);
child = GetWindow(child, 5);
child = GetWindow(child, 2);
newWndProc = new WndProcDelegate(WndProc);
oldWndProc = GetWindowLong(child, GWL_WNDPROC);
int success = SetWindowLong(child, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(newWndProc));
base.OnHandleCreated(e);
}
private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if (msg == 0x0020)
{
PostMessage(this.Handle, WM_LBUTTONUP, 0, 0);
return IntPtr.Zero;
}
return CallWindowProc(oldWndProc, child, msg, wParam, lParam);
}
private IntPtr GetHWND(Control ctl)
{
ctl.Capture = true;
IntPtr hWnd = GetCapture();
ctl.Capture = false;
return hWnd;
}
}
}
Proponuje również utworzyć odpowiedni plik xmta. Pozwoli on na bezproblemowe użycie kontrolki w Design Mode. Poniżej najprostsza zawartość pliku xmta.
<?xml version="1.0" encoding="utf-16"?>
<Classes xmlns="http://schemas.microsoft.com/VisualStudio/2004/03/SmartDevices/XMTA.xsd">
<Class Name="Dudzik.Helpers.WebBrowserExt">
<DesktopCompatible>true</DesktopCompatible>
<Property Name="Size">
<DefaultValue>
<Type>
System.Drawing.Size, System.Drawing, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
</Type>
<Value>
240; 100
</Value>
</DefaultValue>
</Property>
</Class>
</Classes>