I'm drawing a circle as a second cursor in another application using System.Drawing.Graphics.FromHwnd(IntPtr). The shape draws properly beneath my cursor, but it flickers. I'm familiar with double buffering but this code is in an "Input" class I made, and not in a form. This is in a game so I'm pretty sure this is happening because the canvas in the game is being redrawn every frame and painting over my circle shape.
Is there a way to:
- Properly cause double buffering in this situation
- Eliminate flicker by some other means
Thank you
Using C# and .NET 5 if that matters (also since I know there will be inevitable comments on my class structure, this was quick and dirty to demonstrate the issue - I know that some of what I did here is not best practice).
public class Input
{
private ThreadTimer timer;
private IntPtr hwnd;
private Graphics? winGraphics = default;
public Input()
{
timer = new ThreadTimer();
timer.Interval = 15;
timer.AutoReset = true;
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
User32.POINT clientPt = new User32.POINT(Cursor.Position.X, Cursor.Position.Y);
User32.ScreenToClient(hwnd, ref clientPt);
var cursor = new Rectangle(clientPt, new Size(5, 5));
winGraphics = Graphics.FromHwnd(hwnd);
winGraphics.FillEllipse(new SolidBrush(Color.FromArgb(50, Color.Red)), new Rectangle(clientPt.X-15, clientPt.Y-15, 30, 30));
}
public void StartDrawMouse(IntPtr hwnd)
{
this.hwnd = hwnd;
timer.Start();
}
public void StopDrawMouse()
{
this.hwnd = IntPtr.Zero;
timer.Stop();
}
}
ScreenToClient and its pinvoke data structure for POINT:
[DllImport("user32.dll")]
public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
public static implicit operator System.Drawing.Point(POINT p)
{
return new System.Drawing.Point(p.X, p.Y);
}
public static implicit operator POINT(System.Drawing.Point p)
{
return new POINT(p.X, p.Y);
}
}