C# 防止模板显示在工作区域外

C# 防止模板显示在工作区域外,c#,winforms,C#,Winforms,我创建了一个自定义表单,将其显示为工具提示,但要在其上显示数据,当用户将鼠标悬停在按钮上并在鼠标离开时消失时,将显示该表单,所有操作都很完美,但如何防止表单显示在屏幕区域之外 这是我用来显示表单的代码: Info_Form tooltip = new Info_Form(); private void Button131_MouseHover(object sender, EventArgs e) { Button b = (Button)sender;

我创建了一个自定义表单,将其显示为工具提示,但要在其上显示数据,当用户将鼠标悬停在按钮上并在鼠标离开时消失时,将显示该表单,所有操作都很完美,但如何防止表单显示在屏幕区域之外

这是我用来显示表单的代码:

    Info_Form tooltip = new Info_Form();
    private void Button131_MouseHover(object sender, EventArgs e)
    {
        Button b = (Button)sender;

        tooltip = new Info_Form();
        tooltip.Height = tooltip.Height + 30;
        tooltip.Location = new Point(
        b.Right,
        b.Top);

        tooltip.Show();
    }

    private void Button131_MouseLeave(object sender, EventArgs e)
    {
        tooltip.Close();
    }
我建议:

  • 在Program.cs中声明工具提示表单
  • 添加静态方法以显示和隐藏它
当然,您可以使用公开静态方法的专用类来处理工具提示表单

然后,您可以从应用程序中的任何位置访问工具提示窗体,当鼠标指针进入或离开特定控件时,只需调用
ShowToolTip()
HideToolTip()
:此控件的边界转换为屏幕坐标,用作定位工具提示的参考

在这里,我使用一种简化的方法来确定工具提示是否应显示在参考控件的右侧或左侧以及顶部或底部:

  • 如果引用控件位于屏幕的左半部分,则窗体的左药剂为:
    ToolTip.left=[ref Control]。left
  • 否则,
    ToolTip.Left=[ref Control].Right-工具提示宽度
  • 同样的逻辑也适用于工具提示的顶部位置
如果需要,调整此简单计算以使用不同的逻辑定位工具提示窗体

► 无需处理工具提示表单:当传递给
Application.Run()
的表单实例关闭时,工具提示表单将自动处理

注意:如果应用程序不是DpiAware,并且显示应用程序窗口的屏幕是缩放的,则与屏幕或窗口/窗体相关的任何度量值都可能被虚拟化,因此您会收到错误的结果,任何计算都将被关闭

请参见此处的注释:


使用
screen s=screen.FromControl(c)获取当前屏幕然后使用
矩形r=s.WorkingArea
如果工具提示窗体没有完全相交,则重新定位它。@Loating,在我得到
矩形后
如何将其应用于shwon窗体的位置?谢谢,这比我做的要好得多,但现在我在屏幕的顶部和底部都遇到了同样的问题。啊,当然。嗯,这是相同的逻辑:如果显示工具提示的控件位于屏幕的中间/顶部区域,则显示其下方的表单,否则。。。除此之外?要在何处显示工具提示?--当然,您可以让计算稍微复杂一些,总是考虑工具提示的大小。如果工具提示的大小可以更改,否则就没用了。正确,我用这段代码完成了
var-TopPos=refBounds.Bottom非常感谢你的详细回答,你让我开心了:)
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;

public static frmToolTip tooltip = null;

[STAThread]
static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    tooltip = new frmToolTip();
    Application.Run(new SomeForm());
}

public async static Task ShowToolTip(Control control, string title) {
    await Task.Delay(400);
    if (tooltip.Visible) return;

    Rectangle refBounds = control.RectangleToScreen(control.ClientRectangle);
    if (!refBounds.Contains(Cursor.Position)) {
        HideToolTip();
    }
    else {
        var screen = Screen.GetBounds(control);
        var leftPos = refBounds.Left <= screen.Width / 2 ? refBounds.Left : refBounds.Right - tooltip.Width;
        var topPos = refBounds.Top <= screen.Height / 2 ? refBounds.Bottom + 2: refBounds.Top - tooltip.Height - 2;
        tooltip.Location = new Point(leftPos, topPos);
        tooltip.Text = title;
        tooltip.Show(control.FindForm());
    }
}
public static void HideToolTip() => tooltip.Hide();
using System.Threading.Tasks;

public partial class SomeForm : Form
{
   // [...]

    private async void SomeControl_MouseEnter(object sender, EventArgs e)
    {
        await Program.ShowToolTip(sender as Control, "Some Title Text");
    }

    private void SomeControl_MouseLeave(object sender, EventArgs e)
    {
        Program.HideToolTip();
    }
}