Search code examples
c#winapidrawinggdi

C#. WinApi. Draw on window


I need to write a C# program which will identify a window under cursor and draw a border on it.

I could easily get a windows handler:

...
Point point;
WinApi.GetCursorPos(out point);
WinApi.WindowFromPoint(point);
...

But I can't draw on that window...

public static void drawSelectionRectangle(IntPtr handler)
{
    Rectangle rectangle;
    WinApi.GetWindowRect(handler, out rectangle);

    WinApi.PAINTSTRUCT paintProperties;
    IntPtr paintContext = WinApi.BeginPaint(handler, out paintProperties);

    IntPtr pen = WinApi.CreatePen(WinApi.PenStyle.PS_SOLID, 5, (uint) ColorTranslator.ToWin32(Color.Red));
    WinApi.SelectObject(paintContext, pen);

    WinApi.Rectangle(paintContext, rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom);

    WinApi.ValidateRect(handler, IntPtr.Zero);
    WinApi.EndPaint(handler, ref paintProperties);
}

I called drawSelectionRectangle(IntPtr handler) once (by button click) and on loop (by onPaint() method of MyForm, not form on which I want draw). This does not seem to work.

Help me, please. I don't know what to do.


Solution

  • It is not full solution for my problem but it is works.

    I wanted to draw on target window (if target window located under other window, borders must located under other window too)...But tis solution (when borders drawing above all windows) better than nothing.

    I hope my question and solution will help someone. Thank you all ^_^.

    public partial class Form1 : Form
    {
        private IntPtr selectedWindowHandler;    
    
        ...
    
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            Cursor.Current = new Cursor(Properties.Resources.aimImage.GetHicon());
            mousePressed = true;
            pictureBox_aimImage.Invalidate();
        }
    
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        { 
            mousePressed = false;
            invalidateAllWindows();
        }
    
        // this method for pictureBox1 which contain custom cursor
        // to choose window for draw border you must click on this box 
        // and drag to targwt window
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (mousePressed)
            {
                Point point;
                WinApi.GetCursorPos(out point);
                IntPtr hWnd = Window.getHandler(point);
    
                if (hWnd.Equals(selectedWindowHandler))
                {                    
                    drawSelectionRectangle(selectedWindowHandler);
                    pictureBox_aimImage.Invalidate();
                } else
                {
                    selectedWindowHandler = hWnd;
                    invalidateAllWindows();
                }
            }
        }
    
        // when i once called InvalidateRect(...) not all border was cleared
        // i don't know why
        private static void invalidateAllWindows()
        {
            WinApi.InvalidateRect(IntPtr.Zero, IntPtr.Zero, true);
            WinApi.InvalidateRect(IntPtr.Zero, IntPtr.Zero, true);
            WinApi.InvalidateRect(IntPtr.Zero, IntPtr.Zero, true);
        }     
    
        ...
    
        public static Rectangle getRectangle(IntPtr handler)
        {
            Rectangle rectangle;
            WinApi.GetWindowRect(handler, out rectangle);
            rectangle = new Rectangle(
                rectangle.Location,
                new Size(
                    rectangle.Size.Width - rectangle.Location.X,
                    rectangle.Size.Height - rectangle.Location.Y
                )
            );
            return rectangle;
        }
    
        public static void drawSelectionRectangle(IntPtr handler)
        {           
            //getting target window rectangle for GDI+
            Rectangle rect = getRectangle(handler);
    
            //getting context of desktop
            Graphics g = Graphics.FromHwnd(IntPtr.Zero);
            using (g)
            {
                //drawing borders
                g.DrawRectangle(new Pen(Color.Red, 3), rect);
            }
        }
    
    }