Страницы

Поиск по вопросам

воскресенье, 22 декабря 2019 г.

Как получить информацию о Windows окне под курсором мыши?

#c_sharp #winforms #winapi #interop


Как получить информацию о любом из окон Windows, которое находится под курсором мыши?
Надо реализовать часть возможностей, которые есть в утилите Microsoft Spyxx.exe и
выводить следующую иформацию: 


HWND, 
Class Name, 
Window Styles, 
RGB цвет пикселя, 
размеры окна.  


Как получить координату мыши за пределами WinForms Application?
Как получить необходимую информацию об окнах и вывести, например, в таком виде:


    


Ответы

Ответ 1



Для создания такого приложения надо использовать Win API функции для работы с окнами Windows. Позиция курсора определяется по таймеру. // Microsoft (R) Roslyn C# Compiler version 1.1.0.51204 #r "System.Windows.Forms" using System.Windows.Forms; using System.Runtime.InteropServices; using System.Drawing; using System.Reflection; // Win API functions [DllImport("user32.dll")] static extern IntPtr WindowFromPoint(Point p); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern int GetClassName(HandleRef hWnd, StringBuilder cName, int maxCount); [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern int GetWindowLong(HandleRef hWnd, int nIndex); [StructLayout(LayoutKind.Sequential)] struct RECT { public int Left; public int Top; public int Right; public int Bottom; } [DllImport("user32.dll", SetLastError = true)] static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect); [DllImport("user32.dll")] static extern bool GetClientRect(HandleRef hWnd, out RECT lpRect); [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hwnd); [DllImport("user32.dll")] static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc); [DllImport("gdi32.dll")] static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos); static public Color GetPixelColor(Point point) { var hdc = GetDC(IntPtr.Zero); var p = GetPixel(hdc, point.X, point.Y); ReleaseDC(IntPtr.Zero, hdc); return Color.FromArgb((int)(p & 0x000000FF), (int)(p & 0x0000FF00) >> 8, (int)(p & 0x00FF0000) >> 16); } [DllImport("user32")] static extern int GetWindowThreadProcessId(HandleRef hWnd, out int processId); class WindowStyles { static KeyValuePair[] enums; static WindowStyles() { // читаем значения полей WS_* из internal class NativeMethods. var t = typeof(Form).Assembly.GetType("System.Windows.Forms.NativeMethods"); var b = BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public; enums = t.GetFields(b) .Where(fi => fi.Name.StartsWith("WS_")) .Select(fi => new KeyValuePair((int)fi.GetValue(null), fi.Name)) .ToArray(); } static public string[] ReadStyles(HandleRef hr) { var v = GetWindowLong(hr, -16); // GWL_STYLE var res = new List(); for (int i = 0; i < enums.Length; i++) { var wsi = enums[i]; if ((v & wsi.Key) == wsi.Key) res.Add(wsi.Value); } return res.ToArray(); } } class HWndSpy { Timer Timer; public HWndSpy() { this.Timer = new Timer() { Interval = 500, Enabled = true }; this.Timer.Tick += (s, e) => { this.Point = Cursor.Position; // WinAPI: GetCursorPos this.HWnd = WindowFromPoint(this.Point); var hr = new HandleRef(this, this.HWnd); var cn = new StringBuilder(256); GetClassName(hr, cn, cn.Capacity); this.ClassName = cn.ToString(); this.Styles = WindowStyles.ReadStyles(hr); var r = new RECT(); GetWindowRect(hr, out r); this.WindowRect = Rectangle.FromLTRB(r.Left, r.Top, r.Right, r.Bottom); GetClientRect(hr, out r); this.ClientRect = Rectangle.FromLTRB(r.Left, r.Top, r.Right, r.Bottom); this.Color = GetPixelColor(this.Point); int pid; GetWindowThreadProcessId(hr, out pid); this.ProcessId = pid; this.Changed(this, EventArgs.Empty); }; } public IntPtr HWnd { get; private set; } public String ClassName { get; private set; } public String[] Styles { get; private set; } public Rectangle WindowRect { get; private set; } public Rectangle ClientRect { get; private set; } public Point Point { get; private set; } public Color Color { get; private set; } public int ProcessId { get; private set; } public event EventHandler Changed = delegate { }; } var frm = new Form() { Width = 570, Height = 170, TopMost = true }; Func label = (d) => new Label() { Parent = frm, Dock = d, TextAlign = ContentAlignment.TopLeft }; var style = label(DockStyle.Fill); var cname = label(DockStyle.Top); var bounds = label(DockStyle.Top); var hwnd = label(DockStyle.Top); var ws = new HWndSpy(); ws.Changed += (s, e) => { hwnd.Text = "HWnd: " + ws.HWnd + " (ProcessID:" + ws.ProcessId + ")"; bounds.Text = "WindowRect: " + ws.WindowRect + "; ClientRect: " + ws.ClientRect; cname.Text = "ClassName: " + ws.ClassName; style.Text = "Styles: " + String.Join("; ", ws.Styles); frm.Text = String.Concat( "HWndSpy -- Point: ", ws.Point, "; Color: ", ColorTranslator.ToHtml(ws.Color)); }; frm.ShowDialog(); Для компиляции кода и запуска приложения, например, в Visual Studio Community 2015 надо открыть View - Other Windows - C# Interactive, скопировать в него код и нажать Enter. Visual Studio Community 2015 - бесплатная версия, ее можно скачать тут.

Комментариев нет:

Отправить комментарий