【问题标题】:Drawing and clearing on screen with Graphics.FromHwnd使用 Graphics.FromHwnd 在屏幕上绘图和清除
【发布时间】:2016-08-05 02:54:05
【问题描述】:

我正在尝试创建一个程序,它获取光标下窗口的句柄,显示有关它的一些数据并在整个窗口顶部绘制一个填充的矩形(具有非常低的 alpha)。我正在使用 C# 和 winforms。

我已经成功了,但问题是我的绘图方法在 BackgroundWorker 的循环中,并且它不断在窗口上制作越来越多的矩形(-> 具有更高 alpha 的矩形),或者当将鼠标移动到另一个旧窗口时一个仍然存在。

我还没有找到一种方法来清除绘制的矩形,因为它只是在屏幕上“存在”并且没有绑定到图形对象或任何东西。

我尝试过使用某些本地方法,例如

[DllImport("User32.dll")]
public static extern Int64 SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]
public static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, bool bErase);

[DllImport("user32.dll")]
public static extern bool UpdateWindow(IntPtr hWnd);

[DllImport("user32.dll")]
public static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, RedrawWindowFlags flags);

但以上都没有正常工作。其中一些确实有效,但随着消息进入队列,重绘不会立即发生,或者非常缓慢且出现故障(闪烁等)。

所以,问题是,如何“删除”我使用 Graphics.FromHwnd(handleOfWindowUnderCursor) 绘制的矩形?实际上,我认为在其他窗口上绘制它并不重要,因为我之前在尝试摆脱自己表单上的绘图时也遇到了同样的问题(也从未解决过这个问题!)。

或者,关于如何在不使用我现在的方法的情况下完成绘制和删除光标下窗口上的矩形的任何建议?

【问题讨论】:

    标签: c# winforms graphics screen handle


    【解决方案1】:

    我注意到使用

    绘图
    Graphics g = Graphics.FromHwnd(form.Handle);
    

    在其控件下绘制表单背景。是你想要完成的吗?

    // draw the rectangle
    Brush b = new SolidBrush(Color.FromArgb(20, 0, 0, 255));
    g.FillRectangle(b, new Rectangle(5, 5, 200, 200));
    
    // clear the rectangle
    g.Clear(this.BackColor);
    

    如果我直接在屏幕上绘图,那么:

    Graphics g = Graphics.FromHwnd(IntPtr.Zero);
    

    Windows 刷新屏幕后矩形立即消失。

    还有第三种选择,不是很简单。

    创建一个不透明度较低的表单,而不是绘制一个矩形,TopMost 属性设置为 true 并且没有边框。然后让它对事件透明:

    protected override void WndProc(ref Message m)
            {
                const int WM_NCHITTEST = 0x0084;
                const int HTTRANSPARENT = (-1);
    
                if (m.Msg == WM_NCHITTEST)
                {
                    m.Result = (IntPtr)HTTRANSPARENT;
                }
                else
                {
                    base.WndProc(ref m);
                }
            }
    

    之后您唯一需要注意的是此表单的可见性、位置和大小属性。

    【讨论】:

    • 我正在尝试创建一个非常简单的截图程序,它会截取进程窗口的截图。我希望它显示一个轻微的矩形覆盖,以表明窗口是正确的。可能另一种形式会更简单。
    【解决方案2】:
     bool change = false;
    private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                if (change)
                {
                     InvalidateRect(IntPtr.Zero, IntPtr.Zero, true);
                    change = false;
                }
                else
                {
                    PaintRectangleToScreen();
                    change = true;
                }
    
    
            }
            catch (System.Exception caught)
            {
    
                MessageBox.Show(caught.Message);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      • 2018-07-25
      • 2012-11-10
      相关资源
      最近更新 更多