• 写个类操作窗口(句柄操作)


     

    写个类操作窗口(句柄操作)

    前言:本店绝不含地沟油

    顾客:“老板,你这油怎么这么亮呀,跟我平常吃的不一样,不会是地沟油吧?”

    回答:“你平常吃的是地沟油!”

    继续缅怀逝去的程序员生涯

    倒腾WinForm, 是这样的俺想做个方便的类来控制其他程序的窗口,具体就是操作句柄。

    这里以改变窗口的输入框(Text)举例,其他自己搞吧,就是调用WinAPI。

    实现过程:

    过程一:找到当前鼠标位置的句柄

    您的使用2个WinAPI(俺喜欢自己封装下来用):

    [DllImport("user32.dll", EntryPoint = "GetCursorPos")]
    public static extern bool GetCursorPos(out Point pt);

    [DllImport("user32.dll", EntryPoint = "WindowFromPoint")]
    public static extern IntPtr WindowFromPoint(Point pt);

    //鼠标位置的坐标
    public static Point GetCursorPosPoint()
    {
    Point p = new Point();
    if (GetCursorPos(out p))
    {
    return p;
    }
    return default(Point);
    }

    ///<summary>
    /// 找到句柄
    ///</summary>
    ///<param name="p">坐标</param>
    ///<returns></returns>
    public static IntPtr GetHandle(Point p)
    {
    return WindowFromPoint(p);
    }

    过程二:改变窗口的Text

    您的使用1个WinAPI:

    [DllImport("user32.dll", EntryPoint = "SendMessage")]
            private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);
    
            ///<summary>
            /// 给窗口发送内容
            ///</summary>
            ///<param name="hWnd">句柄</param>
            ///<param name="lParam">要发送的内容</param>
            public static void SetText(IntPtr hWnd, string lParam)
            {
                SendMessage(hWnd, WM_SETTEXT, IntPtr.Zero, lParam);
            }
            private const int WM_SETTEXT = 0x000C;
    
    

    通过这个方法就能改变Text的值了。




    思考:如果俺把这个窗口的句柄记录下来,下次不用鼠标获取,直接就能改变值不蛮好的嘛。

    例如:我有个桌面系统老叫我输入用户名,密码。我记录用户名和密码的窗口句柄,然后改变他们的输入值,这样多省事。(只是举例,不考虑安全性)

    问题:你会告诉我,窗口句柄的每次重建会变的呀,咋办。

    回答:类名不变呀。




    过程三:您的准备一些工具吧,例如:句柄找类名呀,类名找句柄什么的等等,下面会用到一些WinAPI

     [DllImport("user32.dll", EntryPoint = "FindWindow")]
            private static extern IntPtr FindWindow(string IpClassName, string IpWindowName);
    
            [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
            private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
    
            [DllImport("user32.dll", EntryPoint = "GetParent")]
            public static extern IntPtr GetParent(IntPtr hWnd);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    
            ///<summary>
            /// 找到句柄
            ///</summary>
            ///<param name="IpClassName">类名</param>
            ///<returns></returns>
            public static IntPtr GetHandle(string IpClassName)
            {
                return FindWindow(IpClassName, null);
            }
    
            ///<summary>
            /// 子窗口句柄
            ///</summary>
            ///<param name="hwndParent">父窗口句柄</param>
            ///<param name="hwndChildAfter">前一个同目录级同名窗口句柄</param>
            ///<param name="lpszClass">类名</param>
            ///<returns></returns>
            public static IntPtr GetChildHandle(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass)
            {
                return FindWindowEx(hwndParent, hwndChildAfter, lpszClass, null);
            }
    
            ///<summary>
            /// 全部子窗口句柄
            ///</summary>
            ///<param name="hwndParent">父窗口句柄</param>
            ///<param name="className">类名</param>
            ///<returns></returns>
            public static List<IntPtr> GetChildHandles(IntPtr hwndParent, string className)
            {
                List<IntPtr> resultList = new List<IntPtr>();
                for (IntPtr hwndClient = GetChildHandle(hwndParent, IntPtr.Zero, className); hwndClient != IntPtr.Zero; hwndClient = GetChildHandle(hwndParent, hwndClient, className))
                {
                    resultList.Add(hwndClient);
                }
    
                return resultList;
            }
    
            ///<summary>
            /// 找类名
            ///</summary>
            ///<param name="hWnd">句柄</param>
            ///<returns></returns>
            public static string GetClassName(IntPtr hWnd)
            {
                StringBuilder lpClassName = new StringBuilder(128);
                if (GetClassName(hWnd, lpClassName, lpClassName.Capacity) == 0)
                {
                    throw new Exception("not found IntPtr!");
                }
                return lpClassName.ToString();
            }
     
    
    

    思考:遍历桌面上所有的窗口,然后找类名,然后改他的Text,扯淡嘛,相同的类名太多了,找毛呀

    实现:不仅记录类名,而且记录类名在父窗口出现的位置,然后通过桌面一层层找下来,最后找到这个句柄。(虽然不是太准,但是一般的还是能解决了,如果你有什么好方式一起研究)。

    过程四:实现一个WinHWND的类,可以把他的规则,他的父窗口类名,以及在父窗口中同类名出现的顺序记录下来,然后通过这些记录的信息还原句柄。

    public class WinHWND
        {
            public IntPtr HWND { get; set; }
            public string ClassName { get; set; }
            public WinHWND Parent { get; set; }
            public int InParentSequence { get; set; }
    
            private WinHWND() { }
    
            public WinHWND(IntPtr hWnd)
            {
                this.HWND = hWnd;
                this.ClassName = GetClassName();
                this.Parent = GetParent();
                this.InParentSequence = GetInParentSequence();
            }
    
            private string GetClassName()
            {
                return WinAPI.GetClassName(this.HWND);
            }
            private WinHWND GetParent()
            {
                if (WinAPI.GetParent(this.HWND) == null)
                {
                    throw new Exception("not found IntPtr!");
                }
    
                if (WinAPI.GetParent(this.HWND) == IntPtr.Zero)
                {
                    return null;
                }
    
                return new WinHWND(WinAPI.GetParent(this.HWND));
            }
            private int GetInParentSequence()
            {
                IntPtr IntprtParent = this.Parent == null ? IntPtr.Zero : this.Parent.HWND;
                return WinAPI.GetChildHandles(IntprtParent, this.ClassName).IndexOf(this.HWND);
            }
    
            public override string ToString()
            {
                StringBuilder result = new StringBuilder();
                for (WinHWND winHandle = this; winHandle != null; winHandle = winHandle.Parent)
                {
                    result.Append(string.Format("{0}:{1};", Escape(winHandle.ClassName), winHandle.InParentSequence.ToString()));
                    if (winHandle.InParentSequence == -1) break;
                }
                return result.ToString().TrimEnd(';');
            }
    
            private static string GetBaseMark(string sMark)
            {
                string[] sMarks = sMark.Split(';');
                return sMarks[sMarks.Length - 1].Split(':')[0];
            }
    
            private static string[] GetChildMarks(string sMark)
            {
                string[] sMarks = sMark.Split(';');
                string[] sChildMarks = new string[sMarks.Length - 1];
                for (int i = 0; i < sChildMarks.Length; i ++ )
                {
                    sChildMarks[i] = sMarks[i ];
                }
                return sChildMarks;
            }
    
            //我一直觉得这段写很丑陋,谁能帮帮我改改
            public static WinHWND GetWinHWND(string sMark)
            {
                List<IntPtr> baseHwnds = WinAPI.GetChildHandles(IntPtr.Zero, GetBaseMark(sMark));
                string[] sChildMarks = GetChildMarks(sMark);
                //由于主窗口在桌面出现所以很可能同名,所以要看看他的儿子和孙子...是不是都匹配
                foreach (IntPtr baseHwnd in baseHwnds)
                {
                    IntPtr handle = baseHwnd;
                    for (int i = sChildMarks.Length - 1; i >= 0; i--)
                    {
                        string[] sChildMark = sChildMarks[i].Split(':');
                        try
                        {
                            handle = WinAPI.GetChildHandles(handle, UnEscape(sChildMark[0]))[int.Parse(sChildMark[1])];
                        }
                        catch
                        {
                            break;
                        }
    
                        if (i == 0) return new WinHWND(handle);
                    }
                    continue;
                }
    
                return null;
            }
    
            #region 转义
            private static string Escape(string arg)
            {
                return arg.Replace(":", "\\:").Replace(";","\\;");
            }
    
            private static string UnEscape(string arg)
            {
                return arg.Replace("\\:", ":").Replace("\\;", ";");
            }
            #endregion
    
            public static WinHWND GetWinHWND()
            {
                return new WinHWND(WinAPI.GetHandle(WinAPI.GetCursorPosPoint()));
            }
        }

    上全部代码,里面加了窗口的部分属性,扩展其他的属性,自己发挥吧,就是搞WinAPI

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Drawing;
    using System.Collections;
    
    namespace InformationCollectionDataFill
    {
        public class WinAPI
        {
            #region WinodwsAPI
            [DllImport("user32.dll", EntryPoint = "FindWindow")]
            private static extern IntPtr FindWindow(string IpClassName, string IpWindowName);
    
            [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
            private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
    
            [DllImport("user32.dll", EntryPoint = "SendMessage")]
            private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);
    
            [DllImport("user32.dll", EntryPoint = "GetParent")]
            public static extern IntPtr GetParent(IntPtr hWnd);
    
            [DllImport("user32.dll", EntryPoint = "GetCursorPos")]
            public static extern bool GetCursorPos(out Point pt);
    
            [DllImport("user32.dll", EntryPoint = "WindowFromPoint", CharSet = CharSet.Auto, ExactSpelling = true)]
            public static extern IntPtr WindowFromPoint(Point pt);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern int GetWindowRect(IntPtr hwnd, ref Rectangle rc);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern int GetClientRect(IntPtr hwnd, ref Rectangle rc);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern int MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
            public static extern int ScreenToClient(IntPtr hWnd, ref Rectangle rect);
            #endregion
    
            #region 封装API方法
            ///<summary>
            /// 找到句柄
            ///</summary>
            ///<param name="IpClassName">类名</param>
            ///<returns></returns>
            public static IntPtr GetHandle(string IpClassName)
            {
                return FindWindow(IpClassName, null);
            }
    
            ///<summary>
            /// 找到句柄
            ///</summary>
            ///<param name="p">坐标</param>
            ///<returns></returns>
            public static IntPtr GetHandle(Point p)
            {
                return WindowFromPoint(p);
            }
    
            //鼠标位置的坐标
            public static Point GetCursorPosPoint()
            {
                Point p = new Point();
                if (GetCursorPos(out p))
                {
                    return p;
                }
                return default(Point);
            }
    
            ///<summary>
            /// 子窗口句柄
            ///</summary>
            ///<param name="hwndParent">父窗口句柄</param>
            ///<param name="hwndChildAfter">前一个同目录级同名窗口句柄</param>
            ///<param name="lpszClass">类名</param>
            ///<returns></returns>
            public static IntPtr GetChildHandle(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass)
            {
                return FindWindowEx(hwndParent, hwndChildAfter, lpszClass, null);
            }
    
            ///<summary>
            /// 全部子窗口句柄
            ///</summary>
            ///<param name="hwndParent">父窗口句柄</param>
            ///<param name="className">类名</param>
            ///<returns></returns>
            public static List<IntPtr> GetChildHandles(IntPtr hwndParent, string className)
            {
                List<IntPtr> resultList = new List<IntPtr>();
                for (IntPtr hwndClient = GetChildHandle(hwndParent, IntPtr.Zero, className); hwndClient != IntPtr.Zero; hwndClient = GetChildHandle(hwndParent, hwndClient, className))
                {
                    resultList.Add(hwndClient);
                }
    
                return resultList;
            }
    
            ///<summary>
            /// 给窗口发送内容
            ///</summary>
            ///<param name="hWnd">句柄</param>
            ///<param name="lParam">要发送的内容</param>
            public static void SetText(IntPtr hWnd, string lParam)
            {
                SendMessage(hWnd, WM_SETTEXT, IntPtr.Zero, lParam);
            }
            private const int WM_SETTEXT = 0x000C;
    
            ///<summary>
            /// 获得窗口内容或标题
            ///</summary>
            ///<param name="hWnd">句柄</param>
            ///<returns></returns>
            public static string GetText(IntPtr hWnd)
            {
                StringBuilder result = new StringBuilder(128);
                GetWindowText(hWnd, result, result.Capacity);
                return result.ToString();
            }
    
            ///<summary>
            /// 找类名
            ///</summary>
            ///<param name="hWnd">句柄</param>
            ///<returns></returns>
            public static string GetClassName(IntPtr hWnd)
            {
                StringBuilder lpClassName = new StringBuilder(128);
                if (GetClassName(hWnd, lpClassName, lpClassName.Capacity) == 0)
                {
                    throw new Exception("not found IntPtr!");
                }
                return lpClassName.ToString();
            }
    
            ///<summary>
            /// 窗口在屏幕位置
            ///</summary>
            ///<param name="hWnd">句柄</param>
            ///<returns></returns>
            public static Rectangle GetWindowRect(IntPtr hWnd)
            {
                Rectangle result = default(Rectangle);
                GetWindowRect(hWnd, ref result);
                return result;
            }
    
            ///<summary>
            /// 窗口相对屏幕位置转换成父窗口位置
            ///</summary>
            ///<param name="hWnd"></param>
            ///<param name="rect"></param>
            ///<returns></returns>
            public static Rectangle ScreenToClient(IntPtr hWnd, Rectangle rect)
            {
                Rectangle result = rect;
                ScreenToClient(hWnd, ref result);
                return result;
            }
    
            ///<summary>
            /// 窗口大小
            ///</summary>
            ///<param name="hWnd"></param>
            ///<returns></returns>
            public static Rectangle GetClientRect(IntPtr hWnd)
            {
                Rectangle result = default(Rectangle);
                GetClientRect(hWnd, ref result);
                return result;
            }
            #endregion
        }
    
        public class WinHWND
        {
            public IntPtr HWND { get; set; }
            public string ClassName { get; set; }
            public WinHWND Parent { get; set; }
            public int InParentSequence { get; set; }
    
            private Rectangle _currentRect;
            private string _Text;
            private int _Left;
            private int _Top;
            private int _Width;
            private int _Height;
    
            public string Text
            {
                get
                {
                    return _Text == default(string) ? WinAPI.GetText(this.HWND) : _Text;
                }
                set
                {
                    _Text = value;
                    WinAPI.SetText(this.HWND, value);
                }
            }
            public int Left
            {
                get
                {
                    return _Left == default(int) ? _currentRect.Left : _Left;
                }
                set
                {
                    _Left = value;
                    WinAPI.MoveWindow(this.HWND, value, this.Top, this.Width, this.Height, true);
                }
            }
            public int Top
            {
                get
                {
                    return _Top == default(int) ? _currentRect.Top : _Top;
                }
                set
                {
                    _Top = value;
                    WinAPI.MoveWindow(this.HWND, this.Left, value, this.Width, this.Height, true);
                }
            }
            public int Width
            {
                get
                {
                    return _Width == default(int) ? _currentRect.Width : _Width;
                }
                set
                {
                    _Width = value;
                    WinAPI.MoveWindow(this.HWND, this.Left, this.Top, value, this.Height, true);
                }
            }
            public int Height
            {
                get
                {
                    return _Height == default(int) ? _currentRect.Height : _Height;
                }
                set
                {
                    _Height = value;
                    WinAPI.MoveWindow(this.HWND, this.Left, this.Top, this.Width, value, true);
                }
            }
    
            private WinHWND() { }
            public WinHWND(IntPtr hWnd)
            {
                this.HWND = hWnd;
                this.ClassName = GetClassName();
                this.Parent = GetParent();
                this.InParentSequence = GetInParentSequence();
                this._currentRect = GetRect();
            }
    
            private string GetClassName()
            {
                return WinAPI.GetClassName(this.HWND);
            }
            private WinHWND GetParent()
            {
                if (WinAPI.GetParent(this.HWND) == null)
                {
                    throw new Exception("not found IntPtr!");
                }
    
                if (WinAPI.GetParent(this.HWND) == IntPtr.Zero)
                {
                    return null;
                }
    
                return new WinHWND(WinAPI.GetParent(this.HWND));
            }
            private int GetInParentSequence()
            {
                IntPtr IntprtParent = this.Parent == null ? IntPtr.Zero : this.Parent.HWND;
                return WinAPI.GetChildHandles(IntprtParent, this.ClassName).IndexOf(this.HWND);
            }
            private Rectangle GetRect()
            {
                if (this.Parent == null) return default(Rectangle);
                Rectangle clientSize = WinAPI.GetClientRect(this.HWND);
                Rectangle clientPoint = WinAPI.ScreenToClient(this.Parent.HWND, WinAPI.GetWindowRect(this.HWND));
                return new Rectangle(clientPoint.X, clientPoint.Y, clientSize.Width, clientSize.Height);
            }
    
            public static WinHWND GetWinHWND()
            {
                return new WinHWND(WinAPI.GetHandle(WinAPI.GetCursorPosPoint()));
            }
    
            public override string ToString()
            {
                StringBuilder result = new StringBuilder();
                for (WinHWND winHandle = this; winHandle != null; winHandle = winHandle.Parent)
                {
                    result.Append(string.Format("{0}:{1};", Escape(winHandle.ClassName), winHandle.InParentSequence.ToString()));
                    if (winHandle.InParentSequence == -1) break;
                }
                return result.ToString().TrimEnd(';');
            }
    
            private static string GetBaseMark(string sMark)
            {
                string[] sMarks = sMark.Split(';');
                return sMarks[sMarks.Length - 1].Split(':')[0];
            }
    
            private static string[] GetChildMarks(string sMark)
            {
                string[] sMarks = sMark.Split(';');
                string[] sChildMarks = new string[sMarks.Length - 1];
                for (int i = 0; i < sChildMarks.Length; i ++ )
                {
                    sChildMarks[i] = sMarks[i];
                }
                return sChildMarks;
            }
    
            //我一直觉得这段写很丑陋,谁能帮帮我改改
            public static WinHWND GetWinHWND(string sMark)
            {
                List<IntPtr> baseHwnds = WinAPI.GetChildHandles(IntPtr.Zero, GetBaseMark(sMark));
                string[] sChildMarks = GetChildMarks(sMark);
                //由于主窗口在桌面出现所以很可能同名,所以要看看他的儿子和孙子...是不是都匹配
                foreach (IntPtr baseHwnd in baseHwnds)
                {
                    IntPtr handle = baseHwnd;
                    for (int i = sChildMarks.Length - 1; i >= 0; i--)
                    {
                        string[] sChildMark = sChildMarks[i].Split(':');
                        try
                        {
                            handle = WinAPI.GetChildHandles(handle, UnEscape(sChildMark[0]))[int.Parse(sChildMark[1])];
                        }
                        catch
                        {
                            break;
                        }
    
                        if (i == 0) return new WinHWND(handle);
                    }
                    continue;
                }
    
                return null;
            }
    
            #region 转义
            private static string Escape(string arg)
            {
                return arg.Replace(":", "\\:").Replace(";","\\;");
            }
    
            private static string UnEscape(string arg)
            {
                return arg.Replace("\\:", ":").Replace("\\;", ";");
            }
            #endregion
        }
    }
    
    
    

    Demo.rar效果:

     
     
     
     
    转自:http://jgr8224.blog.163.com/blog/static/1686849201163144913579/
     
     
  • 相关阅读:
    js遍历多层对象的键值对
    JS HEX十六进制与RGB, HSL颜色的相互转换【转】
    TortoiseSVN打分支、合并分支、切换分支【转】
    grid.containLabel
    安装谷歌vue-devtools调试插件
    使用Echarts遇到的问题
    理解js编程中函数的副作用
    git 镜像下载和安装
    欢迎来到博客园的世界
    c#制作一个屏幕保护程序
  • 原文地址:https://www.cnblogs.com/xiurui12345/p/3006678.html
Copyright © 2020-2023  润新知