public static Point GetWindowPosition(NotifyIcon notifyicon, double windowwidth, double windowheight, double dpi)
{
// retrieve taskbar information
TaskBarInfo taskbarinfo = GetTaskBarInfo();
// retrieve notify icon location
Rect? nipositiontemp = GetNotifyIconRectangle(notifyicon);
// if our functions can't find the rectangle, align it to a corner of the screen
Rect niposition;
if (nipositiontemp == null)
{
switch (taskbarinfo.Alignment)
{
case TaskBarAlignment.Bottom: // bottom right corner
niposition = new Rect(taskbarinfo.Position.Right - 1, taskbarinfo.Position.Bottom - 1, 1, 1);
break;
case TaskBarAlignment.Top: // top right corner
niposition = new Rect(taskbarinfo.Position.Right - 1, taskbarinfo.Position.Top, 1, 1);
break;
case TaskBarAlignment.Right: // bottom right corner
niposition = new Rect(taskbarinfo.Position.Right - 1, taskbarinfo.Position.Bottom - 1, 1, 1);
break;
case TaskBarAlignment.Left: // bottom left corner
niposition = new Rect(taskbarinfo.Position.Left, taskbarinfo.Position.Bottom - 1, 1, 1);
break;
default:
goto case TaskBarAlignment.Bottom;
}
}
else
niposition = (Rect)nipositiontemp;
// check if notify icon is in the fly-out
bool inflyout = IsNotifyIconInFlyOut(niposition, taskbarinfo.Position);
// if the window is pinned open and in the fly-out (Windows 7 only),
// we should position the window above the 'show hidden icons' button
// if (inflyout && pinned)
// niposition = (Rect)GetNotifyAreaButtonRectangle();
// determine centre of notify icon
Point nicentre = new Point(niposition.Left + (niposition.Width / 2), niposition.Top + (niposition.Height / 2));
// get window offset from edge
double edgeoffset = Compatibility.WindowEdgeOffset * dpi;
// get working area bounds
Rect workarea = GetWorkingArea(niposition);
// calculate window position
double windowleft = 0, windowtop = 0;
switch (taskbarinfo.Alignment)
{
case TaskBarAlignment.Bottom:
// horizontally centre above icon
windowleft = nicentre.X - (windowwidth / 2);
if (inflyout)
windowtop = niposition.Top - windowheight - edgeoffset;
else
windowtop = taskbarinfo.Position.Top - windowheight - edgeoffset;
break;
case TaskBarAlignment.Top:
// horizontally centre below icon
windowleft = nicentre.X - (windowwidth / 2);
if (inflyout)
windowtop = niposition.Bottom + edgeoffset;
else
windowtop = taskbarinfo.Position.Bottom + edgeoffset;
break;
case TaskBarAlignment.Left:
// vertically centre to the right of icon (or above icon if in flyout and not pinned)
if (inflyout)
{
windowleft = nicentre.X - (windowwidth / 2);
windowtop = niposition.Top - windowheight - edgeoffset;
}
else
{
windowleft = taskbarinfo.Position.Right + edgeoffset;
windowtop = nicentre.Y - (windowheight / 2);
}
break;
case TaskBarAlignment.Right:
// vertically centre to the left of icon (or above icon if in flyout and not pinned)
if (inflyout)
{
windowleft = nicentre.X - (windowwidth / 2);
windowtop = niposition.Top - windowheight - edgeoffset;
}
else
{
windowleft = taskbarinfo.Position.Left - windowwidth - edgeoffset;
windowtop = nicentre.Y - (windowheight / 2);
}
break;
default:
goto case TaskBarAlignment.Bottom; // should be unreachable
}
//// check that the window is within the working area
//// if not, put it next to the closest edge
if (windowleft + windowwidth + edgeoffset > workarea.Right) // too far right
windowleft = workarea.Right - windowwidth - edgeoffset;
else if (windowleft < workarea.Left) // too far left
windowleft = workarea.Left + edgeoffset;
if (windowtop + windowheight + edgeoffset > workarea.Bottom) // too far down
windowtop = workarea.Bottom - windowheight - edgeoffset;
//// the window should never be too far up, so we can skip checking for that
return new Point(windowleft, windowtop);
}