【问题标题】:How to set the location of a notification custom form just above or below depending on the position of the system Tray Icon of the Taskbar?如何根据任务栏的系统托盘图标的位置设置通知自定义表单的位置在上方或下方?
【发布时间】:2021-01-16 07:01:11
【问题描述】:

有没有办法在c#winforms中识别系统托盘的位置?

我想根据系统托盘的位置创建一个放置在系统托盘上方或下方的表单。

我计划创建一个自定义表单而不是上下文菜单,因为我需要增强 UI,但我对如何将我的表单放置在系统托盘上方/下方感到困惑。

我附上了我想象的表单位置的图像。

【问题讨论】:

  • 我想this 会回答你的问题
  • 使用How do I get the taskbar's position and sizeTaskbar locationGet location and size of TaskBar,您可以在WorkingArea 中计算所需的表单位置。还要考虑到任务栏可以是左/右/上/下以及自动隐藏。
  • 简体:How to obtain task bar Notification Area width in a C# program?。请参阅有关 DpiAwareness 的说明。
  • 我打算创建一个自定义表单而不是上下文菜单,因为我需要增强 UI → 好吧,如果一个通知图标和一个显示复杂的 Form/UserControl在 ContextMenuStrip 里面可以为您解决问题,您可以这样做。看this example
  • 此外,如果屏幕工作区的右下角是您要查找的内容:那么您将f 作为您要显示的表单,您可以将其位置设置为new Point(Screen.PrimaryScreen.WorkingArea.Right - f.Width, Screen.PrimaryScreen.WorkingArea.Bottom - f.Height); 和将其起始位置设置为手动并显示它。但请记住,它是工作区的右下角,而任务栏可能位于屏幕的左/右/顶部!如果您关心的正是托盘位置,那么 Jimi 的帖子会处理您的问题。

标签: c# winforms notifications taskbar trayicon


【解决方案1】:

使用此帖子获取任务栏的坐标:

Taskbar location

static public Rectangle GetTaskbarCoordonates()
{
  var data = new NativeMethods.APPBARDATA();
  data.cbSize = Marshal.SizeOf(data);
  IntPtr retval = NativeMethods.SHAppBarMessage(NativeMethods.ABM_GETTASKBARPOS, ref data);
  if ( retval == IntPtr.Zero ) 
    throw new Win32Exception("Windows Taskbar Error in " + nameof(GetTaskbarCoordonates));
  return new Rectangle(data.rc.left, data.rc.top,
                       data.rc.right - data.rc.left, data.rc.bottom - data.rc.top);
}

该方法将任务栏的锚点样式返回到屏幕边缘:

public const int TaskbarWidthCheckTrigger = 250;

static public AnchorStyles GetTaskbarAnchorStyle()
{
  var coordonates = GetTaskbarCoordonates();
  if ( coordonates.Left == 0 && coordonates.Top == 0 )
    if ( coordonates.Width > TaskbarWidthCheckTrigger )
      return AnchorStyles.Top;
    else
      return AnchorStyles.Left;
  else
  if ( coordonates.Width > TaskbarWidthCheckTrigger )
    return AnchorStyles.Bottom;
  else
    return AnchorStyles.Right;
}

这个值 250 是任意的,可以在特殊条件下校准或更改为更好的东西。

那么我们就可以利用上面的帖子,根据任务栏的边缘位置以及托盘图标的位置和大小,精确计算自定义工具提示通知表单的期望位置。

或者我们可以简单地确定表格的角:

  • 顶部 => 右上角
  • 左 => 左下
  • 底部 => 右下角
  • Rigth => 右下角

例如:

var form = new Form();
form.StartPosition = FormStartPosition.Manual;
var anchor = DisplayManager.GetTaskbarAnchorStyle();
switch ( anchor )
{
  case AnchorStyles.Top:
    form.SetLocation(ControlLocation.TopRight);
    break;
  case AnchorStyles.Left:
    form.SetLocation(ControlLocation.BottomLeft);
    break;
  case AnchorStyles.Bottom:
  case AnchorStyles.Right:
    form.SetLocation(ControlLocation.BottomRight);
    break;
}
form.Show();

拥有:

static public void SetLocation(this Form form, ControlLocation location)
{
  if ( form == null ) return;
  var area = SystemInformation.WorkingArea;
  switch ( location )
  {
    case ControlLocation.TopLeft:
      form.Location = new Point(area.Left, area.Top);
      break;
    case ControlLocation.TopRight:
      form.Location = new Point(area.Left + area.Width - form.Width, area.Top);
      break;
    case ControlLocation.BottomLeft:
      form.Location = new Point(area.Left, area.Top + area.Height - form.Height);
      break;
    case ControlLocation.BottomRight:
      form.Location = new Point(area.Left + area.Width - form.Width,
                                area.Top + area.Height - form.Height);
      break;
    case ControlLocation.Center:
      form.Center(area);
      break;
    case ControlLocation.Fixed:
      form.CenterToMainFormElseScreen();
      break;
    case ControlLocation.Loose:
      break;
    default:
      throw new NotImplementedExceptionEx(location);
  }
}

还有:

[Serializable]
public enum ControlLocation
{
  Loose,
  TopLeft,
  TopRight,
  BottomLeft,
  BottomRight,
  Center,
  Fixed
}

备注:这仅适用于主屏幕,它应该适应使用另一个。

【讨论】:

    【解决方案2】:

    我尝试查看您的参考资料,并在此基础上产生了一个想法,这是解决方法:

    1. 创建了 notifyicon 控件,然后设置为单击方法上的方法来调用我的表单
    2. 表单将显示在鼠标位置上方,因为无论工具箱的位置如何,notifyicon 控件始终放置在系统托盘上。

    代码 sn-p 用于通过鼠标位置定位表单

     var form = new Form1();
                        form.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
                        form.SetDesktopLocation(MousePosition.X - form.Width / 2, MousePosition.Y - form.Height - 20);
                        form.Show();
                        form.Activate();
                        form.TopMost = true;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-20
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多