public Point GetTangentPosition(Forms.NotifyIcon icon) { #region Verbose #if Verbose var wa = icon.GetScreen().WorkingArea; Logger.Debug($"GetTangent trayIcon.ScreenOf x={wa.X} y={wa.Y} left={wa.Left} " + $"top={wa.Top} width={wa.Width} height={wa.Height} (Win32 unscaled)"); #endif #endregion var location = icon.GetRectangle(); if (location.Equals(Rect.Empty)) { location = SystemTray.GetRectangle(); // we need to estimate full geometry of icon based on taskbar orientation // presume standard icon size of 16x16 if ((Edge == ScreenEdge.Bottom) || (Edge == ScreenEdge.Top)) { location = new Rect(new Point(location.X, location.Y), new Size(16, location.Y)); } else // left|right { location = new Rect(new Point(location.X, location.Y), new Size(location.X, 16)); } #region Verbose #if Verbose Logger.Debug("GetTangent fallback to tray location " + $"x={location.X}, y={location.Y} w={location.Width} h={location.Height}"); #endif #endregion } #region Verbose #if Verbose else { // we should have full geometry of icon rectange regardless of taskbar Edge Logger.Debug("GetTangent notify icon location " + $"x={location.X}, y={location.Y} w={location.Width} h={location.Height}" + " (Win32 unscaled)"); } var xa = SystemParameters.WorkArea; Logger.Debug($"...WPF workarea x={xa.X} y={xa.Y} left={xa.Left} top={xa.Top} " + $"width={xa.Width} height={xa.Height}"); var fa = Forms.Screen.PrimaryScreen.WorkingArea; Logger.Debug($"...FRM workarea x={fa.X} y={fa.Y} left={fa.Left} top={fa.Top} " + $"width={fa.Width} height={fa.Height}"); #endif #endregion // calculate scaling factors // TODO: this is limited to the primary monitor so we must assume this is where our // notify icon resides; otherwise, this may not be correct in a multi-DPI desktop var xscale = Forms.Screen.PrimaryScreen.WorkingArea.Width / SystemParameters.WorkArea.Width; var yscale = Forms.Screen.PrimaryScreen.WorkingArea.Height / SystemParameters.WorkArea.Height; location = new Rect( new Point(location.X / xscale, location.Y / yscale), new Size(location.Width / xscale, location.Height / yscale)); #region Verbose #if Verbose Logger.Debug("GetTangent scale-adjusted location " + $"x={location.X}, y={location.Y} w={location.Width} h={location.Height}"); #endif #endregion var x = 0.0; var y = 0.0; switch (Edge) { case ScreenEdge.Bottom: case ScreenEdge.Right: // return upper-left corner of icon x = location.Left; // + (int)(location.Width / 2); y = location.Top; break; case ScreenEdge.Top: // return lower-left corner of tray x = location.Left; y = location.Bottom; break; case ScreenEdge.Left: // return upper-right corner of tray x = location.Top; y = location.Right; break; } #region Verbose #if Verbose Logger.Debug($"GetTangent X={x}, Y={y}"); #endif #endregion return(new Point { X = x, Y = y }); }