【问题标题】:Moving toolstrip just a little too far left will create a new row if another toolstrip is on the same toolstrip panel如果另一个工具条在同一个工具条面板上,则将工具条移动到稍微向左一点将创建一个新行
【发布时间】:2013-02-27 19:16:11
【问题描述】:

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

图 A:我将工具条向左移动,并且“不小心”向左移动了太远(只有几十个像素,用户可以轻松做到这一点)。

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

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

我尝试过 LayoutStyle 无济于事。

【问题讨论】:

  • 哈,刚试过。多么奇怪。
  • 我见过这个,但相信这是由于我垂直移动了一点鼠标。据我所知,如果鼠标水平移动到死角,这对我来说并没有发生。

标签: c# winforms toolstrip


【解决方案1】:

可能有几种方法可以做到这一点。我已经尝试了一些,但没有一个是完美的。我想说我发现的最简单的方法是像 Hans 提到的那样设置 ToolStripPanel 的最大大小,并将 ToolStrip 子类化并覆盖 OnLocationChanged (或者将事件处理程序分配给 LocationChanged 而不是子类化,但是你d 必须为每个 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 时来回跳跃,因为位置在 它已经改变之后被重置,所以它本质上是向下移动,然后立即向上跳。

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

更新完整的步骤和代码:

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

更新了其他面板及其Orientation

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,设置颜色等。

然后我将两个ToolStripExs(带有您提到的齿轮图标)从工具箱拖到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 部分。

这应该就是它的全部了。我运行了这个,ToolStripExs 在移动它们时都没有消失。

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

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

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

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

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

【讨论】:

  • 谢谢。是的,不幸的是,将 Hans 的解决方案与您的解决方案结合使用,我仍然遇到工具条消失的问题。仅供参考,当它消失时,它实际上可能会移动到当前行下方的新行,因此它实际上并没有被“删除”。
  • @DanW 它不应该移动到新行,因为位置基本上被锁定为 0 的 Y。当我测试这个时,我无法让工具条消失。当我尝试其他事情时,我已经看到消失的工具条发生了。也许你可以用你到目前为止的确切代码更新你的问题?
  • 好的,更新了。顺便说一句,尝试简单地将工具条从 TopToolStripPanel 拖到 ContentPanel 中,您会更容易、更直接地看到问题(它会消失)。你也有这个问题吗?
  • @DanW 因为你把ToolStripEx 类放在ToolStripContainerFix 类里面,我怀疑你的toolStrip1 不是ToolStripEx,而是一个普通的ToolStrip。跨度>
  • 对,对不起,那是我的一个愚蠢的错误。我现在重新创建了该项目,是的,它现在似乎“很好”。当它进入 LeftToolStripPanel 时有一个小故障,但我可能可以解决这个问题。此外,工具条有时会相互滑入,但这并不是什么大问题。最后,更令人担忧的是,即使在按照您的步骤操作之后,我也会在设计器中收到“为了防止在加载设计器之前可能丢失数据,必须解决以下错误”。它仍然可以编译/运行。我以前创建过这样的扩展,现在很少遇到这个问题..
【解决方案2】:

Winforms 中的工具条类非常古怪。它们在 .NET 2.0 中发布,然后 Winforms 团队很快就解散了。许多团队成员进入了 WPF 项目。结果,这些怪癖从未得到解决。您自己对此几乎无能为力,大多数工具条代码都被锁定,无法覆盖行为。还有很多,所以重写也不实用。

可以阻止行垂直增长。您可以通过在顶部工具条内容面板上设置 MaximumSize 属性来做到这一点:

    public Form1() {
        InitializeComponent();
        toolStripContainer1.TopToolStripPanel.MaximumSize =
            new Size(0, toolStrip1.Height);
    }

但是当你玩弄这个时,你会发现这会使工具条完全消失。没有干净的解决方法。

请注意,这并不是一个真正的问题,工具条的位置是用户的选择,您不应该以任何方式提供帮助。您可以指望用户以合乎逻辑的方式安排它们。

【讨论】:

  • 谢谢,我也经历过其他工具栏之一通过尝试消失。不幸的是,这个问题是一个问题,它让我的用户感到恼火,所以我会尝试其他两个答案。
【解决方案3】:

如何暂停 OnMouseLeave 上的布局,然后重新启用它 OnMouseEnter/OnMouseUp/etc?

public class ToolStripContainerFix : ToolStripContainer
{
    public ToolStripContainerFix()
        : base()
    {
        this.TopToolStripPanel.MouseLeave += TopToolStripPanel_MouseLeave;
        this.TopToolStripPanel.MouseEnter += TopToolStripPanel_MouseEnter;
    }

    void TopToolStripPanel_MouseLeave(object sender, EventArgs e)
    {
        this.TopToolStripPanel.SuspendLayout();
    }

    void TopToolStripPanel_MouseEnter(object sender, EventArgs e)
    {
        this.TopToolStripPanel.ResumeLayout();
    }
}

您需要对此进行修改,以便它在表单之外检查它,而不是控件本身...这样您就可以允许在预期时创建新行。

【讨论】:

  • 非常感谢。不幸的是,似乎还有其他错误。例如,将另一个工具条拖到左侧有时会使它“隐藏”在另一个工具条下,有时我根本无法拖动它。
  • 您恢复布局了吗?您需要在鼠标事件(Enter / Mouse Up)上重新启用布局更改。
  • 不,我没有,但我看到你已经更新了代码,所以我尝试了。不幸的是,我仍然遇到“卡住”和“消失”工具条和/或“合并”工具条的问题。例如,尝试将第一个工具条向左移动太远,然后将鼠标悬停在另一个工具条的“拖动”部分上,第一个工具条就会消失。
  • 好的,我回家后试试。 :P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-25
相关资源
最近更新 更多