我使用以下代码记录 WinForms 应用程序中的每次点击。本质上,它从 HWND 中查找控件,然后打印控件及其所有父项的类型和名称。类似 MainForm“myWindow”> TabPanel“mainTab”>按钮“保存”
internal class ClickLogger : IMessageFilter
{
private const int WM_LBUTTONDOWN = 0x0201;
private const int WM_LBUTTONDBLCLK = 0x0203;
private const int WM_RBUTTONDOWN = 0x0204;
private const int MaxRecurseDepth = 30;
private readonly ILogger _log;
public ClickLogger(ILogger logger)
{
_log = logger;
}
[DebuggerStepThrough]
public bool PreFilterMessage(ref Message message)
{
if (message.Msg == WM_LBUTTONDOWN
|| message.Msg == WM_RBUTTONDOWN
|| message.Msg == WM_LBUTTONDBLCLK)
{
string path = "Unknown";
Control ctl = Control.FromHandle(message.HWnd);
if (ctl != null)
{
path = PathFromControl(ctl, MaxRecurseDepth).ToString();
}
string logEntry = string.Format("{0} Click on {1}",
WndMsgToClickName(message.Msg), path);
if (_log.IsInfoEnabled)
{
_log.Info(logEntry);
}
}
return false;
}
private StringBuilder PathFromControl(Control control, int maxDepth)
{
if(maxDepth == 0)
{
_log.Warn("Max recursion {0} reached whilst resolving path of control", MaxRecurseDepth);
return new StringBuilder("ERR");
}
string name = control.GetType().Name;
if (control.Name.IsNotBlank())
{
name = name + "\"" + control.Name + "\"";
}
if (control.Parent != null && control.Parent != control)
{
return PathFromControl(control.Parent, maxDepth - 1).Append(">").Append(name);
}
return new StringBuilder(name);
}
public void Initialize()
{
Application.AddMessageFilter(this);
}
private static string WndMsgToClickName(int msgId)
{
switch (msgId)
{
case WM_LBUTTONDOWN:
return "Left";
case WM_LBUTTONDBLCLK:
return "Double";
case WM_RBUTTONDOWN:
return "Right";
default:
return "0x" + Convert.ToString(msgId, 16);
}
}
}
最近我们开始混合使用 WPF 和 WinForms ,上面的点击记录器只是为 WPF上的任何点击打印“未知”控制。
有没有办法可以为 WPF 控件执行类似的技巧?一种跨技术的方法会很棒。