Solved

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

Posted on 2008-06-23
33
7,699 Views
Last Modified: 2010-04-21
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

0
Comment
Question by:yaronusa
  • 18
  • 15
33 Comments
 
LVL 11

Expert Comment

by:jgordos
ID: 21846539
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
 

Author Comment

by:yaronusa
ID: 21846619
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21846772
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
 

Author Comment

by:yaronusa
ID: 21846775
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21846838
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
 

Author Comment

by:yaronusa
ID: 21846877
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
 

Author Comment

by:yaronusa
ID: 21846934
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21846951
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
 

Author Comment

by:yaronusa
ID: 21847075
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21847255
Graphics dc = e.Graphics;
0
 
LVL 11

Expert Comment

by:jgordos
ID: 21847258
And, remember, first thing in the paint method should be


base.OnPaint(e);

-john
0
 

Author Comment

by:yaronusa
ID: 21847397
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
 

Author Comment

by:yaronusa
ID: 21847507
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21848078
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
 

Author Comment

by:yaronusa
ID: 21848154
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21848238
Okay, good! I understand the problem again!

In the routine

GridCustomControl_Paint

if you call

base.OnPaint(e);

You're crashing?

-john
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 11

Expert Comment

by:jgordos
ID: 21848263
Oh shit.

Are you extending "Control" or "UserControl"?

-john
0
 

Author Comment

by:yaronusa
ID: 21848271
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
 

Author Comment

by:yaronusa
ID: 21848288
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21848355
change what you're inheriting from to UserControl

-j
0
 

Author Comment

by:yaronusa
ID: 21848413
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21848486
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
 

Author Comment

by:yaronusa
ID: 21848610
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21848722
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
 

Author Comment

by:yaronusa
ID: 21848819
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21848956
try calling it

OnPaint

not

GridCustomControl_Paint

-j
0
 

Author Comment

by:yaronusa
ID: 21849031
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
 
LVL 11

Accepted Solution

by:
jgordos earned 500 total points
ID: 21849116
well, we're getting close!

now, add

base.OnPaint(e);

as the first line of

pnlMain_Paint

-john
0
 

Author Comment

by:yaronusa
ID: 21849167
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
 
LVL 11

Expert Comment

by:jgordos
ID: 21849258
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
 

Author Comment

by:yaronusa
ID: 21849344
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
 

Author Comment

by:yaronusa
ID: 21849446
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
 

Author Closing Comment

by:yaronusa
ID: 31469752
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

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now