开发者

How to log name/path of clicked control in WPF?

开发者 https://www.devze.com 2023-02-17 07:22 出处:网络
I use the following code to log every click in our WinForms application.In essence it looks up a control from its HWND and then prints the types and names of the control and all of its parents. Someth

I use the following code to log every click in our WinForms application. In essence it looks up a control from its HWND and then prints the types and names of the control and all of its parents. Something like MainForm"myWindow">TabPanel"mainTab">Button"save"

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);
        }
    }
}

Recently we've started to mix WPF and WinForms and the above click logger simply prints "Unknown" for any click on a WPF control.

Is there a way I can perform a similar trick for WPF controls? A method that would work across technologies would be great.


well, it doesn't exactly work across technologies but for wpf you can use a combination of this to get the clicks and any of the helpers in this question to cycle through the parents to get the path.

0

精彩评论

暂无评论...
验证码 换一张
取 消