这是什么控制? (带有下拉菜单的"打开"按钮)
在某些Windows应用程序中使用的打开文件对话框中的"打开"按钮包括一个带有其他选项列表的下拉箭头-即"打开方式.."。
我没有在每个Windows应用程序中都看到过此消息,因此我们可能必须尝试一些才能获得它,但如果转到菜单并选择File->,则SQL Server Management Studio和Visual Studio 2005都将以这种方式显示该按钮。打开->文件...
我想在我的一个应用程序中使用带有内置列表的这样的按钮,但找不到在Visual Studio中任何地方使用的控件。我需要澄清的是,我要查找的是特定按钮,而不是整个对话框。有什么想法吗?
解决方案
回答
我认为.NET中没有内置控件可以做到这一点。我在MSDN文档中寻找有关标准Windows Button控件的信息,但看起来好像不存在。
我确实找到了带有自定义实现的Code Project文章。这可能会有所帮助。
回答
我对使用这两种方法都不熟悉,但是请尝试在msdn中搜索splitbutton或者dropdownbutton。我认为这些与我们要寻找的相似。
回答
我认为我们正在寻找的东西称为toolStripSplitButton。它仅在toolStrip中可用。但是我们可以在窗体上的任意位置添加一个toolStripContainer,然后将toolStrip和toolStripSplitButton放入容器中。
我们将不希望显示夹点,因此将要设置handleMargin =0。我们还可以设置autosize = true,以使工具栏符合按钮。该按钮将看起来像表单上的普通按钮(拆分部分除外)。
回答
由于我是在Windows本身中找到该控件的,所以我希望已经在内置的控件中找到它,因此我不必在代码库中添加任何内容即可使用它。但是此链接上的split按钮(通过msdn建议找到)看起来很有希望。
我自己会稍后再尝试,但是我不知道它将如何处理视觉样式。
回答
这是我的拆分按钮实现。它不会绘制箭头,并且聚焦/散焦行为略有不同。
无论是我的作品还是原始作品都具有视觉风格,并且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(); } } }
回答
我在Spy ++(与VS一起安装)中使用了可拖动的搜索,以查看VS的文件打开对话框中的拆分打开按钮。
这表明它是一个普通的Windows按钮,其样式包括BS_DEFSPLITBUTTON。这是一个魔术关键字,可带我们进入一些有趣的地方,包括
http://www.codeplex.com/windowsformsaero/SourceControl/FileView.aspx?itemId=212902&changeSetId=9930
和这里
http://msdn.microsoft.com/zh-CN/library/bb775949.aspx#using_splits
希望这对我们有所帮助。
编辑:
我实际上刚刚尝试了CodePlex的代码,它确实创建了一个拆分按钮,但是我们必须确保已将按钮的FlatStyle设置为"系统",而不是默认的"标准"。我没有为下拉菜单挂接事件处理内容,但是我认为这已包含在MSDN链接中。
当然,这仅适用于Vista(如果在codeplex上有名称,则不需要启用Aero),如果我们需要早期的OS支持,我们将自己重新绘制它。
回答
我记得Ketarin有这样的按钮。
使用Reflector,我发现了一个很棒的开源控件wyDay.SplitButton。