C#。 WinApi。在窗口上绘制

Posted

技术标签:

【中文标题】C#。 WinApi。在窗口上绘制【英文标题】:C#. WinApi. Draw on window 【发布时间】:2017-10-01 17:19:02 【问题描述】:

我需要编写一个 C# 程序来识别光标下的窗口并在其上绘制边框。

我可以轻松获得一个 Windows 处理程序:

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

但我不能在那个窗口上画画……

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

我调用了drawSelectionRectangle(IntPtr handler) 一次(通过按钮单击)和循环调用(通过 MyForm 的onPaint() 方法,而不是我想要绘制的表单)。这似乎不起作用。

请帮帮我。我不知道该怎么办。

【问题讨论】:

不行。窗户不属于你。所有者将在您可能成功绘制的任何内容上进行绘制。您需要了解 Win32 绘图的工作原理。不管是什么问题,这都不是解决方案。 【参考方案1】:

这不是我的问题的完整解决方案,但它是有效的。

我想在目标窗口上绘制(如果目标窗口位于其他窗口下,边框也必须位于其他窗口下)...但是这个解决方案(当边框在所有窗口上方绘制时)总比没有好。

我希望我的问题和解决方案对某人有所帮助。谢谢大家^_^。

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


【讨论】:

以上是关于C#。 WinApi。在窗口上绘制的主要内容,如果未能解决你的问题,请参考以下文章

如何在标准按钮 WinApi 上绘图

使用 C/C++ 和 WinApi 精确绘制 1 像素宽度的线

如何在 WinAPI 中将 TrueType 字体绘制到像素数组中?

使用 WinAPI 创建具有透明背景的文本标签

使用 gdi 在 winapi 窗口中的运行时更新颜色

如何在c ++ winapi中获取活动文件资源管理器窗口的路径