【问题标题】:C# Prevent child control from leaving main control WinFormsC#防止子控件离开主控件WinForms
【发布时间】:2016-03-11 02:27:25
【问题描述】:

我有一个创建几个按钮的简单程序,它允许您使用自定义类来移动它们。这些按钮被添加到面板中,他们应该不能离开它。但是,当我仍然按住鼠标左键时,我似乎无法做到这一点,即我在面板边界的边缘停止控件并禁用可拖动功能,但是一旦我释放鼠标按钮,它实际上就会采取行动。这是代码:

private void CreateButtons(IList<Button> inputArray)
    {
        for (int i = 0; i < inputArray.Count; i++)
        {
            inputArray[i] = new Button
            {
                Height = 100,
                Width = 100
            };
            PuzzelHolder.Controls.Add(inputArray[i]);
            inputArray[i].Text = Values[i].ToString();
            inputArray[i].TextAlign = ContentAlignment.MiddleCenter;
            inputArray[i].Draggable(true);
            inputArray[i].Location = new Point(20, 20);
            inputArray[i].MouseDown += Button_Mouse_Down;
            inputArray[i].MouseUp += Button_Mouse_Up;
            //horizontal += inputArray[i].Width;
        }
    }

这就是我创建按钮的方式,你可以看到它们有与之关联的事件:

    private void Button_Mouse_Down(object sender, MouseEventArgs e)
    {
        if (IsLeaving(((Control) sender), PuzzelHolder))
        {
            ((Control) sender).Location = new Point(((Control) sender).Location.X, ((Control) sender).Location.Y);
            ((Control) sender).Draggable(false);
        }
        else
        {
            ((Control) sender).Draggable(true);
        }
    }

    private void Button_Mouse_Up(object sender, MouseEventArgs e)
    {
        ((Control)sender).Draggable(true);
    }

这也是 Draggable 类:

public static class ControlExtension
{
    private static readonly Dictionary<Control, bool> draggables =
               new Dictionary<Control, bool>();
    private static System.Drawing.Size mouseOffset;

    public static void Draggable(this Control control, bool Enable)
    {
        if (Enable)
        {
            // enable drag feature
            if (draggables.ContainsKey(control))
            {   // return if control is already draggable
                return;
            }
            // 'false' - initial state is 'not dragging'
            draggables.Add(control, false);

            // assign required event handlersnnn
            control.MouseDown += control_MouseDown;
            control.MouseUp += control_MouseUp;
            control.MouseMove += control_MouseMove;
        }
        else
        {
            // disable drag feature
            if (!draggables.ContainsKey(control))
            {  // return if control is not draggable
                return;
            }
            // remove event handlers
            control.MouseDown -= control_MouseDown;
            control.MouseUp -= control_MouseUp;
            control.MouseMove -= control_MouseMove;
            draggables.Remove(control);
        }
    }

    private static void control_MouseDown(object sender, MouseEventArgs e)
    {
        mouseOffset = new System.Drawing.Size(e.Location);
        // turning on dragging
        draggables[(Control)sender] = true;
    }

    private static void control_MouseUp(object sender, MouseEventArgs e)
    {
        // turning off dragging
        draggables[(Control)sender] = false;
    }

    private static void control_MouseMove(object sender, MouseEventArgs e)
    {
        // only if dragging is turned on
        if (draggables[(Control)sender])
        {
            // calculations of control's new position
            var newLocationOffset = e.Location - mouseOffset;
            ((Control)sender).Left += newLocationOffset.X;
            ((Control)sender).Top += newLocationOffset.Y;
        }
    }
}

【问题讨论】:

  • 您是否尝试过使用 MDI 容器?

标签: c# winforms events key controls


【解决方案1】:

有很多方法可以做到这一点。这取决于你想要的行为。

1.in这个按钮是允许拖到表单外的。

您可以设置主窗体属性 IsMdiContainer = true。然后通过计算相对位置,设置按钮的顶部和左侧并使用鼠标向上事件进行操作。

void button1_MouseUp(对象发送者,MouseEventArgs e) { var btnDragged = ((控制)发件人); var parent = btnDragged.Parent; if (btnDragged.Left parent.Width) btnDragged.Left = parent.Width - btnDragged.Width; if (btnDragged.Bottom > (parent.Height - btnDragged.Height)) btnDragged.Top = parent.Height - btnDragged.Height * 2; }

如果您不想要 mdicontainer,则只需将父变量替换为上面代码中的主表单名称即可。

  1. 如果您不想让按钮被拖到外面。你可以在鼠标移动事件中做同样的事情。但它会给你一些闪烁。 您还可以更改扩展类以支持此行为。

    static void control_MouseMove(object sender, MouseEventArgs e)
    {
            // only if dragging is turned on
            if (draggables[(Control)sender] == true)
            {
                var parent = ((Control)sender).Parent;
                System.Drawing.Point newLocationOffset = e.Location - mouseOffset;
                var controlDragged = (Control)sender;
                if ((controlDragged.Left + newLocationOffset.X) >= 0 && (controlDragged.Right + newLocationOffset.X) <= parent.Width && (controlDragged.Top + newLocationOffset.Y) >= 0 && (controlDragged.Bottom + newLocationOffset.Y) < (parent.Height - controlDragged.Height))
                {
                    controlDragged.Left += newLocationOffset.X;
                    controlDragged.Top += newLocationOffset.Y;               
                }
            }
     }
    

我希望这会有所帮助。

【讨论】:

  • 感谢您对我当前使用第二个选项的响应,该选项不允许控件外出,但无论如何我可以减少闪烁吗?太可怕了
猜你喜欢
  • 1970-01-01
  • 2013-11-11
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
  • 2011-02-10
  • 1970-01-01
  • 2018-08-22
  • 2011-03-05
相关资源
最近更新 更多