MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Рисование на окне другого приложения с помощью WinAPI"
Answer 661636
Проблема в неверном подходе. Во-первых, забудьте про функцию BeginPaint (вне обработки сообщения WM_PAINT), во-вторых, рисовать надо не в контексте целевого окна, а в контексте его родительского окна (контекст окна позволяет рисовать только в его клиентской области, а рамка-то нам нужна снаружи).
Я предлагаю сделать как-то так:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace DrawingTest { public partial class Form1 : Form { [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetCursorPos(out POINT lpPoint); [DllImport("user32.dll")] static extern IntPtr WindowFromPoint(POINT p); [DllImport("user32.dll", SetLastError = true)] static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); [DllImport("user32.dll")] static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint); [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] public static extern IntPtr GetParent(IntPtr hWnd); public Form1() { InitializeComponent(); } private void timer1_Tick(object sender, EventArgs e) { //получаем окно в текущей позиции курсора POINT pt; GetCursorPos(out pt); IntPtr hwnd = WindowFromPoint(pt); //получаем родительское окно IntPtr hwnd_p = GetParent(hwnd); //получаем границы окна RECT rc; GetWindowRect(hwnd, out rc); //перевод из экранных координат в клиентские POINT pt1=new POINT(rc.Left,rc.Top), pt2=new POINT(rc.Right,rc.Bottom); ScreenToClient(hwnd_p, ref pt1); ScreenToClient(hwnd_p, ref pt2); RECT rc_client = new RECT(); rc_client.Left = pt1.X-1; rc_client.Top = pt1.Y-1; rc_client.Right = pt2.X; rc_client.Bottom = pt2.Y; //формируем структуру для GDI+ Rectangle rect = new Rectangle(rc_client.Left, rc_client.Top, rc_client.Right - rc_client.Left, rc_client.Bottom - rc_client.Top); //получаем контекст окна Graphics g = System.Drawing.Graphics.FromHwnd(hwnd_p); using (g) { //рисуем прямоугольник g.DrawRectangle(Pens.Red, rect); } } } [StructLayout(LayoutKind.Sequential)] public struct POINT { public int X; public int Y; public POINT(int x, int y) { this.X = x; this.Y = y; } public POINT(System.Drawing.Point pt) : this(pt.X, pt.Y) { } public static implicit operator System.Drawing.Point(POINT p) { return new System.Drawing.Point(p.X, p.Y); } public static implicit operator POINT(System.Drawing.Point p) { return new POINT(p.X, p.Y); } } [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; // x position of upper-left corner public int Top; // y position of upper-left corner public int Right; // x position of lower-right corner public int Bottom; // y position of lower-right corner } }
Если целевое окно перекрывается другими окнами, соответствующая часть рамки будет скрыта. Чтобы рисовать рамку поверх всех окон, код рисования нужно изменить, используя контекст рабочего стола:
//получаем окно в текущей позиции курсора POINT pt; GetCursorPos(out pt); IntPtr hwnd = WindowFromPoint(pt); //получаем границы окна RECT rc; GetWindowRect(hwnd, out rc); //формируем структуру для GDI+ Rectangle rect = new Rectangle(rc.Left, rc.Top, rc.Right - rc.Left, rc.Bottom - rc.Top); //получаем контекст рабочего стола Graphics g = System.Drawing.Graphics.FromHwnd((IntPtr)0); using (g) { //рисуем прямоугольник g.DrawRectangle(Pens.Red, rect); }
Иллюстрация различия между этими двумя методами:
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.