在Windows操作系统中,应用程序可以包含许多控件窗口。了解并调试这些控件对于开发人员和系统管理员来说是非常有价值的。本文将介绍如何使用C#和Windows Forms构建一个工具,可以列出正在运行的带窗口的进程,并显示其窗口控件的详细信息,包括它们的句柄、类名和文本内容。
首先,我们需要在Visual Studio中创建一个新的Windows Forms项目。
在设计界面上,我们将需要以下控件:
ListBox
控件,用于显示进程列表。将其命名为 btnGetInfo
。Button
按钮,用于触发获取控件信息的操作。将其命名为 buttonGetControls
,并设置文本为“获取控件信息”。TextBox
控件,用于显示控件的详细信息。将其命名为 txtMsg
,并设置 Multiline
属性为 true
。我们需要引入一些 Windows API 函数,以便获取窗口的句柄、文本和类名。
在代码顶部引入以下命名空间:
C#using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
然后,添加需要的P/Invoke声明:
C#[DllImport("user32.dll", SetLastError = true)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
// Windows API declarations
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
[DllImport("user32.dll")]
static extern bool IsWindowVisible(IntPtr hWnd);
private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr lParam);
我们需要编写代码来加载当前正在运行的进程,以及遍历每个窗体控件并获取其详细信息。
加载进程列表:
在 MainForm
类中添加以下方法,用于加载带窗口的进程:
C#private void LoadProcesses()
{
lstProcess.Items.Clear();
Process[] processes = Process.GetProcesses();
foreach (Process proc in processes)
{
if (proc.MainWindowHandle != IntPtr.Zero)
{
lstProcess.Items.Add(new ListItem(proc.ProcessName, proc.MainWindowHandle));
}
}
lstProcess.DisplayMember = "Name";
}
C#public class ListItem
{
public string Name { get; }
public IntPtr WindowHandle { get; }
public ListItem(string name, IntPtr windowHandle)
{
Name = name;
WindowHandle = windowHandle;
}
public override string ToString()
{
return Name;
}
}
获取并显示控件信息:
C#private void btnGetInfo_Click(object sender, EventArgs e)
{
if (lstProcess.SelectedItem != null)
{
ListItem selectedItem = (ListItem)lstProcess.SelectedItem;
IntPtr hwnd = selectedItem.WindowHandle;
txtMsg.Clear();
TraverseControls(hwnd, 0);
}
}
private void TraverseControls(IntPtr hWnd, int indentLevel)
{
if (IsWindowVisible(hWnd))
{
StringBuilder sbText = new StringBuilder(256);
StringBuilder sbClass = new StringBuilder(256);
GetWindowText(hWnd, sbText, sbText.Capacity);
GetClassName(hWnd, sbClass, sbClass.Capacity);
string indent = new string(' ', indentLevel * 2);
txtMsg.AppendText($"{indent}Handle: {hWnd}, Class: {sbClass}, Text: {sbText}\r\n");
EnumChildWindows(hWnd, (childHWnd, lParam) =>
{
TraverseControls(childHWnd, indentLevel + 1);
return true;
}, IntPtr.Zero);
}
}
通过上述步骤,我们构建了一个功能齐全的WinForms应用程序,能够列出正在运行的带窗口的进程,并显示其窗口所有控件的详细信息。
如果您有任何问题或进一步的需求,请随时告诉我!
本文作者:rick
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!