Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. CRTP in c#/.NET?

CRTP in c#/.NET?

Scheduled Pinned Locked Moved C#
csharpquestionc++helplearning
7 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    pr1mem0ver
    wrote on last edited by
    #1

    I found different solutions to this sort of CRTP problem previously... but can't think of a way around it this time. The main form used by my current project allows for moving and resizing even when it doesn't have a border. I have seen other people ask about this particular need before (it seems like a fairly common need for custom forms) and I have developed a better solution than what I have seen for answers online. I would like to provide a more generic solution than the one I am using currently for myself and others if possible so hence... my asking this prerequisite question beforehand. I am needing to create several "controls" in my current project that have this same exact behavior so I want to write an inheritable class for all of them. Simple enough... just write a template that derives from Control. The problem is that none of the derived classes will look and perform like their actual base class in every other way without some way to use a CRTP. It would be nice not to have to write separate base classes for all the seperate possible control types, including forms. Is there a way to write a generic class to cover all controls that one would want to use? Something that effectively does what this would do if this were c++? (I realize that the where statement is c# but there are ways to accomplish the same basic idea in c++).

    public class MovableControl : InheritedControl where InheritedControl : Control
    {
    //...
    }

    In c# the above class definition doesn't compile because in .NET inheriting from a template parameter is not allowed (which is why I need an alternative solution.). Of course I will continue hunting on my own, or worst case, brute force it (by creating the separate classes) but I thought I would ask here in case someone already had an idea.

    B L 2 Replies Last reply
    0
    • P pr1mem0ver

      I found different solutions to this sort of CRTP problem previously... but can't think of a way around it this time. The main form used by my current project allows for moving and resizing even when it doesn't have a border. I have seen other people ask about this particular need before (it seems like a fairly common need for custom forms) and I have developed a better solution than what I have seen for answers online. I would like to provide a more generic solution than the one I am using currently for myself and others if possible so hence... my asking this prerequisite question beforehand. I am needing to create several "controls" in my current project that have this same exact behavior so I want to write an inheritable class for all of them. Simple enough... just write a template that derives from Control. The problem is that none of the derived classes will look and perform like their actual base class in every other way without some way to use a CRTP. It would be nice not to have to write separate base classes for all the seperate possible control types, including forms. Is there a way to write a generic class to cover all controls that one would want to use? Something that effectively does what this would do if this were c++? (I realize that the where statement is c# but there are ways to accomplish the same basic idea in c++).

      public class MovableControl : InheritedControl where InheritedControl : Control
      {
      //...
      }

      In c# the above class definition doesn't compile because in .NET inheriting from a template parameter is not allowed (which is why I need an alternative solution.). Of course I will continue hunting on my own, or worst case, brute force it (by creating the separate classes) but I thought I would ask here in case someone already had an idea.

      B Offline
      B Offline
      BillWoodruff
      wrote on last edited by
      #2

      I will be posting this as a Tip/Trick or Article here in the future with comments and explanations, but, I'm in a rush right now, and don't have time to revise/comment my extended version of this, but, this should give you some ideas. In a Form Load eventhandler, make some Controls movable like this: button1.SetMovable(); textBox1.SetMovable(); panel1.SetMovable(); The code:

      using System;
      using System.Collections.Generic;
      using System.Drawing;
      using System.Windows.Forms;

      namespace YOURNAMESPACE
      {
      public static class ControlMovableExtensions
      {
      private static Control currentControl = null;

          private static Control currentContainer= null;
      
          private static List MovableControls = new List();
      
          private static Rectangle ClippingRect;
      
          private static Rectangle ContainerRect;
      
          private static Point lastGoodLocation;
      
          private static Point nextLocation;
      
          private static int mdx, mdy;
      
          private static bool IsMouseUp = true;
      
          // experiment with these settings
          private static bool UseClipping = false;
          private static bool UseCapture = false;
      
          public static void SetMovable(this Control control)
          {
              if (MovableControls.Contains(control))
              {
                  throw new ArgumentException("control already movable");
              }
      
              MovableControls.Add(control);
      
              control.MouseDown += ControlOnMouseDown;
              control.MouseUp += ControlOnMouseUp;
          }
      
          public static void RemoveMovable(this Control control)
          {
              if (! MovableControls.Contains(control))
              {
                  throw new ArgumentException("control is not movable");
              }
      
              control.MouseDown -= ControlOnMouseDown;
              control.MouseUp -= ControlOnMouseUp;
          }
      
          private static void ControlOnMouseMove(object sender, MouseEventArgs e)
          {
              if (IsMouseUp) return;
      
              nextLocation =  new Point(currentControl.Left + e.X - mdx, currentControl.Top + e.Y - mdy);
      
              if (ContainerRect.Contains(new Rectangle(nextLocation, currentControl.Size)))
              {
                  lastGoodLocation = nextLocation;
              }
      
              currentControl.Location = lastGoodLocation;
          }
      
          private static void ControlOnMouseUp(object sender, MouseEventArgs e)
          {
      
      P 1 Reply Last reply
      0
      • B BillWoodruff

        I will be posting this as a Tip/Trick or Article here in the future with comments and explanations, but, I'm in a rush right now, and don't have time to revise/comment my extended version of this, but, this should give you some ideas. In a Form Load eventhandler, make some Controls movable like this: button1.SetMovable(); textBox1.SetMovable(); panel1.SetMovable(); The code:

        using System;
        using System.Collections.Generic;
        using System.Drawing;
        using System.Windows.Forms;

        namespace YOURNAMESPACE
        {
        public static class ControlMovableExtensions
        {
        private static Control currentControl = null;

            private static Control currentContainer= null;
        
            private static List MovableControls = new List();
        
            private static Rectangle ClippingRect;
        
            private static Rectangle ContainerRect;
        
            private static Point lastGoodLocation;
        
            private static Point nextLocation;
        
            private static int mdx, mdy;
        
            private static bool IsMouseUp = true;
        
            // experiment with these settings
            private static bool UseClipping = false;
            private static bool UseCapture = false;
        
            public static void SetMovable(this Control control)
            {
                if (MovableControls.Contains(control))
                {
                    throw new ArgumentException("control already movable");
                }
        
                MovableControls.Add(control);
        
                control.MouseDown += ControlOnMouseDown;
                control.MouseUp += ControlOnMouseUp;
            }
        
            public static void RemoveMovable(this Control control)
            {
                if (! MovableControls.Contains(control))
                {
                    throw new ArgumentException("control is not movable");
                }
        
                control.MouseDown -= ControlOnMouseDown;
                control.MouseUp -= ControlOnMouseUp;
            }
        
            private static void ControlOnMouseMove(object sender, MouseEventArgs e)
            {
                if (IsMouseUp) return;
        
                nextLocation =  new Point(currentControl.Left + e.X - mdx, currentControl.Top + e.Y - mdy);
        
                if (ContainerRect.Contains(new Rectangle(nextLocation, currentControl.Size)))
                {
                    lastGoodLocation = nextLocation;
                }
        
                currentControl.Location = lastGoodLocation;
            }
        
            private static void ControlOnMouseUp(object sender, MouseEventArgs e)
            {
        
        P Offline
        P Offline
        pr1mem0ver
        wrote on last edited by
        #3

        Interesting approach using extensions. That may work. The one problem is overriding the WndProc as that is the best way to detect resizing attempts. I supposed the override can call a static method... but that is a bit strange unless we can successfully use aggressive inlining. Perhaps we can combine our ideas and write the article together since my approach is very efficient and almost works just like an ordinary window. (There is a bit of a flicker when resizing upward and left but it still works well).

        B 1 Reply Last reply
        0
        • P pr1mem0ver

          Interesting approach using extensions. That may work. The one problem is overriding the WndProc as that is the best way to detect resizing attempts. I supposed the override can call a static method... but that is a bit strange unless we can successfully use aggressive inlining. Perhaps we can combine our ideas and write the article together since my approach is very efficient and almost works just like an ordinary window. (There is a bit of a flicker when resizing upward and left but it still works well).

          B Offline
          B Offline
          BillWoodruff
          wrote on last edited by
          #4

          Hi, Yes, it does work :) I am not sure why you are bringing in WndProc here, for me, use of WndProc is a last resort, and that's even more so now that .NET Core is evolving rapidly. I use different techniques to handle the rare case when a user needs to arbitrarily re-size a Control at run-time. I look forward to reading your article. cheers, Bill

          «Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot

          1 Reply Last reply
          0
          • P pr1mem0ver

            I found different solutions to this sort of CRTP problem previously... but can't think of a way around it this time. The main form used by my current project allows for moving and resizing even when it doesn't have a border. I have seen other people ask about this particular need before (it seems like a fairly common need for custom forms) and I have developed a better solution than what I have seen for answers online. I would like to provide a more generic solution than the one I am using currently for myself and others if possible so hence... my asking this prerequisite question beforehand. I am needing to create several "controls" in my current project that have this same exact behavior so I want to write an inheritable class for all of them. Simple enough... just write a template that derives from Control. The problem is that none of the derived classes will look and perform like their actual base class in every other way without some way to use a CRTP. It would be nice not to have to write separate base classes for all the seperate possible control types, including forms. Is there a way to write a generic class to cover all controls that one would want to use? Something that effectively does what this would do if this were c++? (I realize that the where statement is c# but there are ways to accomplish the same basic idea in c++).

            public class MovableControl : InheritedControl where InheritedControl : Control
            {
            //...
            }

            In c# the above class definition doesn't compile because in .NET inheriting from a template parameter is not allowed (which is why I need an alternative solution.). Of course I will continue hunting on my own, or worst case, brute force it (by creating the separate classes) but I thought I would ask here in case someone already had an idea.

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            Use a proxy. Move / resize the proxy; when done, copy the properties to the original target.

            "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

            B P 2 Replies Last reply
            0
            • L Lost User

              Use a proxy. Move / resize the proxy; when done, copy the properties to the original target.

              "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

              B Offline
              B Offline
              BillWoodruff
              wrote on last edited by
              #6

              That's an interesting approach, one that seems like what goes on with drag-drop. In what kind of scenario would you use this rather than just move the Control ? thanks, Bill

              «Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot

              1 Reply Last reply
              0
              • L Lost User

                Use a proxy. Move / resize the proxy; when done, copy the properties to the original target.

                "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

                P Offline
                P Offline
                pr1mem0ver
                wrote on last edited by
                #7

                I actually am using a proxy system. However, the main window also uses the same (similar in the case of move) system since it is a border-less form. That is why I posted this topic to begin with. I want to write one set of code for both forms and controls.

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups