c# - 如果另一个工具条位于同一个工具条面板上,则将工具条稍微向左移动会创建一个新行

标签 c# winforms toolstrip

当我将一个工具条向左拖动(可能只是为了将它放在角落里)和同一个工具条面板中的另一个工具条时,我正在拖动的工具条会跳到"new"行,就好像我已经移动了一样它下来。这很难解释,所以这里有几个图表。

图表 A:我将工具条向左移动,但“不小心”向左移动了太多(只移动了几十个像素,用户可以轻松做到)。

图 B:发生这种情况,拖动的工具条向下一行。

enter image description here

如何防止这个新行被“创建”?作为最后的手段,我很乐意阻止在任何情况下创建新行(例如:如果用户打算将其向下拖动以创建新行)。

我已经尝试过 LayoutStyle 但无济于事。

最佳答案

可能有几种方法可以做到这一点。我已经尝试了一些,但没有一个是完美的。我会说我发现的最简单的方法是像 Hans 提到的那样设置 ToolStripPanel 的最大大小,并将 ToolStrip 子类化并覆盖 OnLocationChanged(或将事件处理程序分配给 LocationChanged 而不是子类化,但您必须为每个 ToolStrip 分配一个处理程序)。

public class ToolStripEx : ToolStrip
{
    protected override void OnLocationChanged(EventArgs e)
    {
        if (this.Location.Y >= this.Parent.MaximumSize.Height)
        {
            this.Location = new Point(this.Location.X, 0);
        }
        else
        {
            base.OnLocationChanged(e);
        }           
    }
}


注意:这会导致鼠标在尝试向下拖动 ToolStrip 时来回跳动,因为 Location 已经更改后被重置,所以它基本上是向下移动,然后立即跳回。

还值得一提的是,这可能会让用户感到烦恼,尤其是当他们故意尝试将 ToolStrip 放在新行中时,所以我真的不建议这样做。但既然你问了,那就是了。

更新完整步骤和代码:

我创建了一个新的空白 Windows 窗体项目。我在解决方案中添加了一个新文件 ToolStripEx.cs,这是里面的内容:

更新了其他面板及其方向

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public class ToolStripEx : ToolStrip
    {
        protected override void OnLocationChanged(EventArgs e)
        {
            if (this.Parent is ToolStripPanel)
            {
                ToolStripPanel parent = this.Parent as ToolStripPanel;

                if (parent.Orientation == Orientation.Horizontal)
                {
                    if (this.Location.Y != 0)
                    {
                        this.Location = new Point(this.Location.X, 0);
                        return;
                    }
                }
                else if (parent.Orientation == Orientation.Vertical)
                {
                    if (this.Location.X != 0)
                    {
                        this.Location = new Point(0, this.Location.Y);
                        return;
                    }
                }
            }
            base.OnLocationChanged(e);
        }
    }
}


然后我构建了解决方案,因此 ToolStripEx 类将显示在工具箱中。

然后我将一个常规的 ToolStripContainer 从工具箱放到表单上,将 Dock 设置为 Fill,设置颜色等。

然后我将两个 ToolStripEx(带有您提到的齿轮图标)从工具箱拖到 TopToolStripPanel。我设置它们的颜色和渲染器等等。

这是 Form1.cs 的样子:

已更新以设置其他最大尺寸

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.toolStripContainer1.TopToolStripPanel.MaximumSize = new Size(0, toolStripEx1.Height);
            this.toolStripContainer1.LeftToolStripPanel.MaximumSize = new Size(toolStripEx1.Height, 0);
            this.toolStripContainer1.BottomToolStripPanel.MaximumSize = new Size(0, toolStripEx1.Height);
            this.toolStripContainer1.RightToolStripPanel.MaximumSize = new Size(toolStripEx1.Height, 0);
        }
    }
}


注意:此代码可防止任何面板扩展其行(或列,如果它们的OrientationOrientation.Vertical)如果您希望侧面板能够展开,请不要设置它们的最大尺寸并去掉 else if parent.Orientation == Orientation.Vertical 部分。

应该就这些了。我运行了这个,当移动它们时,两个 ToolStripEx 都没有消失。

正如 Hans 所说,ToolStrip 类非常古怪,几乎任何解决问题的方法都不会是完美的,除非您根据自己的需要从头开始开发自己的控件。

如果出于某种原因您需要扩展 ToolStripContainer 类,请将其与新的 ToolStripEx 类分开。我怀疑使用嵌套类会导致您仍在使用常规 ToolStrip 而不是 ToolStripEx 类。

另一个更新 - 修复鼠标跳跃: 我在尝试摆脱鼠标光标问题时偶然发现了这一点。将此添加到 ToolStripEx 类:

protected override void OnBeginDrag(EventArgs e)
{
    //base.OnBeginDrag(e);
}

奇怪的是,这似乎大大降低了工具条被拖出面板的阻力。我还没有深入研究为什么会这样,但似乎 ToolStrip 实现了自己的拖动行为而不使用基本的拖放功能,并且通过覆盖 OnBeginDragDrop ToolStrip 然后专门使用其自定义行为,这使得鼠标在拖动时表现得更好。

关于c# - 如果另一个工具条位于同一个工具条面板上,则将工具条稍微向左移动会创建一个新行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15120432/

相关文章:

c# - 是创建自定义异常还是等待下线发生 NullReferenceException?

c# - 检查我的 Windows 应用程序是否正在运行

c# - OnPaint 在调整大小时留下痕迹

.net - 如何对 ToolStripStatusLabel 进行跨线程调用?

c# - Application.Exit() 未按预期工作

c# - Windows 手机模拟器无法启动

c# - 为什么 Visual Studio 报表数据屏幕不显示所有可用的数据集?

c# - .NET 生成通用方法 - 紧凑的框架

winforms - 中心文本对齐标签

c# - WinForms 菜单工具条获取状态