0

我在表单上创建了一个小面板字段,我希望用户能够为这些面板着色。要为它们着色,您只需单击面板即可。现在我希望能够让用户单击一个面板并拖动到其他面板上以一次为更多面板着色。

我已将 mousedown 和 mouseup 事件添加到所有面板以设置布尔值。我使用 mousemove 事件为面板着色。然而,只有第一个面板被着色。

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;
using System.Diagnostics;

namespace Application
{
    public partial class Form1 : Form
    {
        private const int dim = 25;
        private int cols;
        private int rows;

        private bool mouse_down = false;
        private sbyte fill = -1;
        private Panel pnlTmp;

        public Form1()
        {
            InitializeComponent();

            this.buildGrid();
        }


        /// <summary>
        /// Rebuild the grid to fit the screen.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            this.buildGrid();
        }


        /// <summary>
        /// Build the grid to fit the screen.
        /// </summary>
        private void buildGrid()
        {
            panel1.Controls.Clear();

            cols = int.Parse(Math.Floor((double)panel1.Width / dim).ToString());
            rows = int.Parse(Math.Floor((double)panel1.Height / dim).ToString());

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    Panel pnl = new Panel();
                    pnl.BorderStyle = BorderStyle.FixedSingle;
                    pnl.Width = dim;
                    pnl.Height = dim;
                    pnl.Location = new Point(j * 25 + 1, i * 25 + 1);
                    pnl.Name = string.Format("pnl-{0}-{1}", j, i);
                    pnl.MouseDown += new MouseEventHandler(pnl_MouseDown);
                    pnl.MouseUp += new MouseEventHandler(pnl_MouseUp);
                    pnl.MouseMove += new MouseEventHandler(pnl_MouseHover);
                    panel1.Controls.Add(pnl);
                }
            }
        }

        void pnl_MouseHover(object sender, EventArgs e)
        {
            if (mouse_down)
            {
                Panel p = (Panel)sender;
                if (p != pnlTmp)
                {
                    if (fill == -1)
                        fill = (p.BackColor == SystemColors.Control) ? (sbyte)1 : (sbyte)0;

                    if (fill == 1)
                        p.BackColor = Color.Blue;
                    else
                        p.BackColor = SystemColors.Control;

                    Debug.WriteLine(p.Name);
                }

                pnlTmp = p;
            }
        }

        void pnl_MouseDown(object sender, MouseEventArgs e)
        {
            Debug.WriteLine("true");
            mouse_down = true;
        }

        void pnl_MouseUp(object sender, MouseEventArgs e)
        {
            Debug.WriteLine("false");
            mouse_down = false;
            fill = -1;
        }

        private void panel1_MouseLeave(object sender, EventArgs e)
        {
            //mouse_down = false;
            //fill = -1;
        }
    }
}

我尝试调试应用程序,结果是只有第一个面板继续触发事件,即使我正在移动其他面板。

有人能告诉我这是为什么吗?

4

1 回答 1

2

您的问题是由称为“鼠标捕获”的功能引起的。它由 Control.Capture 属性控制。默认行为是在触发 MouseDown 事件之前在 OnMouseDown() 方法中自动打开它。

鼠标捕获会强制将所有鼠标事件定向到您单击的窗口,即使您将鼠标移出窗口也是如此。这就是为什么您只获得单击面板的 MouseMove 和 MouseUp 事件的原因。它在许多场景中都很重要,尤其是可靠地生成 Click 和 MouseUp 事件。

解决方法是在 MouseDown 事件处理程序中简单地关闭捕获:

    void pnl_MouseDown(object sender, MouseEventArgs e) {
        ((Control)sender).Capture = false;
    }

请注意,您现在遇到了一个新问题,您的“mouse_down”变量不再可靠。如果您将鼠标移到任何面板或窗体之外,然后释放鼠标,则 MouseUp 事件将发送到错误的窗口,并且即使鼠标不再向下,您的 mouse_down 变量仍设置为 true。您失去了捕获功能提供的保证。您可以通过检查 MouseMove 事件处理程序中的按钮状态来解决该问题,如下所示:

    private void pnl_MouseMove(object sender, MouseEventArgs e) {
        if (e.Button == MouseButtons.Left) {
            // etc...
        }
    }

请注意,我修复了您不正确的 pnl_MouseHover 事件处理程序并将其重命名为 pnl_MouseMove。我可以看到你最终是如何犯这个错误的,但它可能确实阻止了你自己发现这个解决方案。小心那把斧头尤金;)

于 2012-12-27T13:16:55.153 回答