Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable user to select control/window from another process

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

enter image description here

EDIT: 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).

like image 520
xx77aBs Avatar asked Dec 09 '22 11:12

xx77aBs


1 Answers

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

  1. To a blank Form, add a PictureBox and four Labels.
  2. Change the BorderStyle of the PictureBox to FixedSingle.
  3. Add using System.Runtime.InteropServices; up at the top of the code with the other using statements.
  4. Wire up the MouseDown(), MouseMove, and MouseUp() events of the PictureBox to the respective methods below.
  5. Run it and drag the PictureBox around the screen...

Very Rough Spy++ Example

The code:

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

}
like image 95
Idle_Mind Avatar answered Dec 11 '22 00:12

Idle_Mind