Namely what I mean. I created my MyTableLayoutPanel control, which almost completely coincides with the base one, with the exception of three redefined events. I redefined them so that it would be possible to move controls in form, here’s the code itself.

 class MyTableLayoutPanel:TableLayoutPanel { //Ρ‚ΠΎΡ‡ΠΊΠ° пСрСмСщСния Point DownPoint; //Π½Π°ΠΆΠ°Ρ‚Π° Π»ΠΈ ΠΊΠ½ΠΎΠΏΠΊΠ° ΠΌΡ‹ΡˆΠΈ bool IsDragMode; protected override void OnMouseDown(MouseEventArgs mevent) { DownPoint = mevent.Location; IsDragMode = true; base.OnMouseDown(mevent); } protected override void OnMouseUp(MouseEventArgs mevent) { IsDragMode = false; base.OnMouseUp(mevent); } protected override void OnMouseMove(MouseEventArgs mevent) { //Ссли ΠΊΠ½ΠΎΠΏΠΊΠ° ΠΌΡ‹ΡˆΠΈ Π½Π°ΠΆΠ°Ρ‚Π° if (IsDragMode) { Point p = mevent.Location; //вычисляСм Ρ€Π°Π·Π½ΠΈΡ†Ρƒ Π² ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°Ρ… ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ курсора ΠΈ "Π½ΡƒΠ»Π΅Π²ΠΎΠΉ" Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ ΠΊΠ½ΠΎΠΏΠΊΠΈ Point dp = new Point(pX - DownPoint.X, pY - DownPoint.Y); Location = new Point(Location.X + dp.X, Location.Y + dp.Y); } base.OnMouseMove(mevent); } } 

Everything works as it should, control moves, no errors. Further. In MyTableLayoutPanel I place pictures or buttons. Actually the question is how to press the pictures, move MyTableLayoutPanel , and not a picture or button?

    1 answer 1

    As such, the routing of events between the parent and child controls in WinForms is not provided, it is only in WPF. But you can partially simulate the routing of events from the child to the parent and use the following simple technique:

     public partial class MyTableLayoutPanel:TableLayoutPanel { public MyTableLayoutPanel() { InitializeComponent(); // ΠŸΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°Π΅ΠΌΡΡ Π½Π° событиС добавлСния Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π° this.ControlAdded += MyTableLayoutPanel_ControlAdded; // ΠŸΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°Π΅ΠΌΡΡ Π½Π° событиС удалСния Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π° this.ControlRemoved += MyTableLayoutPanel_ControlRemoved; } 

    The Control.ControlAdded and Control.ControlRemoved events are triggered when child controls are added to the control. We will use this in order not to subscribe by hand to the events of the child controls to perform actions on the container.

      void MyTableLayoutPanel_ControlAdded(object sender, ControlEventArgs e) { // ДобавляСм свои ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΊ Π½ΡƒΠΆΠ½Ρ‹ΠΌ событиям Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π° // ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ добавляСтся Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ e.Control.MouseUp += MouseUpHandler; e.Control.MouseDown += MouseDownHandler; e.Control.MouseMove += MouseMoveHandler; } void MyTableLayoutPanel_ControlRemoved(object sender, ControlEventArgs e) { // НС Π·Π°Π±Ρ‹Π²Π°Π΅ΠΌ ΠΎΡ‚ΠΏΠΈΡΠ°Ρ‚ΡŒ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ» ΠΎΡ‚ Π½Π°ΡˆΠΈΡ… ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² ΠΏΡ€ΠΈ Π΅Π³ΠΎ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠΈ, // Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΡƒΠ΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ ссылку Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ дольшС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠ³ΠΎ e.Control.MouseUp -= MouseUpHandler; e.Control.MouseDown -= MouseDownHandler; e.Control.MouseMove -= MouseMoveHandler; } 

    Events are based on delegates, and the delegate keeps a reference to the object whose method has been passed to it, so in order not to get a memory leak, do not forget to unsubscribe from the events when removing the control from the parent container. Also, in the handler of the ContolAdded event, you can make additional settings for the properties of the child controls.

    And finally, we describe the handlers of the events we need to manage the parent container.

      private void MouseUpHandler(object sender, MouseEventArgs e) { MouseEventArgs newArgs = new MouseEventArgs( e.Button, e.Clicks, ((Control)sender).Location.X+eX, ((Control)sender).Location.Y+eY, e.Delta); OnMouseUp(newArgs); } // ΠΈ Ρ‚Π°ΠΊ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ события, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π² Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ } 

    If everything is done correctly, your child controls will also call the handlers of the parent container. One more nuance, the handler of the parent container must carefully check who caused it and transfer the coordinates from the coordinate system of the child control to its own, if of course it receives the coordinates in the event arguments and uses them. It may also concern other event arguments, so be careful when developing the logic of such forced event handlers.

    Also read this question and answers , there is proposed a solution that may be suitable for your purposes.

    Another solution is to switch to WPF and use event routing, which is available there without out-of-the-box shamanism.

    • Did not quite understand your example. Those. I need to add 4 more event handlers to mine that already exist? And what do you mean by UseControl for my example, child or parent? Please explain, until I figured it out. - Pyrejkee
    • I hope it became clearer. In general, yes, you caught the idea, since the event cannot be transmitted, we call the handler after catching it in another control. Just don’t enter OnSomthing calls OnSomthing(EventArgs e) into the plugin handler. it triggers an event and this will result in a stack overflow. - rdorn
    • this.ControlAdded += MyTableLayoutPanel_ControlAdded; If the child is a regular button, I should have this. this.MyButtonAdded += MyTableLayoutPanel_MyButtonAdded; ? if yes, then the terms of error ... something I did not catch .. ( - Pyrejkee
    • yes no, the code that is in the example is enough. right as it is. The only thing is to replace the subscription to the click event with the subscriptions you need. Well, at least glance at MSDN in the description of the events ControlAdded and CotrolRemoved - rdorn
    • Directly in the form as it is - a bunch of errors causes. - Pyrejkee