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

前言:本店绝不含地沟油
顾客:“老板,你这油怎么这么亮呀,跟我平常吃的不一样,不会是地沟油吧?”
回答:“你平常吃的是地沟油!”
继续缅怀逝去的程序员生涯
倒腾WinForm, 是这样的俺想做个方便的类来控制其他程序的窗口,具体就是操作句柄。
这里以改变窗口的输入框(Text)举例,其他自己搞吧,就是调用WinAPI。

实现过程:
过程一:找到当前鼠标位置的句柄
您的使用2个WinAPI(俺喜欢自己封装下来用):
写个类操作窗口(句柄操作)窗口句柄写个类操作窗口(句柄操作)窗口句柄View Code [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); } /// /// 找到句柄 /// /// 坐标
/// public static IntPtr GetHandle(Point p) { return WindowFromPoint(p); }

过程二:改变窗口的Text
您的使用1个WinAPI:
View Code [DllImport("user32.dll", EntryPoint = "SendMessage")] private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam); /// /// 给窗口发送内容 /// /// 句柄
/// 要发送的内容
public static void SetText(IntPtr hWnd, string lParam) { SendMessage(hWnd, WM_SETTEXT, IntPtr.Zero, lParam); } private const int WM_SETTEXT = 0x000C;
通过这个方法就能改变Text的值了。

思考:如果俺把这个窗口的句柄记录下来,下次不用鼠标获取,直接就能改变值不蛮好的嘛。
例如:我有个桌面系统老叫我输入用户名,密码。我记录用户名和密码的窗口句柄,然后改变他们的输入值,这样多省事。(只是举例,不考虑安全性)
问题:你会告诉我,窗口句柄的每次重建会变的呀,咋办。
回答:类名不变呀。

过程三:您的准备一些工具吧,例如:句柄找类名呀,类名找句柄什么的等等,下面会用到一些WinAPI
View Code [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); /// /// 找到句柄 /// /// 类名
/// public static IntPtr GetHandle(string IpClassName) { return FindWindow(IpClassName, null); } /// /// 子窗口句柄 /// /// 父窗口句柄
/// 前一个同目录级同名窗口句柄
/// 类名
/// public static IntPtr GetChildHandle(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass) { return FindWindowEx(hwndParent, hwndChildAfter, lpszClass, null); } /// /// 全部子窗口句柄 /// /// 父窗口句柄
/// 类名
/// public static List GetChildHandles(IntPtr hwndParent, string className) { List resultList = new List(); for (IntPtr hwndClient = GetChildHandle(hwndParent, IntPtr.Zero, className); hwndClient != IntPtr.Zero; hwndClient = GetChildHandle(hwndParent, hwndClient, className)) { resultList.Add(hwndClient); } return resultList; } /// /// 找类名 /// /// 句柄
/// 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的类,可以把他的规则,他的父窗口类名,以及在父窗口中同类名出现的顺序记录下来,然后通过这些记录的信息还原句柄。
View Code 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 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
View Code 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方法 /// /// 找到句柄 /// /// 类名
/// public static IntPtr GetHandle(string IpClassName) { return FindWindow(IpClassName, null); } /// /// 找到句柄 /// /// 坐标
/// 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); } /// /// 子窗口句柄 /// /// 父窗口句柄
/// 前一个同目录级同名窗口句柄
/// 类名
/// public static IntPtr GetChildHandle(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass) { return FindWindowEx(hwndParent, hwndChildAfter, lpszClass, null); } /// /// 全部子窗口句柄 /// /// 父窗口句柄
/// 类名
/// public static List GetChildHandles(IntPtr hwndParent, string className) { List resultList = new List(); for (IntPtr hwndClient = GetChildHandle(hwndParent, IntPtr.Zero, className); hwndClient != IntPtr.Zero; hwndClient = GetChildHandle(hwndParent, hwndClient, className)) { resultList.Add(hwndClient); } return resultList; } /// /// 给窗口发送内容 /// /// 句柄
/// 要发送的内容
public static void SetText(IntPtr hWnd, string lParam) { SendMessage(hWnd, WM_SETTEXT, IntPtr.Zero, lParam); } private const int WM_SETTEXT = 0x000C; /// /// 获得窗口内容或标题 /// /// 句柄
/// public static string GetText(IntPtr hWnd) { StringBuilder result = new StringBuilder(128); GetWindowText(hWnd, result, result.Capacity); return result.ToString(); } /// /// 找类名 /// /// 句柄
/// 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(); } /// /// 窗口在屏幕位置 /// /// 句柄
/// public static Rectangle GetWindowRect(IntPtr hWnd) { Rectangle result = default(Rectangle); GetWindowRect(hWnd, ref result); return result; } /// /// 窗口相对屏幕位置转换成父窗口位置 /// ///
///
/// public static Rectangle ScreenToClient(IntPtr hWnd, Rectangle rect) { Rectangle result = rect; ScreenToClient(hWnd, ref result); return result; } /// /// 窗口大小 /// ///
/// 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 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 } }
Tags:  什么是窗口句柄 mfc窗口句柄 获得窗口句柄 获取窗口句柄 窗口句柄

延伸阅读

最新评论

发表评论