使用Graphics.FromHwnd在屏幕上绘图和清除

时间:2013-03-28 13:02:31

标签: c# winforms graphics screen handle

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

我已经成功地做到了,但问题是我的draw方法是在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)“删除”我绘制的矩形?我实际上认为它是在其他窗口上绘制并不重要,因为我在试图摆脱我自己的形式上的图纸之前遇到了同样的问题(从来没有得到那个固定!)。

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

2 个答案:

答案 0 :(得分:2)

我注意到使用

绘图
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);
            }
        }

此后您必须注意的唯一事项是此表单的可见,位置和大小属性。

答案 1 :(得分:0)

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