允许用户从另一个进程中选择控件/窗口

时间:2013-11-16 17:09:00

标签: c# .net winforms winapi

如何让用户从任何窗口中选择控件?像inspect.exe或WinySpy ++这样的东西可以做(见截图)。

enter image description here

编辑: 通过“选择一个控件”,我的意思是如何在鼠标指针下处理控件,以便我可以用它做一些事情(例如,在它周围绘制框,获取它的位置和名称)。我知道我需要使用WinAPI,只是不知道从哪里开始(如何在鼠标指针下处理控件)。

2 个答案:

答案 0 :(得分:11)

这是从一开始:(非常粗略,需要更多工作!)

  1. 在空白表格中添加PictureBox和四个标签。
  2. 将PictureBox的BorderStyle更改为FixedSingle。
  3. 在顶部添加using System.Runtime.InteropServices; 代码与其他using语句。
  4. 连接到的MouseDown(),MouseMove和MouseUp()事件 PictureBox以下各种方法。
  5. 运行它并在屏幕上拖动PictureBox ...
  6. Very Rough Spy++ Example

    代码:

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

答案 1 :(得分:3)

使用GetCursorPos功能获取当前光标位置。

使用WindowFromPoint获取包含指定点的窗口。

至于绘制矩形,请查看source code of WinSpy++