zoukankan      html  css  js  c++  java
  • C# 依据鼠标坐标取网页内成员坐标.ie

    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('', 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");
  • 相关阅读:
    dp(传球)
    最长上升子序列
    FromData获取表单数据
    php解决高并发问题
    php抽象类、接口、traint详解
    mysql、mongodb、redis 数据库之间的区别
    phpstorm2018 安装及破解方法
    phpstudy添加redis扩展
    mysql触发器trigger 实例详解
    mysql查询系列常考问题
  • 原文地址:https://www.cnblogs.com/sanler/p/7474311.html
Copyright © 2011-2022 走看看