|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionNearly, in one of my .NET Compact Framework 2.0 projects, I want to use the WebBrowser Control to display rich-media content. Unfortunately, the WebBrowser control in the .NET CF is not as powerful as the .NET Framework's control. It does not have some of useful interfaces, especially it does not support DOM model... My requirements for the control are:
Background
In the .NET Framework, using the The idea to solve the problem: derive the WebBrowser control, and hook all of mouse events which occur inside the control. Thanks to OpenNETCF's But, when click on the WebBrowser, which is the child window receive these messages? Not a problem! Using the Remote Spy utility (in the Visual Studio Remote Tools), we can see a grandchild window of the WebBrowser control. This window belongs to
ImplementationThere are only approximate 100 lines of code in theWebBrowserEx class, so I paste all here.using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using OpenNETCF.Windows.Forms;
using OpenNETCF.Win32;
using Microsoft.WindowsCE.Forms;
namespace webBrowserEx
{
/// <summary>
/// An extended WebBrowser, can handle Mouse Events.
/// </summary>
public class WebBrowserEx : System.Windows.Forms.WebBrowser, IMessageFilter
{
public WebBrowserEx()
{
//Initialize Message Filter, using OpenNETCF's ApplicationEx
OpenNETCF.Windows.Forms.ApplicationEx.AddMessageFilter(this);
}
#region ------ IMessageFilter implementation ------
public bool PreFilterMessage(ref Message m)
{
if ((m.Msg == (int)WM.LBUTTONDOWN || m.Msg == (int)WM.LBUTTONUP || m.Msg == (int)WM.MOUSEMOVE)
&& IsChildestWindow(this.Handle, m.HWnd))
{
int xPos = (int)m.LParam & 0xFFFF;
int yPos = ((int)m.LParam >> 16) & 0xFFFF;
MouseEventArgs e = new MouseEventArgs(MouseButtons.Left, 1,
xPos, yPos, 0);
switch (m.Msg)
{
case (int)WM.LBUTTONUP:
base.OnMouseUp(e);
break;
case (int)WM.LBUTTONDOWN:
base.OnMouseDown(e);
break;
case (int)WM.MOUSEMOVE:
base.OnMouseMove(e);
break;
}
}
return false;
}
#endregion
#region ------- Private functions -----------------
/// <summary>
/// Check whether <see cref="hCheck"/> is one of <see cref="hWnd"/>'s grandchildren.
/// </summary>
/// <param name="hWnd"></param>
/// <param name="hCheck"></param>
/// <returns></returns>
private static bool IsChildestWindow(IntPtr hWnd, IntPtr hCheck)
{
IntPtr ret = hWnd;
//Find the first "smallest" child
while ((hWnd = GetWindow(hWnd, (int)GetWindowFlags.GW_CHILD)) != IntPtr.Zero)
{
ret = hWnd;
}
//goes through all of "smallest" grandchildren
hWnd = ret;
while ((ret != hCheck) &&
((hWnd = GetWindow(ret, (int)GetWindowFlags.GW_HWNDNEXT)) != IntPtr.Zero))
{
ret = hWnd;
}
return (hWnd != IntPtr.Zero);
}
#endregion
#region -------- P/Invoke declerations ------------
/// <summary>
/// Get relative window with a given window.
/// </summary>
/// <param name="hwnd">the Given window</param>
/// <param name="cmd">an <see cref="GetWindowFlags"/> value, indicates the relation.</param>
/// <returns></returns>
[DllImport("coredll.dll")]
private static extern IntPtr GetWindow(IntPtr hwnd, int cmd);
private enum GetWindowFlags : int
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_MAX = 5
}
#endregion
}
}
The implementation is so easy. Whenever receiving a WM_MOUSEMOVE, WM_LBUTTONUP, WM_LBUTTONDOWN message, we will check if the static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[MTAThread]
static void Main()
{
// Instead of using Application class,
// we use OpenNETCF's ApplicationEx which enables MessageFilter.
OpenNETCF.Windows.Forms.ApplicationEx.Run(new Form1());
//Application.Run(new Form1());
}
}
Points of Interest
Through the years, I learn a lot of interesting things from CodeProject, but this is my first article, with a shy code... So, feel free to comment and... ^^. Sorry for my English, it's not my mother language. History
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||