Using this post to get the Taskbar's coordonates:
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);
}
This method returns the anchor style of the taskbar to the edge of the screen:
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;
}
This value 250 is arbitrary and can be calibrated under special conditions or changed for a better thing.
Then we can use the above post to precisely calculate the desired position of the custom tooltip notification form, considering the edge location of the taskbar as well as the location and size of the Tray Icon.
Or we can simply determine the form's corner:
- Top => top-right
- Left => bottom-left
- Bottom => bottom-right
- Rigth => bottom-right
For example:
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();
Having:
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);
}
}
And that:
[Serializable]
public enum ControlLocation
{
Loose,
TopLeft,
TopRight,
BottomLeft,
BottomRight,
Center,
Fixed
}
Remark: This works only for the primary screen and it should be adapted to use another.