Blokada ContextMenu na komponencie WebBrowser

Adam Dudzik | .NET Compact Framework, Informatyka, Urządzenia mobilne | 19 grudnia 2009

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>

Polski Wordpress
Oparte na WordPress | Theme by Roy Tanck. Tłumaczenia dokonał azWeb dla Polski support WordPress