Cursor.Hide() 函数的奇怪错误
Weird Bug With Cursor.Hide() function
我正在开发一个 Battleship 游戏项目,我制作了一个名为 GraphicCell
的控件,它继承自 PictureBox
class,但用作面板的按钮。
与普通按钮的主要区别在于,当您将鼠标悬停在按钮上时,它会隐藏光标。它还有一个背景图像和一个名为 locked
的参数,我用它来锁定计算机的棋盘(玩家不能在这个棋盘上玩)。锁定的光标不隐藏
我的问题:当我将鼠标悬停在未锁定的 GraphicCell
上时,光标会按应有的方式隐藏,而对于 locked
的光标,它会按应有的方式显示光标,但是当我将鼠标悬停在 locked
上时,当我将鼠标悬停在未锁定的 GraphicCell
.
上时,光标不会再次隐藏
GIF exemple for the bug: https://gyazo.com/750a2688a3d33d49462ff6b6e68533d1
Left (User's Board) - Not Locked
Right (PC's board) - Locked
代码:(错误应该在 MouseEnterEvent
/ MouseLeaveEvent
函数中)
public class GraphicCell : PictureBox
{
enum SquareImage {None, Empty, Bombed};
readonly int x, y;
readonly Square s;
bool locked;
public GraphicCell(int x, int y, Square s, bool locked = false)
{
this.x = x;
this.y = y;
this.s = s;
this.locked = locked;
this.Size = new System.Drawing.Size(25, 25);
this.BackgroundImageLayout = ImageLayout.Stretch;
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.BackgroundImage = Properties.Resources.water;
this.MouseEnter += new EventHandler(MouseEnterEvent);
this.MouseLeave += new EventHandler(MouseLeaveEvent);
}
public bool Locked { get { return locked; } set { locked = value; } }
public void Update(Result r)
{
if (r != Result.None)
{
locked = true;
switch (r)
{
case (Result.Miss):
ChangeImage(SquareImage.Empty);
break;
case (Result.Hit):
case (Result.ShipDestroyed):
case (Result.Victory):
ChangeImage(SquareImage.Bombed);
break;
}
}
}
private void ChangeImage(SquareImage si)
{
switch (si)
{
case (SquareImage.None):
this.Image = null;
break;
case (SquareImage.Empty):
this.Image = Properties.Resources.empty;
break;
case (SquareImage.Bombed):
this.Image = Properties.Resources.bombed;
break;
}
}
private void MouseEnterEvent(Object sender, EventArgs e)
{
if (!locked)
{
this.Image = Properties.Resources.water_bomb;
Cursor.Hide();
}
}
private void MouseLeaveEvent(Object sender, EventArgs e)
{
Cursor.Show();
if (!locked)
{
if (this.Image != null)
this.Image = null;
}
}
public Square GetSquare()
{ return this.s; }
public int GetX()
{ return this.x; }
public int GetY()
{ return this.y; }
}
编辑:问题已解决
感谢“OldBoyCoder”和“Hans Passant”解决了问题。
原来 Cursor.Show()
/Cursor.Hide()
方法使用了一个计数器,所以问题是在 MouseLeaveEvent
中调用了 Cursor.Show()
方法,即使游标已经显示,所以 Cursor.Show()
方法有时被调用多次,它使计数器高于 1,这就是导致错误的原因。
(例如,如果 Cursor.Show()
的计数器为 2 并且我调用 Cursor.Hide()
,则光标保持显示,因为 2 > 1)
修复:
已通过使用布尔值 locked
修复,以确保 Cursor.Show()
仅被调用一次。
更改:
private void MouseLeaveEvent(Object sender, EventArgs e)
{
Cursor.Show();
if (!locked)
{
if (this.Image != null)
this.Image = null;
}
}
收件人:
private void MouseLeaveEvent(Object sender, EventArgs e)
{
if (!locked)
{
Cursor.Show();
if (this.Image != null)
this.Image = null;
}
}
您从未在方法
中将锁定设置回 false
public void Update(Result r)
不是完整的答案,因为我还没有解决方案,但必须平衡对显示和隐藏的调用,因为有一个内部计数器:
发件人:
显示和隐藏方法调用必须平衡。每次调用 Hide 方法都必须对应调用 Show 方法。
您进行的所有 Show 调用都需要与 Hides 进行平衡。
您可以按任意顺序多次调用 vSetCursor(eCursorOperation.Show)
或 vSetCursor(eCursorOperation.Hide)
。
enum eCursorOperation
{
Show,
Hide
}
// Since the cursor is showing to start with assume the internal counter is set to 1 - fingers crossed
private int GiCursorShowCount = 1;
private void vSetCursor(eCursorOperation ecYourChoice)
{
switch (ecYourChoice)
{
case eCursorOperation.Show:
while (GiCursorShowCount < 1)
{
Cursor.Show();
GiCursorShowCount++;
}
break;
case eCursorOperation.Hide:
while (GiCursorShowCount > 0)
{
Cursor.Hide();
GiCursorShowCount--;
}
break;
default:
break;
}
}
我正在开发一个 Battleship 游戏项目,我制作了一个名为 GraphicCell
的控件,它继承自 PictureBox
class,但用作面板的按钮。
与普通按钮的主要区别在于,当您将鼠标悬停在按钮上时,它会隐藏光标。它还有一个背景图像和一个名为 locked
的参数,我用它来锁定计算机的棋盘(玩家不能在这个棋盘上玩)。锁定的光标不隐藏
我的问题:当我将鼠标悬停在未锁定的 GraphicCell
上时,光标会按应有的方式隐藏,而对于 locked
的光标,它会按应有的方式显示光标,但是当我将鼠标悬停在 locked
上时,当我将鼠标悬停在未锁定的 GraphicCell
.
GIF exemple for the bug: https://gyazo.com/750a2688a3d33d49462ff6b6e68533d1
Left (User's Board) - Not Locked
Right (PC's board) - Locked
代码:(错误应该在 MouseEnterEvent
/ MouseLeaveEvent
函数中)
public class GraphicCell : PictureBox
{
enum SquareImage {None, Empty, Bombed};
readonly int x, y;
readonly Square s;
bool locked;
public GraphicCell(int x, int y, Square s, bool locked = false)
{
this.x = x;
this.y = y;
this.s = s;
this.locked = locked;
this.Size = new System.Drawing.Size(25, 25);
this.BackgroundImageLayout = ImageLayout.Stretch;
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.BackgroundImage = Properties.Resources.water;
this.MouseEnter += new EventHandler(MouseEnterEvent);
this.MouseLeave += new EventHandler(MouseLeaveEvent);
}
public bool Locked { get { return locked; } set { locked = value; } }
public void Update(Result r)
{
if (r != Result.None)
{
locked = true;
switch (r)
{
case (Result.Miss):
ChangeImage(SquareImage.Empty);
break;
case (Result.Hit):
case (Result.ShipDestroyed):
case (Result.Victory):
ChangeImage(SquareImage.Bombed);
break;
}
}
}
private void ChangeImage(SquareImage si)
{
switch (si)
{
case (SquareImage.None):
this.Image = null;
break;
case (SquareImage.Empty):
this.Image = Properties.Resources.empty;
break;
case (SquareImage.Bombed):
this.Image = Properties.Resources.bombed;
break;
}
}
private void MouseEnterEvent(Object sender, EventArgs e)
{
if (!locked)
{
this.Image = Properties.Resources.water_bomb;
Cursor.Hide();
}
}
private void MouseLeaveEvent(Object sender, EventArgs e)
{
Cursor.Show();
if (!locked)
{
if (this.Image != null)
this.Image = null;
}
}
public Square GetSquare()
{ return this.s; }
public int GetX()
{ return this.x; }
public int GetY()
{ return this.y; }
}
编辑:问题已解决
感谢“OldBoyCoder”和“Hans Passant”解决了问题。
原来 Cursor.Show()
/Cursor.Hide()
方法使用了一个计数器,所以问题是在 MouseLeaveEvent
中调用了 Cursor.Show()
方法,即使游标已经显示,所以 Cursor.Show()
方法有时被调用多次,它使计数器高于 1,这就是导致错误的原因。
(例如,如果 Cursor.Show()
的计数器为 2 并且我调用 Cursor.Hide()
,则光标保持显示,因为 2 > 1)
修复:
已通过使用布尔值 locked
修复,以确保 Cursor.Show()
仅被调用一次。
更改:
private void MouseLeaveEvent(Object sender, EventArgs e)
{
Cursor.Show();
if (!locked)
{
if (this.Image != null)
this.Image = null;
}
}
收件人:
private void MouseLeaveEvent(Object sender, EventArgs e)
{
if (!locked)
{
Cursor.Show();
if (this.Image != null)
this.Image = null;
}
}
您从未在方法
中将锁定设置回 falsepublic void Update(Result r)
不是完整的答案,因为我还没有解决方案,但必须平衡对显示和隐藏的调用,因为有一个内部计数器:
发件人:
显示和隐藏方法调用必须平衡。每次调用 Hide 方法都必须对应调用 Show 方法。
您进行的所有 Show 调用都需要与 Hides 进行平衡。
您可以按任意顺序多次调用 vSetCursor(eCursorOperation.Show)
或 vSetCursor(eCursorOperation.Hide)
。
enum eCursorOperation
{
Show,
Hide
}
// Since the cursor is showing to start with assume the internal counter is set to 1 - fingers crossed
private int GiCursorShowCount = 1;
private void vSetCursor(eCursorOperation ecYourChoice)
{
switch (ecYourChoice)
{
case eCursorOperation.Show:
while (GiCursorShowCount < 1)
{
Cursor.Show();
GiCursorShowCount++;
}
break;
case eCursorOperation.Hide:
while (GiCursorShowCount > 0)
{
Cursor.Hide();
GiCursorShowCount--;
}
break;
default:
break;
}
}