C#Windows窗体鼠标事件问题中的自定义控件

时间:2022-10-31 15:51:41

I have a mouseenter and mouseleave event for a Panel control that changes the backcolor when the mouse enters and goes back to white when it leaves.

我有一个用于Panel控件的mouseenter和mouseleave事件,当鼠标进入时会改变背景颜色,当它离开时会返回白色。

I have Label control within this panel as well but when the mouse enters the Label control, the mouseleave event for the panel fires.

我也在此面板中有Label控件,但当鼠标进入Label控件时,面板的mouseleave事件将触发。

This makes sense but how do I keep the backcolor of the Panel the same when the mouse is in its area without the other controls inside affecting it?

这是有道理的,但是当鼠标位于其区域而其他控件不会影响它时,如何保持Panel的背景颜色相同?

4 个解决方案

#1


5  

You can use GetChildAtPoint() to determine if the mouse is over a child control.

您可以使用GetChildAtPoint()来确定鼠标是否在子控件上。

private void panel1_MouseLeave(object sender, EventArgs e)
{
    if (panel1.GetChildAtPoint(panel1.PointToClient(MousePosition)) == null)
    {
        panel1.BackColor = Color.Gray;
    }
}

If the control isn't actually a child control, you can still use MousePosition and PointToScreen to determine if the mouse is still within the bounds of the control.

如果控件实际上不是子控件,您仍然可以使用MousePosition和PointToScreen来确定鼠标是否仍在控件的范围内。

private void panel1_MouseLeave(object sender, EventArgs e)
{
    Rectangle screenBounds = new Rectangle(this.PointToScreen(panel1.Location), panel1.Size);
    if (!screenBounds.Contains(MousePosition))
    {
        panel1.BackColor = Color.Gray;
    }
}

#2


1  

Adding an event for a contained control means that when you want to add another control to the panel, you have to go through the same exercise for that too.

为包含的控件添加事件意味着当您想要向面板添加另一个控件时,您也必须执行相同的练习。

Adding an event for the parent control means that as soon as you want to use the panel somewhere else, you have to do the same for the new parent. And when the requirements for the panel change, you have to remember to take the processing out of the parent control's event.

为父控件添加事件意味着只要您想在其他位置使用面板,就必须为新父控件执行相同的操作。当面板的要求发生变化时,您必须记住将处理从父控件的事件中取出。

All potentially messy a little further down the line.

所有潜在的混乱都在线下。

I'd be inclined to put some coordinate checking in the mouse leave event for the panel, and only reset the panel colour if the mouse has really gone outside the bounds of the panel.

我倾向于在面板的鼠标离开事件中进行一些坐标检查,并且只有在鼠标真的超出面板边界时才重置面板颜色。

That way, your code for panel-handling remains only on the panel in question.

这样,您的面板处理代码仅保留在相关面板上。

#3


1  

I found a simple solution. I just set the enabled property to false on the label and it's fine.

我找到了一个简单的解决方我只是在标签上将enabled属性设置为false,这很好。

#4


0  

You could add a MouseEnter event for the label which also sets the Panel's back colour. You wouldn't need a MouseLeave event for the label.

您可以为标签添加MouseEnter事件,该事件也设置Panel的背面颜色。您不需要标签的MouseLeave事件。

Or:

  1. Set the MouseEnter event for the Panel to set the Panel's back colour.
  2. 为Panel设置MouseEnter事件以设置Panel的背景颜色。

  3. Set the Panel's parent control's (e.g. the Form) MouseEnter event to reset the Panel's back colour.
  4. 设置Panel的父控件(例如Form)MouseEnter事件以重置Panel的背面颜色。


If you wanted to do point 2 above without touching the parent control's code (as per other user's comment), you could do something like this in the Panel's ParentChanged event:

如果您想在不触及父控件代码的情况下执行上述第2点(根据其他用户的注释),您可以在Panel的ParentChanged事件中执行以下操作:

    private void panel1_ParentChanged(object sender, EventArgs e)
    {
        Panel thisPanel = sender as Panel;

        if(thisPanel != null && thisPanel.Parent != null)
        {
            thisPanel.Parent.MouseEnter += delegate(object senderObj, EventArgs eArgs) { thisPanel.BackColor = SystemColors.Control; };
        }
    }

#1


5  

You can use GetChildAtPoint() to determine if the mouse is over a child control.

您可以使用GetChildAtPoint()来确定鼠标是否在子控件上。

private void panel1_MouseLeave(object sender, EventArgs e)
{
    if (panel1.GetChildAtPoint(panel1.PointToClient(MousePosition)) == null)
    {
        panel1.BackColor = Color.Gray;
    }
}

If the control isn't actually a child control, you can still use MousePosition and PointToScreen to determine if the mouse is still within the bounds of the control.

如果控件实际上不是子控件,您仍然可以使用MousePosition和PointToScreen来确定鼠标是否仍在控件的范围内。

private void panel1_MouseLeave(object sender, EventArgs e)
{
    Rectangle screenBounds = new Rectangle(this.PointToScreen(panel1.Location), panel1.Size);
    if (!screenBounds.Contains(MousePosition))
    {
        panel1.BackColor = Color.Gray;
    }
}

#2


1  

Adding an event for a contained control means that when you want to add another control to the panel, you have to go through the same exercise for that too.

为包含的控件添加事件意味着当您想要向面板添加另一个控件时,您也必须执行相同的练习。

Adding an event for the parent control means that as soon as you want to use the panel somewhere else, you have to do the same for the new parent. And when the requirements for the panel change, you have to remember to take the processing out of the parent control's event.

为父控件添加事件意味着只要您想在其他位置使用面板,就必须为新父控件执行相同的操作。当面板的要求发生变化时,您必须记住将处理从父控件的事件中取出。

All potentially messy a little further down the line.

所有潜在的混乱都在线下。

I'd be inclined to put some coordinate checking in the mouse leave event for the panel, and only reset the panel colour if the mouse has really gone outside the bounds of the panel.

我倾向于在面板的鼠标离开事件中进行一些坐标检查,并且只有在鼠标真的超出面板边界时才重置面板颜色。

That way, your code for panel-handling remains only on the panel in question.

这样,您的面板处理代码仅保留在相关面板上。

#3


1  

I found a simple solution. I just set the enabled property to false on the label and it's fine.

我找到了一个简单的解决方我只是在标签上将enabled属性设置为false,这很好。

#4


0  

You could add a MouseEnter event for the label which also sets the Panel's back colour. You wouldn't need a MouseLeave event for the label.

您可以为标签添加MouseEnter事件,该事件也设置Panel的背面颜色。您不需要标签的MouseLeave事件。

Or:

  1. Set the MouseEnter event for the Panel to set the Panel's back colour.
  2. 为Panel设置MouseEnter事件以设置Panel的背景颜色。

  3. Set the Panel's parent control's (e.g. the Form) MouseEnter event to reset the Panel's back colour.
  4. 设置Panel的父控件(例如Form)MouseEnter事件以重置Panel的背面颜色。


If you wanted to do point 2 above without touching the parent control's code (as per other user's comment), you could do something like this in the Panel's ParentChanged event:

如果您想在不触及父控件代码的情况下执行上述第2点(根据其他用户的注释),您可以在Panel的ParentChanged事件中执行以下操作:

    private void panel1_ParentChanged(object sender, EventArgs e)
    {
        Panel thisPanel = sender as Panel;

        if(thisPanel != null && thisPanel.Parent != null)
        {
            thisPanel.Parent.MouseEnter += delegate(object senderObj, EventArgs eArgs) { thisPanel.BackColor = SystemColors.Control; };
        }
    }