kidprogramer
kidprogramer

Reputation: 11

Drawing on the monitor even if another application is full screen in C#

First of all, hello, this will be my first question. I wish you a good day. Coming to my question, creating a special crosshair is supported in CSGO or CS2, but unfortunately, this is not supported in old CS games such as CS 1.6. For this reason, I want to draw a special crosshair directly on the monitor using C#. I did what I wanted, but the only problem is that when an application is full screen, the program stops drawing crosses on the screen. How can I solve this problem? How can I draw on the screen even if an application is full screen? I leave my code below, thank you in advance.

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace AimChanger
{
    public partial class Form1 : Form
    {
        private bool dragging = false;
        private Point dragCursorPoint;
        private Point dragFormPoint;
        private Timer drawTimer;
        private IntPtr desktopPtr;
        private Graphics desktopGraphics;

        [DllImport("user32.dll")]
        public static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("user32.dll")]
        public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

        [DllImport("gdi32.dll")]
        public static extern IntPtr CreatePen(int fnObject, int nWidth, int color);

        [DllImport("gdi32.dll")]
        public static extern bool SelectObject(IntPtr hdc, IntPtr hObject);

        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);

        [DllImport("user32.dll")]
        public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int nWidth, int nHeight, IntPtr hdcSrc, int xSrc, int ySrc, uint dwRop);

        public Form1()
        {
            this.TopMost = true;
            InitializeComponent();
            InitializeDirectDraw();
            pictureBox2.Paint += PictureBox2_Paint;
            pictureBox2.MouseDown += PictureBox2_MouseDown;
            pictureBox2.MouseMove += PictureBox2_MouseMove;
            pictureBox2.MouseUp += PictureBox2_MouseUp;
            ApplyRoundedCornersToPictureBox();
            textBox1.Text = trackBar1.Value.ToString();
            textBox2.Text = trackBar2.Value.ToString();
            textBox3.Text = trackBar3.Value.ToString();
            textBox4.Text = trackBar4.Value.ToString();
            textBox5.Text = trackBar5.Value.ToString();
            textBox6.Text = trackBar6.Value.ToString();
            textBox7.Text = trackBar7.Value.ToString();
            textBox8.Text = trackBar8.Value.ToString();
            checkBox2.CheckedChanged += checkBox2_CheckedChanged;
        }

        private void InitializeDirectDraw()
        {
            drawTimer = new Timer()
            {
                Interval = 16
            };
            drawTimer.Tick += DrawTimer_Tick;
            desktopPtr = GetDC(IntPtr.Zero);
            desktopGraphics = Graphics.FromHdc(desktopPtr);
        }

        private void DrawTimer_Tick(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                DrawCustomCrosshair(desktopGraphics);
            }
        }

        private void DrawCustomCrosshair(Graphics g)
        {
            int screenCenterX = Screen.PrimaryScreen.Bounds.Width / 2;
            int screenCenterY = Screen.PrimaryScreen.Bounds.Height / 2;
            int size = trackBar1.Value;
            int thickness = trackBar2.Value;
            int gap = trackBar3.Value;
            int alpha = trackBar4.Value;
            int outline = trackBar5.Value;
            Color crosshairColor = Color.FromArgb(alpha, trackBar6.Value, trackBar7.Value, trackBar8.Value);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            if (outline > 0)
            {
                using (Pen outlinePen = new Pen(Color.FromArgb(alpha, Color.Black), thickness + outline * 2))
                {
                    g.DrawLine(outlinePen, screenCenterX - size - gap, screenCenterY, screenCenterX - gap, screenCenterY);
                    g.DrawLine(outlinePen, screenCenterX + gap, screenCenterY, screenCenterX + size + gap, screenCenterY);
                    g.DrawLine(outlinePen, screenCenterX, screenCenterY - size - gap, screenCenterX, screenCenterY - gap);
                    g.DrawLine(outlinePen, screenCenterX, screenCenterY + gap, screenCenterX, screenCenterY + size + gap);
                }
            }
            using (Pen crosshairPen = new Pen(crosshairColor, thickness))
            {
                g.DrawLine(crosshairPen, screenCenterX - size - gap, screenCenterY, screenCenterX - gap, screenCenterY);
                g.DrawLine(crosshairPen, screenCenterX + gap, screenCenterY, screenCenterX + size + gap, screenCenterY);
                g.DrawLine(crosshairPen, screenCenterX, screenCenterY - size - gap, screenCenterX, screenCenterY - gap);
                g.DrawLine(crosshairPen, screenCenterX, screenCenterY + gap, screenCenterX, screenCenterY + size + gap);
            }
            if (checkBox2.Checked)
            {
                int dotSize = 5;  
                using (Brush dotBrush = new SolidBrush(Color.FromArgb(alpha, trackBar6.Value, trackBar7.Value, trackBar8.Value)))
                {
                    g.FillEllipse(dotBrush, screenCenterX - dotSize / 2, screenCenterY - dotSize / 2, dotSize, dotSize);
                }
            }
        }
        private void PictureBox2_Paint(object sender, PaintEventArgs e)
        {
            DrawGradientText(e.Graphics, pictureBox2.ClientRectangle);
        }
        [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
        private static extern IntPtr CreateRoundRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse);
        private void ApplyRoundedCornersToPictureBox()
        {
            int radius = 30;
            IntPtr region = CreateRoundRectRgn(0, 0, pictureBox3.Width, pictureBox3.Height, radius, radius);
            pictureBox3.Region = Region.FromHrgn(region);
        }
        private void DrawGradientText(Graphics g, Rectangle bounds)
        {
            string text1 = "Crosshair";
            string text2 = "Changer";
            Font font = new Font("Consolas", 18, FontStyle.Bold);
            Point text1Location = new Point(bounds.Left + 10, bounds.Top + 15);
            Point text2Location = new Point(bounds.Left + 135, bounds.Top + 15);
            using (SolidBrush whiteBrush = new SolidBrush(Color.White))
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.DrawString(text1, font, whiteBrush, text1Location);
            }
            Rectangle gradientRect = new Rectangle(text2Location, new Size(200, 50));
            Color[] colors = { Color.Purple, Color.Red, Color.Orange };
            using (LinearGradientBrush brush = new LinearGradientBrush(gradientRect, Color.White, Color.Red, LinearGradientMode.Horizontal))
            {
                ColorBlend blend = new ColorBlend
                {
                    Colors = colors,
                    Positions = new float[] { 0f, 0.5f, 1f }
                };
                brush.InterpolationColors = blend;
                g.DrawString(text2, font, brush, text2Location);
            }
        }
        private void ApplyRoundedCorners()
        {
            int radius = 50;
            Region = new Region(new GraphicsPath());
            GraphicsPath path = new GraphicsPath();
            path.AddArc(0, 0, radius, radius, 180, 90);
            path.AddArc(Width - radius, 0, radius, radius, 270, 90);
            path.AddArc(Width - radius, Height - radius, radius, radius, 0, 90);
            path.AddArc(0, Height - radius, radius, radius, 90, 90);
            path.CloseFigure();
            Region = new Region(path);
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            ApplyRoundedCorners();
        }
        private void Form1_Resize(object sender, EventArgs e)
        {
            ApplyRoundedCorners();
        }
        private void PictureBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                dragging = true;
                dragCursorPoint = Cursor.Position;
                dragFormPoint = this.Location;
            }
        }
        private void PictureBox2_MouseMove(object sender, MouseEventArgs e)
        {
            if (dragging)
            {
                Point diff = new Point(Cursor.Position.X - dragCursorPoint.X, Cursor.Position.Y - dragCursorPoint.Y);
                this.Location = new Point(dragFormPoint.X + diff.X, dragFormPoint.Y + diff.Y);
            }
        }
        private void PictureBox2_MouseUp(object sender, MouseEventArgs e)
        {
            dragging = false;
        }
        private void label2_Click(object sender, EventArgs e)
        {
            Environment.Exit(0);
        }
        private void label3_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            textBox1.Text = trackBar1.Value.ToString();
        }
        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            textBox2.Text = trackBar2.Value.ToString();
        }
        private void trackBar3_Scroll(object sender, EventArgs e)
        {
            textBox3.Text = trackBar3.Value.ToString();
        }
        private void trackBar4_Scroll(object sender, EventArgs e)
        {
            textBox4.Text = trackBar4.Value.ToString();
        }
        private void trackBar5_Scroll(object sender, EventArgs e)
        {
            textBox5.Text = trackBar5.Value.ToString();
        }
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                drawTimer.Start();
            }
            else
            {
                drawTimer.Stop();
                InvalidateRect(IntPtr.Zero, IntPtr.Zero, true);
            }
        }
        [DllImport("user32.dll")]
        private static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, bool bErase);
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (drawTimer != null)
            {
                drawTimer.Dispose();
            }
            if (desktopGraphics != null)
            {
                desktopGraphics.Dispose();
            }
            if (desktopPtr != IntPtr.Zero)
            {
                ReleaseDC(IntPtr.Zero, desktopPtr);
            }
            base.OnFormClosing(e);
        }
        private void trackBar6_Scroll(object sender, EventArgs e)
        {
            textBox6.Text = trackBar6.Value.ToString();
        }
        private void trackBar7_Scroll(object sender, EventArgs e)
        {
            textBox7.Text = trackBar7.Value.ToString();
        }
        private void trackBar8_Scroll(object sender, EventArgs e)
        {
            textBox8.Text = trackBar8.Value.ToString();
        }
        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {
            Invalidate();  
        }
    }
}

Solving the problem and learning the truth

Upvotes: 1

Views: 123

Answers (1)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112682

In WinForms, you can set a custom mouse cursur. First create a cursor from an image:

var cursor = new Cursor(Properties.Resources.paintcan_png_cur.GetHicon());

then assign it to a control (your game background or game canvas):

_polygonCanvas.Cursor = cursor;

you can restore the normal cursor with:

_polygonCanvas.Cursor = Cursors.Arrow;

There is a long list of standard cursors exposed as static properties in the Cursor class.

My cursor from the example above looks like this and displays even colors:

enter image description here


I tried another thing by using the WS_EX_Layered style:

private const int GWL_ExStyle = -20;
private const int WS_EX_Layered = 0x80000;

[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

public Form1()
{
    InitializeComponent();

    FormBorderStyle = FormBorderStyle.None;
    WindowState = FormWindowState.Maximized;
    TopMost = true;

    int initialStyle = GetWindowLong(Handle, GWL_ExStyle);
    _ = SetWindowLong(Handle,
        GWL_ExStyle, initialStyle | WS_EX_Layered);

    Cursor = Cursors.Cross;
}

This displays a crosshair on top of another maximized application; however, it is not possible to interact with the other application.

Upvotes: 0

Related Questions