Click here to Skip to main content
Click here to Skip to main content

Draw Over WinForms Controls

, 26 Aug 2010
Rate this:
Please Sign up or sign in to vote.
Use the Graphics object to draw almost anything on top of your form's controls
Form1

GraphicalOverlayDemo1.PNG GraphicalOverlayDemo2.PNG

Form2

GraphicalOverlayDemo3.PNG GraphicalOverlayDemo4.PNG GraphicalOverlayDemo5.PNG

Introduction

The GraphicalOverlay component draws on top of a form's controls. It is essentially like laying a piece of glass over the form and drawing on the glass. I use this component to draw lines between controls to help users make sense of complex relationships in the UI. I use it sparingly, but sometimes you just need a big red arrow that says: This affects that! When done correctly, the result can be quite elegant.

Using the Code

To use the GraphicalOverlay component, follow these steps:

  1. Copy the following two files to your project's directory: GraphicalOverlay.cs, GraphicalOverlay.designer.cs.
  2. Add GraphicalOverlay.cs to your project. Visual Studio will automatically include GraphicalOverlay.designer.cs.

    Compile the project. This will create a GraphicalOverlay component in the Visual Studio toolbox.

  3. Drag a GraphicalOverlay component from the toolbox onto your form's design surface. The component will automatically be named graphicalOverlay1.
  4. In your form, create a paint event handler for graphicalOverlay1 (graphicalOverlay1_Paint()).
  5. In your form's constructor, after the InitializeComponents(); line, add the following line:
    public Form1()
    {
        InitializeComponent();
    
        graphicalOverlay1.Owner = this;
    }
  6. In graphicalOverlay1_Paint() (see step 5), use e.Graphics to draw anything you like, using form-relative coordinates.
    private void graphicalOverlay1_Paint(object sender, PaintEventArgs e)
    {
        // This event will fire for the form and each control on the form.
        // The graphical overlay component will have already transformed the
        // graphics object to use the form's coordinate system, 
        // so no control-specific calculations are required.
    
        Rectangle rect = this.ClientRectangle;
        rect.Inflate(-10, -10);
    
        using(Pen pen = new Pen(Color.Red, 5))
            e.Graphics.DrawEllipse(pen, rect);
    
        using(Font font = new Font("Arial", 14))
            e.Graphics.DrawString("Now is the time.", 
                                  font, Brushes.Green, 60, 110);
    
        [...]
    }
  7. To draw control-relative graphics, use the Coordinates() method to get the control's form-relative coordinates. See the Form1.graphicalOverlay1_Paint() event handler in the demo code for an example.
    private void graphicalOverlay1_Paint(object sender, PaintEventArgs e)
    {
        [...]
        // To draw relative to a control, use the Coordinates method.
        using (Pen pen = new Pen(Color.Blue, 3))
            e.Graphics.DrawEllipse(pen, pictureBox1.Coordinates());
    }

Points of Interest

The component contains the following event handlers:

  • Form_Resize
  • Control_Paint

When the graphicalOverlay1.Owner property is set, the component connects its Form_Resize event handler to the owner form's Resize event. Then, the component attaches its Control_Paint event handler to the Paint event for each of the owner form's controls (including the owner form itself).

As each control is repainted, the component handles the Paint event, transforms the coordinates of the e.Graphics object, then fires its own Paint event which will be handled by the form's graphicalOverlay1_Paint event handler.

Because the e.Graphics object received by graphicalOverlay1_Paint() has been transformed to use the form's coordinate system, all of the drawing logic is form-relative. Just draw as if you're drawing within the form's client area.

This approach makes it difficult to draw relative to the controls, however. So, to make control-relative drawing easier, I have added an extension method called Coordinates() to the System.Windows.Forms.Control class. The Coordinates() method converts the control's location to form-relative coordinates. Just draw using Coordinates(control) instead of control.Location.

Because the graphical overlay can be drawn over all of the form's controls, redrawing it requires the entire form to be invalidated. Calling the component's Invalidate() method will invalidate the form and each of the form's controls.

Limitations

The component responds to each control's Paint event. The TextBox control does not fire a Paint event, so the component cannot draw over TextBox controls. It may be possible to use text box controls from a third party, but I have not tested any of them.

The component can only draw over a control's client area. Some controls include a border that is not part of their client area, so the component cannot draw over the border. One solution to this problem is to turn off the control's border and draw it using the component.

The component can only draw within a form's client area. It cannot draw over the form's title bar or borders, and it cannot draw between forms. To simulate drawing over the form's borders, you would need to turn off the form's border and draw it with the component--and re-implement all of the lost functionality.

Demos

I have included two demo forms to help you understand how to implement your own graphicalOverlay1_Paint event handler.

Form1.cs is the one with the picture with red and blue rings and green text.

Note: While the Form1 demo is running, resize the form a few times.

Form2.cs is the demo with the group boxes and radio buttons.

Note: In order to switch between the Form1 and Form2 demos, you must modify the Program.cs file to run Form1 or Form2. By default, the demo will run Form2.

In the Form2 demo, the code in graphicalOverlay1_Paint() contains a lot of hard coded values. I could have calculated these values, but it would only have made it harder to read the code. The hard coded values may not work exactly right if your UI culture is different from mine or if your fonts are configured differently from mine. The screenshots at the beginning of the article will show you what they are supposed to look like.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

RocketteScientist
Software Developer (Senior)
United States United States
No Biography provided

Comments and Discussions

 
BugIssue with NumericUpDown PinmemberAbysmaroth19-Aug-14 1:12 
QuestionSwitching between Images ? Pinmemberzeleksonob3-Aug-14 4:54 
QuestionCreate GraphicalOverlay object dynamically PinmemberMember 107769789-Jul-14 17:25 
GeneralThanks! [modified] PinmemberMember 1063400028-Feb-14 12:18 
QuestionDraw line over UserControls with this code PinmemberM_Mogharrabi2-Dec-13 23:09 
BugAlmost works Pinmemberqubit10125-Jan-13 3:28 
Questionit works also on control as owner PinmemberMember 889513027-Apr-12 6:17 
QuestionAm able to overlay on picture box, but i want to overlay text on AxVLC plugin control. Is it possible? Pinmembersirigineediravikumar18-Mar-12 0:19 
AnswerRe: Am able to overlay on picture box, but i want to overlay text on AxVLC plugin control. Is it possible? PinmemberRocketteScientist20-Mar-12 7:56 
GeneralMy vote of 5 Pinmemberp1nkzz24-Feb-12 0:29 
GeneralMy vote of 5 Pinmembermanoj kumar choubey21-Feb-12 23:54 
GeneralMy vote of 4 Pinmembertokenian11-Oct-11 21:03 
QuestionWhat about scrolling stuff? PinmemberRikard Häggström4-Oct-11 11:47 
AnswerRe: What about scrolling stuff? [modified] PinmemberRocketteScientist4-Oct-11 15:44 
GeneralMy vote of 5 PinmemberBoilerProg25-Jul-11 4:52 
QuestionDynamically Create GraphicalOverlay and Class the Draw Code PinmemberMember 304592322-Jul-11 5:37 
AnswerRe: Dynamically Create GraphicalOverlay and Class the Draw Code PinmemberRocketteScientist22-Jul-11 21:01 
GeneralRe: Dynamically Create GraphicalOverlay and Class the Draw Code PinmemberMember 304592325-Jul-11 4:46 
GeneralBroken drawing of custom control, with fix PinmemberAndrew Haydn Grant29-Sep-10 11:48 
GeneralMy vote of 4 PinmemberToli Cuturicu26-Aug-10 4:42 
GeneralA new version of the GraphicalOverlayComponent is available. PinmemberRocketteScientist24-Aug-10 19:59 
GeneralGraphicalOverlay over a SplitContainer PinmemberDramirak24-Aug-10 6:40 
AnswerRe: GraphicalOverlay over a SplitContainer PinmemberRocketteScientist24-Aug-10 17:43 
GeneralRe: GraphicalOverlay over a SplitContainer PinmemberRocketteScientist24-Aug-10 20:08 
GeneralAdding A circle when button is clicked PinmemberDramirak18-Aug-10 3:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140821.2 | Last Updated 26 Aug 2010
Article Copyright 2008 by RocketteScientist
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid