Is there a way to position a form just above the clicked Notify Icon in windows 7 and windows Vista?
Asked
Active
Viewed 6,421 times
4
-
1does this help u? http://codetechnic.blogspot.com/2009/03/set-windows-forms-start-position-to.html – Zenwalker Sep 03 '11 at 18:03
-
no that positions the form in the right bottom corner above the taskbar. I need to position it above the notify icon. – blejzz Sep 03 '11 at 18:04
-
Possible duplicate: http://stackoverflow.com/questions/272778/how-to-find-the-location-of-the-icon-in-the-system-tray – Devin Burke Sep 03 '11 at 18:04
-
You can't, as explained in the dup. There is one thing you *do* know: where the mouse is located. It won't be far from the icon. Don't forget that the taskbar could be on any of the 4 sides of the screen. – Hans Passant Sep 03 '11 at 18:20
-
aha ok thanks, how could i know how is the taskbar positioned? – blejzz Sep 03 '11 at 18:22
-
The right click message tells you the mouse location. You just need to click that to the work area and make sure that your form doesn't span multiple monitors. – David Heffernan Sep 03 '11 at 18:30
2 Answers
8
Here is an easier way.
You can get X,Y position of the mouse when the OnClick event is fired.
You can also get the taskbar position with somes checks from these objects Screen.PrimaryScreen.Bounds
, Screen.PrimaryScreen.WorkingArea
.
private void OnTrayClick(object sender, EventArgs e)
{
_frmMain.Left = Cursor.Position.X;
_frmMain.Top = Screen.PrimaryScreen.WorkingArea.Bottom -_frmMain.Height;
_frmMain.Show();
}

Richard Ev
- 52,939
- 59
- 191
- 278

Adam Paquette
- 1,243
- 1
- 14
- 28
-
This is bar far the nicest solution I saw, apart from the case when tray is located on the right side on the screen, not at the bottom... – Do-do-new Feb 06 '20 at 21:24
-
1This made my day! :) Small enhancement for multiple screens: trayIcon.ContextMenuStrip.Show(Cursor.Position); // should be first as height is initially not correct... trayIcon.ContextMenuStrip.Left = Math.Min(Cursor.Position.X, Screen.PrimaryScreen.WorkingArea.Right - trayIcon.ContextMenuStrip.Width); // for multiple monitors and different placements of task bar trayIcon.ContextMenuStrip.Top = Screen.PrimaryScreen.WorkingArea.Bottom - trayIcon.ContextMenuStrip.Height; – Laky May 12 '21 at 08:26
1
Regarding your comment: "how could i know how is the taskbar positioned?"
Check out the following article which contains a class which exposes a method for retrieving a Rectangle Structure for the tray: [c#] NotifyIcon - Detect MouseOut
Using this class you can retrieve the Rectangle Structure for the tray like so:
Rectangle trayRectangle = WinAPI.GetTrayRectangle();
Which will provide you with the Top, Left, Right and Bottom coordinates for the tray along with its width and height.
I have included the class below:
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.ComponentModel;
public class WinAPI
{
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public override string ToString()
{
return "(" + left + ", " + top + ") --> (" + right + ", " + bottom + ")";
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string strClassName, string strWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
public static IntPtr GetTrayHandle()
{
IntPtr taskBarHandle = WinAPI.FindWindow("Shell_TrayWnd", null);
if (!taskBarHandle.Equals(IntPtr.Zero))
{
return WinAPI.FindWindowEx(taskBarHandle, IntPtr.Zero, "TrayNotifyWnd", IntPtr.Zero);
}
return IntPtr.Zero;
}
public static Rectangle GetTrayRectangle()
{
WinAPI.RECT rect;
WinAPI.GetWindowRect(WinAPI.GetTrayHandle(), out rect);
return new Rectangle(new Point(rect.left, rect.top), new Size((rect.right - rect.left) + 1, (rect.bottom - rect.top) + 1));
}
}
Hope this helps.

jdavies
- 12,784
- 3
- 33
- 33
-
1That is a grotesque hack. Why on earth would you do that rather than read out the cursor pos from the right click event? Why resort to hacks when you can do it properly? – David Heffernan Sep 03 '11 at 18:35
-
@David Heffernan what would be the proper way to get how the taskbar is positioned? i just need to know if it's on the left/right/top/bottom. – blejzz Sep 03 '11 at 18:39
-
1@blejzz Hans already explained that you can't locate your icon. What you can do is get the cursor pos of the event that invoked your icons context menu. From that you can work out which corner. – David Heffernan Sep 03 '11 at 18:44
-
1Either method would work. The code I posted would retrieve the coordinates for the tray, the mouse cursor position will give you the approx position of the tray icon. The way I see it, you could combine the two to position your form. Determining the location of the task bar could be inferred from the coordinates or mouse position. – jdavies Sep 03 '11 at 18:44
-
@jdavies the difference is that your method relies on undocumented implementation details which is why I turned my nose up at it. – David Heffernan Sep 03 '11 at 19:49
-
For what it is worth, I am trying to locate a tray icon not during a click event, so for me this hack would work. I agree that hanging on undocumented implementation details is very fishy, but it is a close solution to my problem. – user912447 Jul 08 '13 at 02:07