Ukrycie paska postępu - WebBrowser, CF2.0

Adam Dudzik | .NET Compact Framework, Informatyka, Urządzenia mobilne | 1 stycznia 2010

Niejako uzupełniając zagadnienie poruszone w wpisie Blokada ContextMenu na komponencie WebBrowser chcę Wam przedstawić sposób ukrycia paska postępu ładowania strony. Pojawia się on zawsze w dolnej części komponentu WebBrowser i czasami może być denerwujący :).

Całość zagadnienia sprowadza się do wywołania funkcji DestroyWindow z biblioteki coredll.dll .

Kod wygląda następująco (podobnie jak poprzednio tworze własną kontrolkę dziedzicząc po WebBrowser - wydaje mi sie to najprostszym rozwiązaniem)

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Dudzik.Helpers
{
    public class WebBrowserExt : System.Windows.Forms.WebBrowser
    {
        private IntPtr child, pieHtml;

        [DllImport("coredll")]
        extern static IntPtr GetCapture();

        [DllImport("coredll.dll", EntryPoint = "GetWindow")]
        private static extern IntPtr GetWindow(IntPtr handleWindow, int cmd);

        [DllImport("coredll.dll")]
        private static extern bool DestroyWindow(IntPtr hwnd);  

        protected override void OnHandleCreated(EventArgs e)
        {
            IntPtr webHandle = GetHWND(this);
            child = GetWindow(webHandle, 5);
            pieHtml = GetWindow(child, 5); //MSPIE Status

            DestroyWindow(pieHtml);

            base.OnHandleCreated(e);
        }

        private IntPtr GetHWND(Control ctl)
        {
            ctl.Capture = true;
            IntPtr hWnd = GetCapture();
            ctl.Capture = false;
            return hWnd;
        }
    }
}

Oczywiście nic nie stoi na przeszkodzie by połączyć to z ukrywaniem ContextMenu. Uzyskany kod powinien  wyglądać następująco

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Dudzik.Helpers
{
    public class WebBrowserExt : System.Windows.Forms.WebBrowser
    {
        private IntPtr child, pieHtml;
        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);

        [DllImport("coredll.dll")]
        private static extern bool DestroyWindow(IntPtr hwnd);  

        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);
            pieHtml = GetWindow(child, 5); //MSPIE Status
            child = GetWindow(pieHtml, 2); //PIEHTML

            newWndProc = new WndProcDelegate(WndProc);
            oldWndProc = GetWindowLong(child, GWL_WNDPROC);
            int success = SetWindowLong(child, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(newWndProc));

            DestroyWindow(pieHtml);

            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;
        }
    }
}

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>

Nowy tutorial z serii “How do I?” Videos for Devices

Adam Dudzik | .NET Compact Framework | 23 kwietnia 2008

Na stronie “How do I?” Videos for Devices pojawił sie nowy tutorial pt. “How Do I: Use Existing COM Objects in .NET Compact Framework Applications?”

Jak wykryć uruchomienie programu na emulatorze

Adam Dudzik | .NET Compact Framework | 16 kwietnia 2008

Pisząc aplikację pod Windows Mobile testuję ją głównie pod emulatorem. Jednakże w związku z miejscem pracy :) muszę obsługiwać skaner kodów kreskowych. Oczywistym jest że Device Emulator takowego skanera nie posiada. Co za tym idzie muszę jakoś wykryć na jakim urządzeniu uruchomiony jest program. Pomaga mi w tym poniższy kawałek kodu.

[System.Runtime.InteropServices.DllImport("coredll.dll")]
private static extern int SystemParametersInfo(int uiAction, int uiParam, StringBuilder pvParam, int fWinIni);
private const int SPI_GETOEMINFO = 258;

public static string GetOemInfo()
{
	StringBuilder oemInfo = new StringBuilder(100);
	if(SystemParametersInfo(SPI_GETOEMINFO, oemInfo.Capacity, oemInfo, 0)!=0)
		return oemInfo.ToString().ToUpper();
	else
		return "";
}

I tak przykładowo terminal Symbol MC9090 zwraca ciąg SYMBOL MC9090 a Device Emulator Microsoft DeviceEmulator. Tyle mi wystarczy żeby w zależności od rodzaju urządzenia włączać lub wyłączać skaner kodów kreskowych.

Nowy tutorial z serii “How do I?” Videos for Devices

Adam Dudzik | .NET Compact Framework | 15 kwietnia 2008

Na stronie “How do I?” Videos for Devices pojawił sie nowy tutorial pt. “How Do I: Use Custom Extension Methods to Improve the Efficiency of LINQ Queries?”

MessageBeep a Compact Framework

Adam Dudzik | .NET Compact Framework | 14 marca 2008

Czasami wymagane jest aby bezduszna maszyna jaką jest terminal przenośny wydał z siebie dźwięk. W aplikacjach które pisze (aplikacje użytkowe) nie mam potrzeby odtwarzania IX Symfonii Beethovena w jakości CD-Audio toteż z powodzeniem wykorzystuję poniższą klasę.

using System;
using System.Runtime.InteropServices;

namespace Helpers
{
	class Beep
	{
		[DllImport("coredll.dll", SetLastError = true)]
		public static extern bool MessageBeep(
			MessageBeepType type
		);

		public enum MessageBeepType
		{
			Simple = -1,
			Ok = 0x00000000,
			Error = 0x00000010,
			Question = 0x00000020,
			Warning = 0x00000030,
			Information = 0x00000040
		}
	}
}

Sposób wykorzystania banalny:

Beep.MessageBeep(MessageBeepType.Ok);

Rodzaje dźwięków pobrałem stąd:

http://msdn2.microsoft.com/en-us/library/ms680356(VS.85).aspx

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