允许用户从另一个进程中选择控件/窗口 [英] Enable user to select control/window from another process

查看:35
本文介绍了允许用户从另一个进程中选择控件/窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用户能够从任何窗口中选择控件?诸如inspect.exe或WinySpy ++之类的东西都可以做(请参见屏幕截图).

How can I enable user to select a control from any window? Something like inspect.exe or WinySpy++ can do (see screenshot).

所谓选择控件",是指如何在鼠标指针下获取控件的句柄,以便随后对其进行处理(例如,在其周围绘制框,获取其位置和名称).我知道我需要使用WinAPI,只是不知道从哪里开始(如何在鼠标指针下获取控件的句柄).

By "select a control" I mean how can I get handle of the control under the mouse pointer so that I can then do something with it (e.g. draw box around it, get it's position and name). I know I need to use WinAPI, just don't know where to start (how to get handle of the control under the mouse pointer).

推荐答案

从这里开始:(这非常粗糙,需要做更多的工作!)

Here's something to start from: (this is very rough and needs more work!)

  1. 在空白表单中,添加一个PictureBox和四个标签.
  2. 将PictureBox的BorderStyle更改为FixedSingle.
  3. 使用System.Runtime.InteropServices; 添加与其他 using 语句一起编码.
  4. 连接以下事件的MouseDown(),MouseMove和MouseUp()事件:PictureBox下面的相应方法.
  5. 运行它并将PictureBox拖动到屏幕周围...

代码:

public partial class Form1 : Form
{

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    public const int WM_GETTEXT = 0xD;
    public const int WM_GETTEXTLENGTH = 0x000E;

    [DllImport("user32.dll")]
    public static extern IntPtr WindowFromPoint(Point point);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int GetClassName(IntPtr handle, StringBuilder ClassName, int MaxCount);

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr handle, int msg, int Param1, int Param2);

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr handle, int msg, int Param, System.Text.StringBuilder text);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetWindowRect(IntPtr handle, out RECT Rect);

    public class WindowInfo
    {
        public IntPtr Handle;
        public string ClassName;
        public string Text;
        public Rectangle Rect;

        public WindowInfo(IntPtr Handle)
        {
            this.Handle = Handle;
            this.ClassName = GetWindowClassName(Handle);
            this.Text = GetWindowText(Handle);
            this.Rect = GetWindowRectangle(Handle);
        }
    }

    WindowInfo LastWindow = null;
    WindowInfo CurWindow;

    public Form1()
    {
        InitializeComponent();
    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            pictureBox1.Cursor = Cursors.Cross;
        }
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            Point pt = Cursor.Position;
            this.Text = "Mouse Position: " + pt.ToString();
            this.CurWindow = new WindowInfo(WindowFromPoint(pt));

            label1.Text = "Handle: " + this.CurWindow.Handle.ToString("X");
            label2.Text = "Class: " + this.CurWindow.ClassName;
            label3.Text = "Text: " + this.CurWindow.Text;
            label4.Text = "Rectangle: " + this.CurWindow.Rect.ToString();

            if (this.LastWindow == null)
            {
                ControlPaint.DrawReversibleFrame(this.CurWindow.Rect, Color.Black, FrameStyle.Thick);
            }
            else if (!this.CurWindow.Handle.Equals(this.LastWindow.Handle))
            {
                ControlPaint.DrawReversibleFrame(this.LastWindow.Rect, Color.Black, FrameStyle.Thick);
                ControlPaint.DrawReversibleFrame(this.CurWindow.Rect, Color.Black, FrameStyle.Thick);                   
            }

            this.LastWindow = this.CurWindow;
        }
    }

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            pictureBox1.Cursor = Cursors.Default;
            if (this.LastWindow != null)
            {
                ControlPaint.DrawReversibleFrame(this.LastWindow.Rect, Color.Black, FrameStyle.Thick);

                // ... do something with "this.LastWindow" ...

            }
        }
    }

    public static string GetWindowClassName(IntPtr handle)
    {
        StringBuilder buffer = new StringBuilder(128);
        GetClassName(handle, buffer, buffer.Capacity);
        return buffer.ToString();
    }

    public static string GetWindowText(IntPtr handle)
    {
        StringBuilder buffer = new StringBuilder(SendMessage(handle, WM_GETTEXTLENGTH,0,0) + 1);
        SendMessage(handle, WM_GETTEXT, buffer.Capacity, buffer);
        return buffer.ToString();
    }

    public static Rectangle GetWindowRectangle(IntPtr handle)
    {
        RECT rect = new RECT();
        GetWindowRect(handle, out rect);
        return new Rectangle(rect.Left, rect.Top, (rect.Right - rect.Left) + 1, (rect.Bottom - rect.Top) + 1);
    }

}

这篇关于允许用户从另一个进程中选择控件/窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆