C# GDI Drawing in Panel in Custom Control in c sharp

I am trying to draw a simple square inside a panel which is inside a user custom control. I have been able to: (1) draw exactly that inside a panel in a form (2) been able to draw in a custom control, and use that control in another project.

What I can't do is see my drawing (a simple square) drawn inside a panel that is inside a custom control because the panel (pnlMain) Paint event never seems to get called.

The code snippet is from my custom control:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
 
namespace gridCustomControl
{
    
 
    public partial class GridCustomControl : System.Windows.Forms.Control
    {
        public GridCustomControl()
        {
            InitializeComponent();
        }
 
        private void GridCustomControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //These 3 line of test code worked, so I commented them out:
            
            /*
            Graphics g = e.Graphics;
            g.FillRectangle(Brushes.Red, ClientRectangle);
            g.DrawString("Hello World!", Font, Brushes.Black, 0, 0);
            */
        }
 
        private void pnlMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //The path of execution never goes through this function
            Graphics dc = e.Graphics;
            Console.WriteLine("in pnlMain_Paint"); 
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
        }
 
    } // End Class GridCustomControl
} // End namespace gridCustomControl

Open in new window

yaronusaAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
jgordosConnect With a Mentor Commented:
well, we're getting close!

now, add

base.OnPaint(e);

as the first line of

pnlMain_Paint

-john
0
 
jgordosCommented:
Hang the painting of the panel off the custom control's paint event; not the panel.

Once  you have a custom control, it's all up to you.. windows won't do the messaging for you
0
 
yaronusaAuthor Commented:
OK, so how do I do the messaging, is it difficult? It sounds like it would be the clean solution...

I did try the following: In the Paint method of the custom control, my panel (pnlMain) does not have a Graphics property, only createGraphics. I don't think I want to create the graphics all over again everytime the Paint function for the custom control is called do I?
private void GridCustomControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //These 3 line of test code worked, so I commented them out:
            
            /*
            Graphics g = e.Graphics;
            g.FillRectangle(Brushes.Red, ClientRectangle);
            g.DrawString("Hello World!", Font, Brushes.Black, 0, 0);
            */
 
            Graphics dc = /* ??? *?
            Console.WriteLine("in pnlMain_Paint"); 
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
        }

Open in new window

0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
jgordosCommented:
Yeah, you do... it's not as bad as you think; just be sure to dispose of it after every paint...

You aren't trying to do some real-time video gamey graphics are you?

0
 
yaronusaAuthor Commented:
I'm not sure what this does, but this line was added to my InitializeComponent() method of the custom control:

this.pnlMain.Paint += new System.Windows.Forms.PaintEventHandler(this.pnlMain_Paint);

where pnlMain is the panel I'm trying to draw to.
0
 
jgordosCommented:
that certainly looks like the hook for the paint event was added to the handler for the form.

in other words, the form now controls the paint event for the handler....

This is in the portion of the code you can't change, yes?
0
 
yaronusaAuthor Commented:
No game programming... according to your advice, the code snippet shows what I have so far, but I still don't see a black square.... any ideas why (When debugging the execution path does go thru the paint event method)?
namespace gridCustomControl
{
    public partial class GridCustomControl : System.Windows.Forms.Control
    {
        public GridCustomControl()
        {
            InitializeComponent();
        }
 
        private void GridCustomControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Graphics dc = pnlMain.CreateGraphics();
            Console.WriteLine("in pnlMain_Paint"); 
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
            dc.Dispose();
        }
    } // End Class GridCustomControl
} // End namespace gridCustomControl

Open in new window

0
 
yaronusaAuthor Commented:
This is how my InitializeComponent of the custom control looks like now:
private void InitializeComponent()
        {
            this.pnlMain = new System.Windows.Forms.Panel();
            this.SuspendLayout();
            // 
            // pnlMain
            // 
            this.pnlMain.Location = new System.Drawing.Point(0, 0);
            this.pnlMain.Name = "pnlMain";
            this.pnlMain.Size = new System.Drawing.Size(200, 100);
            this.pnlMain.TabIndex = 0;
            // 
            // GridCustomControl
            // 
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.GridCustomControl_Paint);
            this.ResumeLayout(false);
 
        }

Open in new window

0
 
jgordosCommented:
did you paint the base object?

ie,

base.OnPaint(e)
before you drawyour custom stuff...

and... don't create your graphics

do

Graphics dc = e.Graphics....

-john

0
 
yaronusaAuthor Commented:
That's what I was saying in my previous post, that my panel (pnlMain) does not have a Graphics property, only createGraphics within the Paint Event Method -- take a look at the ??? at the code snippet -- I don't know what to put there.

Should I put pnlMain.CreateGraphics() or e.Graphics. If I put e.Graphics... then how can I update my panel??

I don't know where to put base.OnPaint(e)
private void GridCustomControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //These 3 line of test code worked, so I commented them out:
            
            /*
            Graphics g = e.Graphics;
            g.FillRectangle(Brushes.Red, ClientRectangle);
            g.DrawString("Hello World!", Font, Brushes.Black, 0, 0);
            */
 
            Graphics dc = /* ??? *?
            Console.WriteLine("in pnlMain_Paint"); 
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
        }

Open in new window

0
 
jgordosCommented:
Graphics dc = e.Graphics;
0
 
jgordosCommented:
And, remember, first thing in the paint method should be


base.OnPaint(e);

-john
0
 
yaronusaAuthor Commented:
OK...

Let me see if I can explain this better...

I need the lline of code where I draw the rectangle IN the panel (pnlMain) that is IN the control? Otherwise, the code as it is, just writes to the panel, which I could already do...

0
 
yaronusaAuthor Commented:
hmmm... I thought the base.OnPaint(e) is called only if you are overriding a paint event method, but in the custom control context, I'm in a private event method, so I don't think there is any "base" to call, my code crashes if I put Base.OnPaint(e).

Maybe I'm misunderstanding something, should I be overriding the control paint method with a paint event for the panel, and in that panel paint event call the base.OnPaint(e)?

0
 
jgordosCommented:
yaronusa said:

>OK...
>
>Let me see if I can explain this better...
>
>I need the lline of code where I draw the rectangle IN the panel (pnlMain) that is IN the control? Otherwise, the >code as it is, just writes to the panel, which I could already do...
>
and
> Maybe I'm misunderstanding something, should I be overriding the control paint method with a paint event for  >the panel, and in that panel paint event call the base.OnPaint(e)?

Suddenly, you've confused me....

You have a custom control.
Within that custom control is a panel.
you want to draw a square within the PANEL that is within the CONTROL on the "onPaint" method, yes?

-john



0
 
yaronusaAuthor Commented:
Yes, I would like to do that, that is correct. I would prefer the "onPaint" method belong to the panel that is IN the control, but I'll take it ANYWAY  I can get it! :)
0
 
jgordosCommented:
Okay, good! I understand the problem again!

In the routine

GridCustomControl_Paint

if you call

base.OnPaint(e);

You're crashing?

-john
0
 
jgordosCommented:
Oh shit.

Are you extending "Control" or "UserControl"?

-john
0
 
yaronusaAuthor Commented:
this is correct, that line makes me crash. Without the line, it doesn't crash.

You can see the line in the code snippet.
private void GridCustomControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e); //This line causes C# VS to crash
            Graphics dc = e.Graphics;
            Console.WriteLine("in pnlMain_Paint");
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
            dc.Dispose();
        }

Open in new window

0
 
yaronusaAuthor Commented:
I don't think I'm extending it, I basically created a control and dragged and dropped a panel into it in design mode. Here is the full code for the full user custom control:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
 
namespace gridCustomControl
{
    public partial class GridCustomControl : System.Windows.Forms.Control
    {
        public GridCustomControl()
        {
            InitializeComponent();
        }
 
        private void GridCustomControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e); //This line causes C# VS to crash
            Graphics dc = e.Graphics;
            Console.WriteLine("in pnlMain_Paint");
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
            dc.Dispose();
        }
 
        private void pnlMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Graphics dc = e.Graphics;
            Console.WriteLine("in pnlMain_Paint");
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
            dc.Dispose();
        }
    } // End Class GridCustomControl
} // End namespace gridCustomControl

Open in new window

0
 
jgordosCommented:
change what you're inheriting from to UserControl

-j
0
 
yaronusaAuthor Commented:
OK I tried that just now, when I run the program, I get a blank form nothing drawn on it.

Here's my current code below... something maybe I'm missing?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
 
namespace gridCustomControl
{
    public partial class GridCustomControl : UserControl
    {
        public GridCustomControl()
        {
            InitializeComponent();
        }
 
        private void GridCustomControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //Graphics dc = e.Graphics;
            //Console.WriteLine("in pnlMain_Paint");
            //Pen blackPen = new Pen(Color.Black, 1);
            //Point topLeftRec = new Point(0, 0);
            //Size howBig = new Size(75, 75);
            //Rectangle rec = new Rectangle(topLeftRec, howBig);
            //dc.DrawRectangle(blackPen, rec);
            //blackPen.Dispose();
        }
 
        private void pnlMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Graphics dc = e.Graphics;
            Console.WriteLine("in pnlMain_Paint");
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
        }
    } // End Class GridCustomControl
} // End namespace gridCustomControl

Open in new window

0
 
jgordosCommented:
okay...

now name the paint method IN THE CONTROL

protected override void OnPaint(PaintEventArgs e)


that should get you a paint method for the custom control

0
 
yaronusaAuthor Commented:
I renamed:

private void GridCustomControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

TO:

protected override void GridCustomControl_Paint(object sender, PaintEventArgs e)

What's next?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
 
namespace gridCustomControl
{
    public partial class GridCustomControl : UserControl
    {
        public GridCustomControl()
        {
            InitializeComponent();
        }
 
        // igordos: is this what you wanted me to type?
        protected override void GridCustomControl_Paint(object sender, PaintEventArgs e)
        {
            //Graphics dc = e.Graphics;
            //Console.WriteLine("in pnlMain_Paint");
            //Pen blackPen = new Pen(Color.Black, 1);
            //Point topLeftRec = new Point(0, 0);
            //Size howBig = new Size(75, 75);
            //Rectangle rec = new Rectangle(topLeftRec, howBig);
            //dc.DrawRectangle(blackPen, rec);
            //blackPen.Dispose();
        }
 
        private void pnlMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //Graphics dc = e.Graphics;
            //Console.WriteLine("in pnlMain_Paint");
            //Pen blackPen = new Pen(Color.Black, 1);
            //Point topLeftRec = new Point(0, 0);
            //Size howBig = new Size(75, 75);
            //Rectangle rec = new Rectangle(topLeftRec, howBig);
            //dc.DrawRectangle(blackPen, rec);
            //blackPen.Dispose();
        }
    } 
} 

Open in new window

0
 
jgordosCommented:
yes, that's right...

Now, the custom control has a paint method...

Now, here's the ROOT OF OUR PROBLEM!

The custom control (to your way of thinking) has some "sub controls" on it.

You want to call the paint method of the panel, yes?

First things, first...

in the paint method do

base.OnPaint(e);

then...

plnMain_Paint( e );

That should get us pretty close...

-john




0
 
yaronusaAuthor Commented:
Before implementing your above suggestion, I'm getting an error:

Error      1      'gridCustomControl.GridCustomControl.GridCustomControl_Paint_1(object, System.Windows.Forms.PaintEventArgs)': no suitable method found to override      C:\Users\PMC TB3\Documents\Visual Studio 2005\Projects\gridCustomControl\gridCustomControl\GridCustomControl.cs      19      33      gridCustomControl

No suitable method to override... should i change something?
namespace gridCustomControl
{
    public partial class GridCustomControl : UserControl
    {
        public GridCustomControl()
        {
            InitializeComponent();
        }
 
        // igordos: the following line has the error:
        protected override void GridCustomControl_Paint(object sender, PaintEventArgs e)
        {
            //Graphics dc = e.Graphics;
            //Console.WriteLine("in pnlMain_Paint");
            //Pen blackPen = new Pen(Color.Black, 1);
            //Point topLeftRec = new Point(0, 0);
            //Size howBig = new Size(75, 75);
            //Rectangle rec = new Rectangle(topLeftRec, howBig);
            //dc.DrawRectangle(blackPen, rec);
            //blackPen.Dispose();
        }
 
        private void pnlMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //Graphics dc = e.Graphics;
            //Console.WriteLine("in pnlMain_Paint");
            //Pen blackPen = new Pen(Color.Black, 1);
            //Point topLeftRec = new Point(0, 0);
            //Size howBig = new Size(75, 75);
            //Rectangle rec = new Rectangle(topLeftRec, howBig);
            //dc.DrawRectangle(blackPen, rec);
            //blackPen.Dispose();
        }
 
    } 
} 

Open in new window

0
 
jgordosCommented:
try calling it

OnPaint

not

GridCustomControl_Paint

-j
0
 
yaronusaAuthor Commented:
OK, so far so good. The snippet of code has what I have so far.

It compiles and runs. But the square is drawn on the Form, not in the panel.

What should we do next?
namespace gridCustomControl
{
    public partial class GridCustomControl : UserControl
    {
        public GridCustomControl()
        {
            InitializeComponent();
        }
 
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            pnlMain_Paint(pnlMain, e);
        }
 
        private void pnlMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Graphics dc = e.Graphics;
            Console.WriteLine("in pnlMain_Paint");
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
        }
    } 
} 

Open in new window

0
 
yaronusaAuthor Commented:
OK  I just did that, same result as before so far... Here's the snippet:
namespace gridCustomControl
{
    public partial class GridCustomControl : UserControl
    {
        public GridCustomControl()
        {
            InitializeComponent();
        }
 
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            pnlMain_Paint(pnlMain, e);
            
        }
 
        private void pnlMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics dc = e.Graphics;
            Console.WriteLine("in pnlMain_Paint");
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = new Point(0, 0);
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
            blackPen.Dispose();
        }
    } 
} 

Open in new window

0
 
jgordosCommented:
good!

Now, we've got a paint loop working for the panel...

The reason it looks odd to you is the topLeftRect really isn't a rect... you just set it (arbitrarily) to 0,0

You now need to base it from the topleft corner of the panel you installed...

So, get the rect of the panel, and add it's top left corner to the co-ordinates of the square you want....
0
 
yaronusaAuthor Commented:
The panel is hiding the rectangle. It is like they are on different layers, with the panel being on top, and the rectangle hidden behind it..
0
 
yaronusaAuthor Commented:
I don't know if the following will help, but this is the code I used when drawing IN a panel that was IN a regular form.

The rectangle shows up on top of the panel:
private void pnlClientView_Paint(object sender, PaintEventArgs e)
        {
            Graphics dc = e.Graphics;
            Size scrollOffset = new Size(pnlClientView.AutoScrollPosition);
            Pen blackPen = new Pen(Color.Black, 1);
            Point topLeftRec = (Point)scrollOffset;
            Size howBig = new Size(75, 75);
            Rectangle rec = new Rectangle(topLeftRec, howBig);
            dc.DrawRectangle(blackPen, rec);
        }

Open in new window

0
 
yaronusaAuthor Commented:
It was my mistake the rectangle was showing up behind the panel, it was just an illusion, your solution worked ...  thanks so much for helping a newbie...  you put a lot of effort.... till next time... =)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.