简体   繁体   中英

Enable a button to be clicked at design-time in Visual Studio?

My setting: I've got a C# application (.NET 3.5) in Visual Studio 2008. No chance to switch to WPF or whatsoever :).

My app contains a custom control (a button class derived from Windows.Forms.Button) that acts as a replacement for the Windows.Forms.TabControl. I can associate these buttons with one another and each button can be associated with one control that it is dealing with (usually some sort of Windows.Forms.Panel). It looks something like this:

public class TabButton : System.Windows.Forms.Button
{
    // ...
    protected override void OnClick(EventArgs e)
    {
        base.OnClick(e);
        this.myAssociatedControl.Visible = true;
        this.tellMyBuddiesToHideTheirControls();
    }
    // ...
}

Basically it is just about clicking a button, showing its bound control and having the controls bound to the associated buttons disappear - just like the TabControl, but the approach is easily designable and I can place the buttons far from their content panels.

The problem: This works pretty well at runtime, but the usage at design time is arguably odd: With the mouse, find a control that´s belonging to the group and run a series of <Send To Back> s until the desired control is visible.

The question: Is there a way to tell the VS designer to evaluate the clicks on the buttons at design time like it does with the TabControl so that I can switch the tabs just by clicking them like I would at runtime?

I've been searching for quite a while now. There are some articles here at SO but they only seem to cover adding additional attributes to the properties designer.

Edith says: By request, an answer to my own question ...

This is the solution that is suitable to my application. It is basically an example from the msdn with some twists to get the custom designer to use a callback on click. Hope it helps anyone :-).

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
public class TabButtonDesigner : System.Windows.Forms.Design.ControlDesigner
{
    ShowTabGlyph myGlyph = null;
    Adorner myAdorner;

    public TabButtonDesigner()
    {
    }

    public override void Initialize(IComponent component)
    {
        base.Initialize(component);

        // Add the custom set of glyphs using the BehaviorService. 
        // Glyphs live on adornders.
        myAdorner = new Adorner();
        BehaviorService.Adorners.Add(myAdorner);
        myGlyph = new ShowTabGlyph(BehaviorService, Control);
        myGlyph.Callback = () =>
        {
            ((MyCustomTabButton)this.Control).ShowMyTab();
        };
        myAdorner.Glyphs.Add(myGlyph);
    }

    class ShowTabGlyph : Glyph
    {
        Control control;
        BehaviorService behaviorSvc;

        public Action Callback
        {
            get;
            set;
        }

        public ShowTabGlyph(BehaviorService behaviorSvc, Control control) :
            base(new ShowTabBehavior())
        {
            this.behaviorSvc = behaviorSvc;
            this.control = control;
        }

        public override Rectangle Bounds
        {
            get
            {
                // Create a glyph that is 10x10 and sitting
                // in the middle of the control.  Glyph coordinates
                // are in adorner window coordinates, so we must map
                // using the behavior service.
                Point edge = behaviorSvc.ControlToAdornerWindow(control);
                Size size = control.Size;
                Point center = new Point(edge.X + (size.Width / 2),
                    edge.Y + (size.Height / 2));

                Rectangle bounds = new Rectangle(
                    center.X - 5,
                    center.Y - 5,
                    10,
                    10);

                return bounds;
            }
        }

        public override Cursor GetHitTest(Point p)
        {
            // GetHitTest is called to see if the point is
            // within this glyph.  This gives us a chance to decide
            // what cursor to show.  Returning null from here means
            // the mouse pointer is not currently inside of the glyph.
            // Returning a valid cursor here indicates the pointer is
            // inside the glyph, and also enables our Behavior property
            // as the active behavior.
            if (Bounds.Contains(p))
            {
                return Cursors.Hand;
            }

            return null;
        }

        public override void Paint(PaintEventArgs pe)
        {
            // Draw our glyph. It is simply a blue ellipse.
            pe.Graphics.DrawEllipse(Pens.Blue, Bounds);
        }

        // By providing our own behavior we can do something interesting
        // when the user clicks or manipulates our glyph.
        class ShowTabBehavior : Behavior
        {
            public override bool OnMouseUp(Glyph g, MouseButtons button)
            {
                //MessageBox.Show("Hey, you clicked the mouse here");
                //this.
                ShowTabGlyph myG = (ShowTabGlyph)g;
                if (myG.Callback != null)
                {
                    myG.Callback();
                }
                return true; // indicating we processed this event.
            }
        }
    }
}

[DesignerAttribute(typeof(TabButtonDesigner))]
public class MyCustomTabButton : System.Windows.Forms.Button
{
    // The attribute will assign the custom designer to the TabButton
    // and after a rebuild the button contains a centered blue circle
    // that acts at design time like the button in runtime does ...

    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM