back to projects
Software

Udraw

C# WinForms Drawing App with SQL Storage.

Udraw

overview

uDraw is a personal project built in C# (WinForms) to explore the intersection of GUI development, graphics rendering, and SQL database management. The goal: create a simple desktop drawing environment that can save drawings into an SQL Server database and later load them back as editable canvases.

application structure

The app follows a clean separation of concerns: • UI Layer → Forms for user interaction • Graphics Layer → Canvas rendering • Persistence Layer → SQL Server CRUD operations

uDraw/
├── Forms/
│   ├── MainForm.cs
│   ├── SaveForm.cs
│   └── LoadForm.cs
├── Components/
│   └── PaintingCanvas.cs
├── Database/
│   ├── DatabaseHelper.cs
│   └── DatabaseConfig.cs
├── Properties/
└── Program.cs

drawing logic

The PaintingCanvas control is the core of uDraw. It captures mouse input, renders strokes, and maintains a Bitmap buffer to avoid flicker.

// PaintingCanvas.cs
public class PaintingCanvas : Panel
{
    private bool isDrawing = false;
    private Point lastPoint;
    private Bitmap canvas;

    public PaintingCanvas()
    {
        this.DoubleBuffered = true;
        canvas = new Bitmap(800, 600);
        this.MouseDown += OnMouseDown;
        this.MouseMove += OnMouseMove;
        this.MouseUp += OnMouseUp;
    }

    private void OnMouseDown(object sender, MouseEventArgs e)
    {
        isDrawing = true;
        lastPoint = e.Location;
    }

    private void OnMouseMove(object sender, MouseEventArgs e)
    {
        if (!isDrawing) return;
        using (Graphics g = Graphics.FromImage(canvas))
        {
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.DrawLine(new Pen(Color.DeepSkyBlue, 2), lastPoint, e.Location);
        }
        lastPoint = e.Location;
        Invalidate();
    }

    private void OnMouseUp(object sender, MouseEventArgs e)
    {
        isDrawing = false;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.DrawImageUnscaled(canvas, 0, 0);
    }
}

database integration

Each drawing is stored in SQL Server as a VARBINARY(MAX) column. The DatabaseHelper handles serialization and CRUD operations.

Retrieving the drawing:

// DatabaseHelper.cs
public static void SaveDrawing(string name, Bitmap bmp)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConfig.ConnectionString))
    {
        conn.Open();
        using (MemoryStream ms = new MemoryStream())
        {
            bmp.Save(ms, ImageFormat.Png);
            byte[] data = ms.ToArray();

            string q = "INSERT INTO Drawings (Name, ImageData, CreatedAt) VALUES (@n, @d, GETDATE())";
            using (SqlCommand cmd = new SqlCommand(q, conn))
            {
                cmd.Parameters.AddWithValue("@n", name);
                cmd.Parameters.Add("@d", SqlDbType.VarBinary).Value = data;
                cmd.ExecuteNonQuery();
            }
        }
    }
}
// DatabaseHelper.cs
public static Bitmap LoadDrawing(string name)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConfig.ConnectionString))
    {
        conn.Open();
        string q = "SELECT ImageData FROM Drawings WHERE Name = @n";
        using (SqlCommand cmd = new SqlCommand(q, conn))
        {
            cmd.Parameters.AddWithValue("@n", name);
            var imgData = (byte[])cmd.ExecuteScalar();
            if (imgData == null) return null;

            using (MemoryStream ms = new MemoryStream(imgData))
                return new Bitmap(ms);
        }
    }
}

SQL Schema

The database schema is simple and optimized for binary image storage:

CREATE TABLE Drawings (
    Id INT IDENTITY PRIMARY KEY,
    Name NVARCHAR(100) NOT NULL,
    ImageData VARBINARY(MAX) NOT NULL,
    CreatedAt DATETIME DEFAULT GETDATE()
);

configuration

The configuration file allows switching between local or remote SQL servers easily. Error handling ensures the app doesn’t crash if the database is unavailable.

// DatabaseConfig.cs
public static class DatabaseConfig
{
    public static string ConnectionString =
        "Server=localhost;Database=uDrawDB;Trusted_Connection=True;";
}

technical stack

  • Language: C# (.NET Framework 4.8)
  • UI Framework: Windows Forms
  • Database: Microsoft SQL Server
  • Libraries: System.Data.SqlClient, System.Drawing
  • IDE: Visual Studio 2022

future work

  • Add multiple layers and brush styles.
  • Integrate cloud save (Azure Blob Storage or Firebase).
  • Implement undo/redo stack and drawing history.
  • Refactor UI using WPF for modern rendering.

conclusion

uDraw shows that even small WinForms apps can be full-stack. From Graphics rendering to SQL persistence, it encapsulates key desktop software concepts — responsiveness, data management, and a clean modular codebase.

explore more