问题
I am trying to create a program which gets the handle of the window under your cursor, show's some data about it and draws a filled rectangle (with very low alpha) on top of the whole window. I am using C# and winforms.
I have succeeded in doing so, but the problem is my draw method is in a BackgroundWorker's loop and it keeps making more and more rectangles (-> rectangle with higher alpha) on the window or when moving mouse to another window the old one still exists.
I haven't managed to find a method to clear the drawn rectangle as it just "is" on the screen and isn't bound to the graphics object or anything.
I have tried using certain native methods such as
[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);
but none of the above has worked correctly. Some of them do work but as the messages get in the queue the redrawing doesn't occur immediately or is very slow and glitched (flickering etc).
So, the question is, how would I "remove" the rectangle I have drawn using Graphics.FromHwnd(handleOfWindowUnderCursor)? I actually think it doesn't matter that it is drawn on other window as I have had the very same problem earlier when trying to get rid of the drawings on my own form too (never got that fixed either!).
Alternatively, any suggestions on how I could accomplish drawing and removing the rectangle on the window under cursor without using the methods I am now?
回答1:
I noticed that drawing using
Graphics g = Graphics.FromHwnd(form.Handle);
draws on the form background, under its controls. Is it whatyou want to acomplish?
// 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);
If I draw on the screen directly, with this:
Graphics g = Graphics.FromHwnd(IntPtr.Zero);
the rectangle disapears immediately after Windows refreshes the screen.
There is a third option, which is not realy strightforward.
Instead of drawing a rectangle, create a form with lowered opacity, TopMost property set to true and without borders. Then make it transparent to events:
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);
}
}
The only things you have to take care after that is this form's Visible, Location and Size properties.
回答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);
}
}
来源:https://stackoverflow.com/questions/15682543/drawing-and-clearing-on-screen-with-graphics-fromhwnd