473,405 Members | 2,379 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

How to add a MouseEvent to a Control inside a Panel with an existing MouseEvent

In a WinForms Application, I've created a Figure class that extends Control. This class gets instantiated
Expand|Select|Wrap|Line Numbers
  1. figureArray[i] = new Figure(x, y, width, height, thickness, color, type);
whenever I RightClick on a Panel "canvas"..
Long story short, each instance draws a graphic inside the Canvas.

Now I also want to trace the instances in my Panel by clicking on them.
So when I instantiate the Figure, I also add a MouseEvent to it:
Expand|Select|Wrap|Line Numbers
  1. figureArray[i].MouseClick += new MouseEventHandler(figure_click_function);
However, figure_click_function never fires.. I assume it's because my figures are inside the Panel which in turn also has a MouseEvent (the mouse event that gets them drawn/instantiated). So when I click on a figure, it really just clicks on the canvas Panel.

I tried
Expand|Select|Wrap|Line Numbers
  1. figureArray[i].BringToFront();
but it's still just a graphic inside the Panel and doesn't get clicked.

How can I both paint these objects and later click on them to identify each?
Oct 20 '10 #1

✓ answered by GaryTexmo

Hrm... I'm not sure what you're doing wrong. I wrote the following code based entirely off your description and am having absolutely no troubles whatsoever. If anything, I'd be frustrated by my panel not getting the click event because the figure intercepted it.

Can you please take a look at this and post back to let us know what the problem was?

Note, this is on a form with a panel on it named panel1...

Expand|Select|Wrap|Line Numbers
  1.     public partial class Form1 : Form
  2.     {
  3.         List<Figure> m_figureList = new List<Figure>();
  4.  
  5.         public Form1()
  6.         {
  7.             InitializeComponent();
  8.         }
  9.  
  10.         //void f_Click(object sender, EventArgs e)
  11.         //{
  12.         //    if (sender is Figure)
  13.         //    {
  14.         //        ((Figure)sender).BringToFront();
  15.         //    }
  16.         //}
  17.  
  18.         void f_MouseClick(object sender, MouseEventArgs e)
  19.         {
  20.             if (sender is Figure)
  21.             {
  22.                 ((Figure)sender).BringToFront();
  23.             }
  24.         }
  25.  
  26.         private void panel1_MouseClick(object sender, MouseEventArgs e)
  27.         {
  28.             switch (e.Button)
  29.             {
  30.                 case MouseButtons.Left:
  31.                     Figure f = new Figure("Figure " + (m_figureList.Count + 1).ToString(), e.X, e.Y, 150, 100);
  32.                     //f.Click += new EventHandler(f_Click);
  33.                     f.MouseClick += new MouseEventHandler(f_MouseClick);
  34.  
  35.                     m_figureList.Add(f);
  36.                     panel1.Controls.Add(f);
  37.  
  38.                     f.BringToFront();
  39.                     break;
  40.             }
  41.         }
  42.     }
  43.  
  44.     public class Figure : Control
  45.     {
  46.         public Figure(string text, int x, int y, int width, int height)
  47.             : base(text, x, y, width, height)
  48.         {
  49.         }
  50.  
  51.         protected override void OnPaint(PaintEventArgs e)
  52.         {
  53.             base.OnPaint(e);
  54.  
  55.             Graphics g = e.Graphics;
  56.             g.FillRectangle(Brushes.White, this.ClientRectangle);
  57.             g.FillRectangle(Brushes.LightGray, this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width, (int)(this.Font.Height * 1.25));
  58.             g.DrawString(this.Text, this.Font, Brushes.Black, new Point(this.ClientRectangle.X + (int)(this.ClientRectangle.Width / 2 - g.MeasureString(this.Text, this.Font).Width / 2), this.ClientRectangle.Y + (int)(this.Font.Height * 1.25 / 2 - this.Font.Height / 2)));
  59.             g.DrawRectangle(Pens.Black, this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1);
  60.             g.DrawLine(Pens.Black, new Point(this.ClientRectangle.X, (int)(this.Font.Height * 1.25)), new Point(this.ClientRectangle.X + this.ClientRectangle.Width - 1, (int)(this.Font.Height * 1.25)));
  61.         }
  62.     }

9 2757
GaryTexmo
1,501 Expert 1GB
Hrm... I'm not sure what you're doing wrong. I wrote the following code based entirely off your description and am having absolutely no troubles whatsoever. If anything, I'd be frustrated by my panel not getting the click event because the figure intercepted it.

Can you please take a look at this and post back to let us know what the problem was?

Note, this is on a form with a panel on it named panel1...

Expand|Select|Wrap|Line Numbers
  1.     public partial class Form1 : Form
  2.     {
  3.         List<Figure> m_figureList = new List<Figure>();
  4.  
  5.         public Form1()
  6.         {
  7.             InitializeComponent();
  8.         }
  9.  
  10.         //void f_Click(object sender, EventArgs e)
  11.         //{
  12.         //    if (sender is Figure)
  13.         //    {
  14.         //        ((Figure)sender).BringToFront();
  15.         //    }
  16.         //}
  17.  
  18.         void f_MouseClick(object sender, MouseEventArgs e)
  19.         {
  20.             if (sender is Figure)
  21.             {
  22.                 ((Figure)sender).BringToFront();
  23.             }
  24.         }
  25.  
  26.         private void panel1_MouseClick(object sender, MouseEventArgs e)
  27.         {
  28.             switch (e.Button)
  29.             {
  30.                 case MouseButtons.Left:
  31.                     Figure f = new Figure("Figure " + (m_figureList.Count + 1).ToString(), e.X, e.Y, 150, 100);
  32.                     //f.Click += new EventHandler(f_Click);
  33.                     f.MouseClick += new MouseEventHandler(f_MouseClick);
  34.  
  35.                     m_figureList.Add(f);
  36.                     panel1.Controls.Add(f);
  37.  
  38.                     f.BringToFront();
  39.                     break;
  40.             }
  41.         }
  42.     }
  43.  
  44.     public class Figure : Control
  45.     {
  46.         public Figure(string text, int x, int y, int width, int height)
  47.             : base(text, x, y, width, height)
  48.         {
  49.         }
  50.  
  51.         protected override void OnPaint(PaintEventArgs e)
  52.         {
  53.             base.OnPaint(e);
  54.  
  55.             Graphics g = e.Graphics;
  56.             g.FillRectangle(Brushes.White, this.ClientRectangle);
  57.             g.FillRectangle(Brushes.LightGray, this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width, (int)(this.Font.Height * 1.25));
  58.             g.DrawString(this.Text, this.Font, Brushes.Black, new Point(this.ClientRectangle.X + (int)(this.ClientRectangle.Width / 2 - g.MeasureString(this.Text, this.Font).Width / 2), this.ClientRectangle.Y + (int)(this.Font.Height * 1.25 / 2 - this.Font.Height / 2)));
  59.             g.DrawRectangle(Pens.Black, this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1);
  60.             g.DrawLine(Pens.Black, new Point(this.ClientRectangle.X, (int)(this.Font.Height * 1.25)), new Point(this.ClientRectangle.X + this.ClientRectangle.Width - 1, (int)(this.Font.Height * 1.25)));
  61.         }
  62.     }
Oct 20 '10 #2
GaryTexmo
1,501 Expert 1GB
Oh, it occurred to me... are you adding your figures to the controls list of your panel, or are you manually drawing them via your figures array in your panel's paint method?

If the latter, that would explain why the click method doesn't go to the figure. I'd recommend taking the approach I used, but if you don't want to then you'll need to check your mouse click location against all the client rectangles of the figures, then fire the Clicked event for the figures themselves.
Oct 20 '10 #3
It still doesn't work but you've helped a lot! :D

I was trying to add the figure to panel1's control list by doing
Expand|Select|Wrap|Line Numbers
  1. figureArray[i].Parent = panel1;
(which is stupid, but I was baffled by not finding a panel1.AddChild method like in Flash :P; didn't think of looking in panel1.Controls for some reason)

Regarding your second post, yes, I store the figures in a
Expand|Select|Wrap|Line Numbers
  1. Figure[limit] figureArray
and am manually drawing them to panel1 in it's paint method, by sending the panel's paint event args to a figureArray[i].my_paint_method(e). I did this trying to have persistent graphics (so they'd all redraw when I resize, minimize etc).

But, what I'm doing now is, I'm also adding them to the controls list of my panel1 AND they're still painted manually in the panel1's paint event.
It obviously doesn't work, but if I'm not supposed to manually paint them, how exactly do I paint them at all?
Oct 21 '10 #4
[EDIT] I hadn't noticed the
Expand|Select|Wrap|Line Numbers
  1. protected override void OnPaint(PaintEventArgs e)
override you posted, it was early in the morning..
So now I've done basically what you did in your example, and all the events fire, EXCEPT I can't see any of the objects I paint. I know they're there, and the
Expand|Select|Wrap|Line Numbers
  1. void f_MouseClick(object sender, MouseEventArgs e)
confirms it, but for some reason the paint override method doesn't actually show the objects on the panel when I paint them.. I tried invalidate() but no luck.

To be more clear, the objects DO get "painted", but I don't see them. When I click on the panel, in a spot where I know I will be hitting a square, the MouseEvent fires with the properties of that instance.. They're invisible.
Oct 21 '10 #5
GaryTexmo
1,501 Expert 1GB
Glad you were able to make some progress :)

As for why your figures aren't drawing, did you move your drawing code from the panel's paint method to the paint method for the figure itself? Please check my example... OnPaint is a method built into the control (that I've overridden) and gets called automatically when the panel tries to draw it's children. Since you mentioned this above I'm pretty sure you know this, but I figured I'd check.

Can you post the relevant bits of your code? What I often find helps is to boil your project down to something simpler and debug from there. If you can isolate your drawing code from the rest of it, and you still have that issue, then you're dealing with a lot less code to debug.
Oct 21 '10 #6
Thanks for your patienece.

I had some more time and fiddled around for an hour and a half but still can't figure out what's going on..
I've posted the relevant code from my project (it's not much) and here is a screenshot of a very peculiar thing I've noticed: http://img64.imageshack.us/img64/912/jeeze.jpg

My figures seem to have white squares as borders around them. So they overlap and the white stuff covers the figures below. But what really baffles me is why the only place my figures are actually somewhat visible is that small corner.

Also, my clearCanvas method doesn't work anymore. It used to work fine when I was painting things manually using the panel's paint method.

Note than my "Figure" object is actually called Brush and stored in brushArray[]. My "panel1" is called canvas.
Expand|Select|Wrap|Line Numbers
  1. public partial class geometryShop : Form
  2.     {
  3.         public int width = 50;
  4.         public int height = 50;
  5.         public int thickness = 3;
  6.         public Color color = Color.IndianRed;
  7.         public string type = "rect";
  8.  
  9.         public Brush[] brushArray = new Brush[256];
  10.         public int brushes_no = -1;
  11.  
  12.         public geometryShop()
  13.         {
  14.             InitializeComponent();
  15.             console2_txt.Text += "[tool] Rectangle selected. \r\n";
  16.             autoScroll();
  17.         }
  18.  
  19.         private int x=0; 
  20.         private int y=0;
  21.  
  22.         private void autoScroll()
  23.         {
  24.             console_txt.SelectionStart = console_txt.Text.Length;
  25.             console_txt.ScrollToCaret();
  26.             console_txt.Refresh();
  27.             console2_txt.SelectionStart = console2_txt.Text.Length;
  28.             console2_txt.ScrollToCaret();
  29.             console2_txt.Refresh();
  30.         }
  31.  
  32.         private void figure_click(object sender, MouseEventArgs e) {
  33.             //console2_txt.Text +=  "YAY???\r\n";
  34.             //if((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
  35.             if (e.Button.ToString() == "Left")
  36.             {
  37.  
  38.                 if (sender is Brush)
  39.                 {
  40.                     ((Brush)sender).BringToFront();
  41.                     Brush tmp = (Brush)sender;
  42.                     console2_txt.Text += "\r\n[" + tmp.Name + "] Clicked: " + tmp.type + "\r\n";
  43.                     autoScroll();
  44.                 }
  45.             }
  46.  
  47.         }
  48.  
  49.         private void canvas_click(object sender, MouseEventArgs e)
  50.         {
  51.             if (e.Button.ToString() == "Right")
  52.             {
  53.                 refreshSize();
  54.                 x = e.X - width / 2 - 1;
  55.                 y = e.Y - height / 2 - 1;
  56.  
  57.  
  58.                 try
  59.                 {
  60.                     brushes_no++;
  61.                     brushArray[brushes_no] = new Brush(x, y, width, height, thickness, color, type);
  62.  
  63.                     brushArray[brushes_no].MouseClick +=new MouseEventHandler(figure_click); //new MouseEventHandler(figure_click);
  64.  
  65.                     canvas.Controls.Add(brushArray[brushes_no]);
  66.                     brushArray[brushes_no].BringToFront();
  67.                     //canvas.Invalidate();
  68.                     Control tmp = (Control)sender; //Determining sender instance name
  69.                     console_txt.Text += "\r\n[" + tmp.Name + "] Instantiated: " + brushArray[brushes_no].type
  70.                                                                                 + ", id=" + brushes_no
  71.                                                                                 + ", pos= " + brushArray[brushes_no].x
  72.                                                                                 + ", " + brushArray[brushes_no].y
  73.                                                                                 + "\r\n";
  74.                     autoScroll();
  75.                 }
  76.                 catch (Exception ex)
  77.                 {
  78.                     console_txt.Text += "[ERR] " + ex.Message + "\r\n";
  79.                     console_txt.Text += ex.StackTrace + "\r\n";
  80.  
  81.                 }
  82.                 //canvas.Invalidate(); //will cause the Paint event to fire
  83.             }
  84.  
  85.         }
  86.  
  87.         private void clearCanvas(object sender, EventArgs e)
  88.         {
  89.             console_txt.Text += "\r\n[!] Cleaning Canvas\r\n";
  90.             autoScroll();
  91.             int j = 0;
  92.             for (j = 0; j <= brushes_no; j++)
  93.             {
  94.                 brushArray[j] = null;
  95.                 canvas.Controls.Remove(brushArray[j]);
  96.                 //i.destroy();
  97.                 console_txt.Text += "x ";
  98.                 autoScroll();
  99.             }
  100.  
  101.             canvas.Invalidate();
  102.             console_txt.Text += "\r\n[!] Done.\r\n";
  103.             autoScroll();
  104.         }
  105.  
My Brush class:
Expand|Select|Wrap|Line Numbers
  1. public Brush(int x, int y, int width, int height, int thickness, Color color, string type): base(type, x, y, width, height)
  2.         {
  3.             this.x = x;
  4.             this.y = y;
  5.             this.width = width;
  6.             this.height = height;
  7.             this.thickness = thickness;
  8.             if (color == Color.White)
  9.             {
  10.                 Random rand = new Random();
  11.                 this.color = Color.FromArgb(rand.Next(256),
  12.                                        rand.Next(256),
  13.                                        rand.Next(256));
  14.             }
  15.             else this.color = color;
  16.             this.type = type;
  17.             this.location = new Point(x, y);
  18.             this.size = new Size(width, height);
  19.             this.rect = new Rectangle(location, size);
  20.         }
  21.  
  22.         protected override void OnPaint(PaintEventArgs e)
  23.         {
  24.             base.OnPaint(e);
  25.             Graphics g = e.Graphics;
  26.  
  27.             Pen pen = new Pen(color, thickness);
  28.             //GraphicsContainer eCon = e.Graphics.BeginContainer();
  29.             g.SmoothingMode = SmoothingMode.AntiAlias;
  30.             g.CompositingQuality = CompositingQuality.GammaCorrected;
  31.             if (type == "ellipse")
  32.                 g.DrawEllipse(pen, x, y, width, height);
  33.             else if (type == "pie")
  34.                 g.DrawPie(pen, rect, width, height);
  35.             else if (type == "arc")
  36.                 g.DrawArc(pen, rect, width, height); 
  37.             else if (type == "rect")
  38.                 g.DrawRectangle(pen, x, y, width, height); 
  39.             pen.Dispose();
  40.             //e.Graphics.Dispose();
  41.  
  42.         }
  43.  
Any ideas why are these control children so messed up inside my panel?
Oct 22 '10 #7
I solved everything eventually..
Thanks a lot for all your help an advice!

I wish there was an edit button to the posts, now I feel like I look a bit foolish :D
Oct 24 '10 #8
GaryTexmo
1,501 Expert 1GB
Haha no worries. What was the problem (so others reading this thread and may have the same issue can get help)? In your code I wasn't seeing where you added it to the controls list or painted it, but I may not be seeing it.

Something else that may help... instead of using an array of brush objects, perhaps consider a List? Right now you're limited to the size you instantiate your array with, currently 256. If you use a List, you can add to that list as much as you want.

Expand|Select|Wrap|Line Numbers
  1. List<Brush> brushes = new List<Brush>();
  2. ...
  3. brushes.Add(new Brush(...));
  4. // etc...
http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx
Oct 25 '10 #9
The problem was me adding x and y (ints grabbed from the mouse position in the click event of the canvas, and sent to the Brush class in it's constructor), instead of adding what you used:
Expand|Select|Wrap|Line Numbers
  1. this.ClientRectangle.X
My problem was that the controls I was adding to the canvas, were of say width=50 and height=50, but their graphic representations (the rectangles, ellipses etc.) were outside that area, because of my wrong x and y coordinates relative to that (50,50); so they never showed..

I used an array because I thought I'd need to access a certain index directly like my_brush[11], but that was never the case. Also, I reasoned that having over 256 movable controls on my canvas would slow things down a lot (and actually, 255 instances make my process cost 11mb of RAM :P)

Also, I did add the controls to the control list:
Expand|Select|Wrap|Line Numbers
  1. canvas.Controls.Add(brushArray[brushes_no]);
Hey, since we're on the same topic.. I noticed that these "Brush:Control" instances I'm adding to the canvas, are all in fact squares. Which means that if I draw an ellipse, it will be drawn inside this little white square (which shows when I overlap 2 objects). Is there any way I can make this canvas-coloured instance-background transparent? (or make it the same shape as the object)
Maybe extending Control wasn't a good idea. (but I don't know if there's anything else I could extend that would be canvas.AddChild-able)

..I also wanted to add a slider that would change the opacity of the things I paint; but it seems there's no such thing as a flash-style slider in C# :(
Oct 27 '10 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

5
by: Georges Heinesch | last post by:
Hi. Is it possible to put a tab control inside another tab control. I tried it several times, but for some reason this doesn't seem to work. Can someone confirm this, or tell me what the trick...
3
by: DC Gringo | last post by:
I've got a web user control (a) inside a web user control (b) inside a webform (c). I need the webform to set a label control text value inside the inner of the two web user control. Inside my...
4
by: huzz | last post by:
I am trying to access a DropDownList control inside a repeater using ItemCommand as shown below but for some reason i can't access the DropDownList. When i step through the debug i get <undefine...
2
by: Henri | last post by:
Hi I would like to use a User Control to render the body of the mail I send. The problem is that my application is not an ASP.NET page so I can't use any Page reference to call LoadControl What...
4
by: Bernie Yaeger | last post by:
I'm building a custom textbox for numbers only (actually two of them - one for integers and one that allows currency entries, but let's discuss the integer only control). I'm having a problem...
0
by: harishashim | last post by:
I'll make this post as short as possible. 1. Put a GroupBox on a window form. Put a Button and TextBox inside the GroupBox . 2. Select the group box, do copy and paste inside the same windows...
2
by: Rob Dob | last post by:
Hi, How do I go about installing another Web Site Project inside my existing VS2005 website project. I currently have both a forum WSP and my main WSP application within the same solution. Both...
0
by: osmarjunior | last post by:
I wanna create a control like Microsoft Outlook 2003 calendar. I'm thinking about to make a control with a DataGridView inside. But how do I host a control inside a cell, in order to resize it or...
0
by: vut.wong | last post by:
Hi, I would like to get use my activex control inside Cdialog in beginthreadex When I used Cdialog and activex control , everything is fine but when i put it inside thread (beginthreadex),...
19
by: hedges98 | last post by:
Sorry for the mouthful of a title! Basically, I have a form with tabbed controls (Personal/Contact Details, Referral Information, Case Info/Status etc.) and I want to add a tabbed control form...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.