用鼠标移动为面板着色

本文关键字:鼠标 移动 | 更新日期: 2023-09-27 17:49:42

我在表单上创建了一个小面板字段,我希望用户能够为这些面板着色。要给它们上色,你必须简单地点击面板,这是有效的。现在我希望能够让用户点击一个面板并拖动到其他面板上,以便一次为更多面板上色。

我已经为所有面板添加了mousedown和mouseup事件来设置布尔值。然后我使用鼠标移动事件给面板上色。然而,只有第一块面板是有色的。

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

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

谁能告诉我这是为什么?

用鼠标移动为面板着色

你的问题是由一个叫做"鼠标捕获"的功能引起的。它是由主控者控制的。获取属性。默认行为是在OnMouseDown()方法中自动开启,然后触发MouseDown事件。

鼠标捕获强制将所有鼠标事件定向到您单击的窗口,即使您将鼠标移出窗口。这就是为什么你只获得你点击的面板的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。我知道你是怎么犯这个错误的,但它可能确实阻止了你自己发现这个解决方案。小心那把斧头,Eugene;)