9

在某些 Windows 应用程序中使用的打开文件对话框上的Open按钮包括一个带有附加选项列表的下拉箭头 - 即Open With...

打开文件对话框

我没有在每个 Windows 应用程序中都看到这个,所以你可能需要尝试一些来获得它,但是如果你进入菜单并选择File-> Open- ,SQL Server Management Studio 和 Visual Studio 2017 都会以这种方式显示按钮>File...

我想在我的一个应用程序中使用这样的按钮和内置列表,但我在 Visual Studio 的任何地方都找不到他们使用的控件。我应该澄清一下,我正在寻找那个特定的按钮,而不是整个对话框。有什么想法吗?

4

7 回答 7

7

我使用 Spy++(与 VS 一起安装)中的可拖动搜索来查看 VS 文件打开对话框上的拆分打开按钮。

这表明它是一个普通的 Windows 按钮,其样式包括 BS_DEFSPLITBUTTON。这是一个神奇的关键字,可以带你到一些有趣的地方,包括

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

和这里

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

希望这对您有所帮助。

编辑:

实际上,我刚刚尝试过 CodePlex 中的代码,它确实创建了一个拆分按钮 - 但您必须确保已将按钮的 FlatStyle 设置为“系统”而不是“标准”,这是默认设置。我没有费心为下拉列表连接事件处理的东西,但我认为这在 MSDN 链接中有所介绍。

当然,这仅适用于 Vista(但不需要启用 Aero,尽管 codeplex 上的名称) - 如果您需要更早的操作系统支持,您将自己重新绘制它。

于 2008-08-27T20:51:31.803 回答
5

我记得Ketarin有一个这样的按钮。

使用Reflector,我发现了一个很棒的开源控件wyDay.SplitButtonwyDay.SplitButton

于 2009-10-18T12:01:02.000 回答
4

我认为您正在寻找的东西称为 toolStripSplitButton。它仅在工具条中可用。但是您可以在表单的任何位置添加 toolStripContainer,然后将 toolStrip 和 toolStripSplitButton 放入容器中。

您不想显示夹点,因此您需要设置 GripMargin = 0。您还可以设置 autosize=true 以便工具条符合您的按钮。该按钮看起来就像表单上的普通按钮(拆分部分除外)。

于 2008-08-27T20:31:18.607 回答
2

我不熟悉使用其中任何一个,但尝试在 msdn 中搜索 splitbutton 或 dropdownbutton。我认为这些与您正在寻找的相似。

于 2008-08-27T20:17:20.090 回答
2

这是我的拆分按钮实现。它不绘制箭头,聚焦/不聚焦行为略有不同。

我的和原版都处理视觉风格,并且在 Aero 上看起来很棒。

基于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();
        }
    }
}
于 2008-08-27T20:36:18.297 回答
1

我不认为有一个内置的控件可以在.NET 中做到这一点。我在标准 Windows Button 控件的 MSDN 文档中四处寻找,但它看起来并不存在。

我确实找到了带有自定义实现的代码项目文章;这可能会有所帮助。

于 2008-08-27T20:12:24.017 回答
0

由于我在 Windows 本身中找到了该控件,因此我希望它已经内置在某个地方,因此我不必在我的代码库中添加任何东西来使用它。但是这个链接上的拆分按钮(通过 msdn 建议找到)看起来很有希望。

我稍后会自己尝试,但我不知道它处理视觉样式的效果如何。

于 2008-08-27T20:33:26.743 回答