用鼠标移动为面板着色
本文关键字:鼠标 移动 | 更新日期: 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;)