拖动步骤

时间:2013-12-10 10:28:11

标签: c# winforms mouseevent drag

我有一个分为10行的面板。然后我有标记(高度= =高度的正方形),我希望能够上下拖动,但标记需要完全适合一行。标记不能拖动到第1行中有一半而第2行中有另一半的位置。因此拖动必须位于某些特定的垂直位置。 我只需要垂直拖动。然后我需要分配已被移动到标记的行作为对象的属性。例如。如果标记已放置在第5行,则该对象的等级将分配给5。 这是我到目前为止所做的,我能够垂直拖动每个标记,问题是它们可能在父容器外部被破坏,并且我无法使它们仅移动到所需的y位置。 关于如何实现这一点的任何想法或解释...请随时问我的问题是否不那么清楚..谢谢。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace MouseDragTest
{
    class Marker : PictureBox
    {
        public Label lb1 = new Label();
        public Label lb2 = new Label();
        bool isDragging = false;
        int rank;

        //-------Constructor----------
        public Marker(int xLoc, int yLoc)
        {
            Location = new Point(xLoc, yLoc);
            this.Size = new Size(20, 20);
            this.BackColor = Color.Blue;
            this.BringToFront();

        //-------Mouse Event Handlers--------
            this.MouseDown += new MouseEventHandler(StartDrag);
            this.MouseUp += new MouseEventHandler(StopDrag);
            this.MouseMove += new MouseEventHandler(OnDrag);
        }

        //-------Mouse Event Handlers Implementation---------
        private void StartDrag(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isDragging = true;
                rank = (this.Top + e.Y);
            }
        }

        private void StopDrag(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isDragging = false;
                rank = this.Top + e.Y;                
                lb1.Text = rank.ToString(); //Info on blue square
                lb2.Text = rank.ToString(); //Info on red square
            }
        }

        private void OnDrag(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                this.Top = this.Top + e.Y; //move vertically;
            }
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
           base.OnPaint(pe);
        }
    }
  }

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MouseDragTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen p = new Pen(Color.Black, 1);

            int yLoc = 20;
            for (int i = 0; i < 10; i++)
            {
                g.DrawLine(p, 0, yLoc, this.Width, yLoc);yLoc += 20;
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Marker mk1 = new Marker(0, 0);
            panel1.Controls.Add(mk1);
            /*For testing*/  mk1.lb1 = label1;

            Marker mk2 = new Marker(20,0);
            panel1.Controls.Add(mk2);
            /*For testing*/ mk2.lb2 = label2;
            mk2.BackColor = Color.Red;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

在'OnDrag'事件中,您需要检查当前Y坐标是否在您的范围内,然后仅在值处于所需范围内时才对Top值执行更新。

在StopDrag事件中,您需要为此等级中的项目计算正确的位置,并将对象的“顶部”值设置为所需的值,以使其“捕捉”到正确的位置。

我可以看到的问题是,处理拖放操作的事件位于Marker类中,并且不知道全局环境,从而阻止您编写代码,例如'if(this.Y&lt; lowerY) || this.Y&gt; upperY)然后什么都不做。有许多解决方案:将拖动事件处理程序移动到父容器上,以便它们知道所需的数据,使父容器具有某种形式的全局可见属性,这些属性在其中一个标记的范围内可见,或者可能为每个标记添加一个属性,使它们能够知道它们的父“容器”。