Windows窗体控件属性查看器:wfspy工具介绍

在Windows应用程序开发中,经常需要查看和修改窗体控件的属性。wfspy是一款功能强大的工具,它可以帮助开发者查看和编辑任何Windows窗体控件的属性。最初,开发者需要一个小工具来获取控件的类型名称和程序集名称,但随着时间的推移,wfspy逐渐发展成为一个功能更加完善的工具,可以显示所有控件的属性,并允许用户进行修改。目前,该工具尚未实现事件监听功能,但开发者计划在未来的版本中加入这一功能。

wfspy的工作原理

wfspy通过使用Windows钩子来实现其功能。该项目包含三个程序集:

  • wfspy - 这是主应用程序,包含用户界面代码,使用C#编写。
  • wfspylib - 这是一个C#类库,包含工具函数和控件。这个库被注入到窗口所属的进程中。
  • wfspyhook - 这是一个托管C++类库(.dll),包含将托管程序集注入到进程中的代码。

如何使用wfspy

wfspy工具本身非常简单。主窗口显示所有托管窗口及其层次结构,桌面窗口作为根节点。任何未托管的窗口,如果不是直接或间接托管窗口的父窗口,则不会显示在树中。托管窗口使用略有不同的图标显示。用户可以通过点击主窗体中的“详细信息”按钮来查看托管窗口的属性。这将弹出一个带有属性网格的对话框。用户甚至可以在网格中修改属性。接下来的几个部分将讨论实现的一些重要方面。

为了枚举托管窗口,wfspy使用标准的Win32 API函数EnumChildWindows。如果未托管窗口不是任何托管窗口的父窗口,则它们会被过滤出树。为了确定一个窗口是否托管,需要检查其类名。任何从System.Windows.Forms.Control派生的托管窗口的类名格式为WindowsForms10.<字符序列>.app<应用程序域的哈希码>。中间的字符序列是正在被超类的窗口的类名,例如Button、SysListView32等。以下代码用于确定类名是否为托管。

private static Regex classNameRegex = new Regex(@"WindowsForms10\..*\.app[\da-eA-E]*$", RegexOptions.Singleline); public static bool IsDotNetWindow(string className) { Match match = classNameRegex.Match(className); return (match.Success); }

.NET程序集注入到另一个进程中需要一些技巧,因为与常规Win32 DLL中的函数不同,.NET函数在运行时被编译成原生代码,因此地址不是静态的。这个问题可以通过使用托管C++来解决,它允许从程序集中导出托管全局函数。导出的函数实际上是一个在运行时指向JIT编译器生成的代码的thunk。因此,导出的函数可以用作钩子过程。该函数可以用来加载另一个程序集。将在另一篇文章中详细介绍这种技术。

给定一个HWND,可以通过Control.FromHandle方法找到托管的Control对象。然后可以在属性网格中查看该控件对象的属性。这里有一个需要注意的问题,属性网格应该在控件对象所属的进程中创建。幸运的是,Windows允许一个进程创建子窗口到属于另一个进程的父窗口。这种技术被用来从目标进程创建属性网格,作为wfspy进程中一个窗体的子窗口。为了实现这一点,属性网格控件被放置在一个用户控件中。用户控件的CreateParams属性被覆盖。

protected override CreateParams CreateParams { get { System.Windows.Forms.CreateParams cp = base.CreateParams; cp.Parent = parentWindow; RECT rc = new RECT(); UnmanagedMethods.GetClientRect(parentWindow, ref rc); cp.X = rc.left; cp.Y = rc.top; cp.Width = rc.right - rc.left; cp.Height = rc.bottom - rc.top; return cp; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485