C#阻止子控件离开主控WinForms

时间:2016-03-11 02:27:25

标签: c# winforms events key controls

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

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;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

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

1.允许将此按钮拖出窗体外。

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

        void button1_MouseUp(object sender, MouseEventArgs e)
        {
            var btnDragged = ((Control)sender);
            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;               
                }
            }
     }
    
  2. 我希望这会有所帮助。