Question

Le bouton "Ouvrir" de la boîte de dialogue d'ouverture de fichier utilisée dans certaines applications Windows comprend une flèche déroulante avec une liste d'options supplémentaires, à savoir "Ouvrir avec ..".

Je n'ai pas vu cela dans toutes les applications Windows, vous devrez donc peut-être en essayer quelques-unes pour l'obtenir, mais SQL Server Management Studio et Visual Studio 2005 afficheront tous deux le bouton de cette façon si vous allez dans le menu et choisissez Fichier->Ouvrir->Fichier...

Je souhaite utiliser un bouton comme celui-ci avec une liste intégrée dans l'une de mes applications, mais je ne trouve le contrôle qu'ils utilisent nulle part dans Visual Studio.Je dois préciser que je recherche ce bouton spécifique, pas la boîte de dialogue entière.Des pensées?

Était-ce utile?

La solution

J'ai utilisé la recherche déplaçable dans Spy++ (installé avec VS) pour examiner le bouton d'ouverture fractionnée dans la boîte de dialogue d'ouverture de fichier de VS.

Cela a révélé qu'il s'agit d'un bouton Windows ordinaire avec un style qui inclut BS_DEFSPLITBUTTON.C'est un mot-clé magique qui vous amène à des endroits intéressants, notamment

http://www.codeplex.com/windowsformsaero/SourceControl/FileView.aspx?itemId=212902&changeSetId=9930

et ici

http://msdn.microsoft.com/en-us/library/bb775949.aspx#using_splits

J'espère que cela vous aide.

MODIFIER:

En fait, je viens d'essayer ce code de CodePlex et il crée un bouton partagé - mais vous devez vous assurer que vous avez défini le FlatStyle du bouton sur "Système" plutôt que "Standard", qui est la valeur par défaut.Je n'ai pas pris la peine de connecter les éléments de gestion des événements pour la liste déroulante, mais cela est couvert dans le lien MSDN, je pense.

Bien sûr, il s'agit uniquement de Vista (mais il n'est pas nécessaire d'activer Aero, malgré le nom sur codeplex) - si vous avez besoin d'une prise en charge antérieure du système d'exploitation, vous reviendrez au dessin vous-même.

Autres conseils

Je me suis souvenu de ça Kétarine a un bouton comme ça.

En utilisant Réflecteur J'ai trouvé un excellent contrôle open source appelé wyDay.SplitButton. wyDay.SplitButton

Je pense que ce que vous recherchez s'appelle un toolStripSplitButton.Il n'est disponible que dans un toolStrip.Mais vous pouvez ajouter un toolStripContainer n'importe où sur votre formulaire, puis placer le toolStrip et le toolStripSplitButton à l'intérieur de votre conteneur.

Vous ne voudrez pas afficher les poignées, vous souhaiterez donc définir votre gripMargin = 0.Vous pouvez également définir votre autosize=true afin que la bande d'outils soit conforme à votre bouton.Le bouton ressemblera à un bouton normal (sauf pour la partie divisée) sur votre formulaire.

Je ne suis pas familier avec l'utilisation de l'un ou l'autre de ces éléments, mais essayez de rechercher dans Msdn un bouton partagé ou un bouton déroulant.Je pense que ceux-ci ressemblent à ce que vous recherchez.

Voici mon implémentation de bouton partagé.Il ne dessine pas la flèche et le comportement de mise au point/défocalisation est un peu différent.

Le mien et les originaux gèrent les styles visuels et ont fière allure avec Aero.

Basé sur http://wyday.com/splitbutton/

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Drawing;
using System.ComponentModel;
using System.Diagnostics;

// Original: http://blogs.msdn.com/jfoscoding/articles/491523.aspx
// Wyatt's fixes: http://wyday.com/splitbutton/
// Trimmed down and redone significantly from that version (Nick 5/6/08)
namespace DF
{
    public class SplitButton : Button
    {
        private ContextMenuStrip m_SplitMenu = null;
        private const int SplitSectionWidth = 14;
        private static int BorderSize = SystemInformation.Border3DSize.Width * 2;
        private bool mBlockClicks = false;
        private Timer mTimer;

        public SplitButton()
        {
            this.AutoSize = true;
            mTimer = new Timer();
            mTimer.Interval = 100;
            mTimer.Tick += new EventHandler(mTimer_Tick);
        }

        private void mTimer_Tick(object sender, EventArgs e)
        {
            mBlockClicks = false;
            mTimer.Stop();
        }

        #region Properties
        [DefaultValue(null)]
        public ContextMenuStrip SplitMenu
        {
            get
            {
                return m_SplitMenu;
            }
            set
            {
                if (m_SplitMenu != null)
                    m_SplitMenu.Closing -= 
                        new ToolStripDropDownClosingEventHandler(m_SplitMenu_Closing);

                m_SplitMenu = value;

                if (m_SplitMenu != null)
                    m_SplitMenu.Closing += 
                        new ToolStripDropDownClosingEventHandler(m_SplitMenu_Closing);
            }
        }

        private void m_SplitMenu_Closing(object sender, ToolStripDropDownClosingEventArgs e)
        {
            HideContextMenuStrip();
            // block click events for 0.5 sec to prevent re-showing the menu

        }

        private PushButtonState _state;
        private PushButtonState State
        {
            get
            {
                return _state;
            }
            set
            {
                if (!_state.Equals(value))
                {
                    _state = value;
                    Invalidate();
                }
            }
        }

        #endregion Properties

        protected override void OnEnabledChanged(EventArgs e)
        {
            if (Enabled)
                State = PushButtonState.Normal;
            else
                State = PushButtonState.Disabled;

            base.OnEnabledChanged(e);
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left)
                return;
            if (State.Equals(PushButtonState.Disabled))
                return;
            if (mBlockClicks)
                return;

            if (!State.Equals(PushButtonState.Pressed))
                ShowContextMenuStrip();
            else
                HideContextMenuStrip();
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            if (!State.Equals(PushButtonState.Pressed) && !State.Equals(PushButtonState.Disabled))
            {
                State = PushButtonState.Hot;
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            if (!State.Equals(PushButtonState.Pressed) && !State.Equals(PushButtonState.Disabled))
            {
                if (Focused)
                {
                    State = PushButtonState.Default;
                }

                else
                {
                    State = PushButtonState.Normal;
                }
            }
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);

            Graphics g = pevent.Graphics;
            Rectangle bounds = this.ClientRectangle;

            // draw the button background as according to the current state.
            if (State != PushButtonState.Pressed && IsDefault && !Application.RenderWithVisualStyles)
            {
                Rectangle backgroundBounds = bounds;
                backgroundBounds.Inflate(-1, -1);
                ButtonRenderer.DrawButton(g, backgroundBounds, State);

                // button renderer doesnt draw the black frame when themes are off =(
                g.DrawRectangle(SystemPens.WindowFrame, 0, 0, bounds.Width - 1, bounds.Height - 1);
            }
            else
            {
                ButtonRenderer.DrawButton(g, bounds, State);
            }

            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            g.DrawString(Text, Font, SystemBrushes.ControlText, bounds, format);
        }

        private void ShowContextMenuStrip()
        {
            State = PushButtonState.Pressed;
            if (m_SplitMenu != null)
            {
                m_SplitMenu.Show(this, new Point(0, Height), ToolStripDropDownDirection.BelowRight);
            }
        }

        private void HideContextMenuStrip()
        {
            State = PushButtonState.Normal;
            m_SplitMenu.Hide();
            mBlockClicks = true;
            mTimer.Start();
        }
    }
}

Je ne pense pas qu'il existe un contrôle intégré capable de le faire dans .NET.Je fouille dans la documentation MSDN pour le contrôle Windows Button standard, mais il ne semble pas qu'il soit là.

J'ai trouvé un Article sur le projet de code avec une implémentation personnalisée ;cela pourrait aider un peu.

Depuis que j'ai trouvé le contrôle dans Windows lui-même, j'espérais le trouver déjà intégré quelque part afin de ne pas avoir à ajouter quoi que ce soit à ma base de code pour l'utiliser.Mais le bouton partagé à ce lien (trouvé via la suggestion msdn) semble assez prometteur.

Je l'essaierai moi-même plus tard, mais je ne sais pas dans quelle mesure il gérera les styles visuels.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top