C# 依据鼠标坐标取网页内成员坐标.ie

2021-03-12 21:29

阅读:367

标签:classname   浏览器   spel   extern   ons   获取网页   out   win32   ring   

C# 根据鼠标坐标取网页内成员坐标.ie

有时候你需要后台获取ie浏览器 鼠标所在位置的元素坐标,然而你使用屏幕坐标是不可行的

所以我们需要把坐标转换成浏览器内坐标 然后再通过elementFromPoint获取网页成员。

 

        private void tmrWatcher_Tick(object sender, EventArgs e)
        {
            IntPtr hWnd = WindowFromPoint(MousePosition);
            dynamic document = GetHtmlDocumentByHandle(hWnd);
            if (document != null)
            {
                Rectangle r = GetHtmlElementPoint(hWnd, MousePosition, document); // 根据鼠标坐标取网页成员坐标
                Marshal.FinalReleaseComObject(document);
                Console.WriteLine(r.X + ":" + r.Y + ":" + r.Width + ":" + r.Height);
            }
        }

上面是一个时钟tmrWatcher的Tick回调函数,在上面使用了WindowFromPoint函数 主要是获取

MousePosition所在的窗口句柄,然后再通过GetHtmlDocumentByHandle函数(获取文档从句柄)

 

        public static object GetComObjectByHandle(int Msg, Guid riid, IntPtr hWnd)
        {
            object _ComObject;
            int lpdwResult = 0;
            if (!SendMessageTimeout(hWnd, Msg, 0, 0, SMTO_ABORTIFHUNG, 1000, ref lpdwResult))
                return null;
            if (ObjectFromLresult(lpdwResult, ref riid, 0, out _ComObject))
                return null;
            return _ComObject;
        }

        public object GetHtmlDocumentByHandle(IntPtr hWnd)
        {
            string buffer = new string(‘\0‘, 24);
            GetClassName(hWnd, ref buffer, 25);
            if (buffer != "Internet Explorer_Server")
                return null;
            return GetComObjectByHandle(WM_HTML_GETOBJECT, IID_IHTMLDocument, hWnd);
        }

实际上与我上次的帖子:http://blog.csdn.net/u012395622/article/details/46404193

 

并没什么太大的出入,而获取一个网页文档的成员只是简单的调度Mshtml COM接口

 

        public Rectangle GetHtmlElementPoint(IntPtr hWnd, Point point, dynamic document)
        {
            if (document == null && hWnd != IntPtr.Zero)
                return Rectangle.Empty;
            ScreenToClient(hWnd, ref point);
            dynamic element = document.elementFromPoint(point.X, point.Y);
            if (element == null) return Rectangle.Empty;
            try
            {
                Rectangle o = new Rectangle()
                {
                    Y = element.offsetTop,
                    X = element.offsetLeft,
                    Width = element.offsetWidth,
                    Height = element.offsetHeight
                };
                while (element.offsetParent != null)
                {
                    element = element.offsetParent;
                    o.Y += element.offsetTop;
                    o.X += element.offsetLeft;
                }
                return o;
            }
            catch
            {
                return Rectangle.Empty;
            }
        }

上面代码是实现获取 元素在网页内的一个确切坐标,整体并不是很难阅读的。

 

之所以while(element.offsetParent != null) { ... }是因为网页始终与客户端不相

同我们不能用常规在Win32操作控件位置那样去看待它 它很麻烦,而且层次

很难分明,所以会造成你根本不知道到底有多宽不过还好,一般计算一个

成员元素在窗口什么位置,只要把父容器的位置加起来就行了。反正有点

解释的不清楚,大家莫见怪

 

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern bool ScreenToClient(IntPtr hWnd, ref Point lpPoint);

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetClassName(
            [In]IntPtr hWnd,
            [MarshalAs(UnmanagedType.VBByRefStr)]ref string IpClassName,
            [In]int nMaxCount
            );

        [DllImport("oleacc.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool ObjectFromLresult(
            [In]int lResult,
            [In]ref Guid riid,
            [In]int wParam,
            [Out, MarshalAs(UnmanagedType.IUnknown)]out object ppvObject
            );

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.I4)]
        public static extern int RegisterWindowMessage(
            [In]string lpString
            );

        [DllImport("user32.dll", EntryPoint = "SendMessageTimeoutA", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SendMessageTimeout(
            [In]IntPtr MSG,
            [In]int hWnd,
            [In]int wParam,
            [In]int lParam,
            [In]int fuFlags,
            [In]int uTimeout,
            [In, Out]ref int lpdwResult
            );

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.SysInt)]
        public static extern IntPtr WindowFromPoint(
            [In]Point Point
            );

        public const int SMTO_ABORTIFHUNG = 2;

        public readonly static int WM_HTML_GETOBJECT = RegisterWindowMessage("WM_HTML_GETOBJECT"); 
        public readonly static Guid IID_IHTMLDocument = new Guid("626fc520-a41e-11cf-a731-00a0c9082637");

C# 依据鼠标坐标取网页内成员坐标.ie

标签:classname   浏览器   spel   extern   ons   获取网页   out   win32   ring   

原文地址:https://www.cnblogs.com/soundcode/p/12583779.html


评论


亲,登录后才可以留言!