0
votes

I'm using the wpf notifyicon (http://www.hardcodet.net/wpf-notifyicon)

When my laptop is at 100% dpi scaling, the left side of the context menu is centred on the tray icon, as expected.

When the laptop isn't at 100%, the context menu is pushed to the far right.

On high resolution laptop displays, 100% scaling is not the default.

Wherever my tray icon is positioned, that is, however far from the clock, the menu always pops up over the clock, as far to the bottom-right of the screen as is possible while remaining visible.

Note: I'm testing on a default installation of Windows 8.1. Also, the NotifyIcon that I'm using is the one that is generally recommended for anyone attempting tray functionality in WPF.

To reproduce: the problem exists in the windowless sample provided by hardcodet. I'm using wpf NotifyIcon without a window, and can reproduce easily in code or xaml. In fact, I cannot stop reproducing it. It occurs when dpi scaling is turned on, i.e. when a 1080p display is actually showing a lesser resolution, which is what windows does to stop applications having text too tiny to read.

Any ideas about how I can make the context menu appear in the expected place regardless of dpi?

Screen shots as suggested by kennyzx:

good behaviour. the m on red background (MEGAsync) has just been right-clicked

bad behaviour. the green tick, my notifyicon, has just been right-clicked and the menu appears over the clock

!good behaviour. the m on red background (MEGAsync) has just been right-clicked

!bad behaviour. the green tick, my notifyicon, has just been right-clicked and the menu appears over the clock

and some code:

var n = new TaskbarIcon();
n.Icon=new System.Drawing.Icon(@"C:\window - 64 - tick.ico");
n.ContextMenu = new System.Windows.Controls.ContextMenu();
n.ContextMenu.Items.Add(new System.Windows.Controls.MenuItem {Header="E_xit" });
1
this is better illustrated by a screenshot.kennyzx

1 Answers

0
votes

Found the solution here: http://www.codeproject.com/Messages/4929452/Problem-with-context-menu-position.aspx

It is, with thanks to codeproject user Igorious:

Get the code for Wpf Notifyicon (http://www.hardcodet.net/wpf-notifyicon)).

In Hardcodet.Wpf.TaskbarNotification.TaskbarIcon.ShowContextMenu()

replace

ContextMenu.HorizontalOffset = cursorPosition.X;
ContextMenu.VerticalOffset = cursorPosition.Y;

with

var g = Graphics.FromHwnd(IntPtr.Zero);
var scaleX = g.DpiX / 96.0;
var scaleY = g.DpiY / 96.0;

ContextMenu.HorizontalOffset = cursorPosition.X / scaleX;
ContextMenu.VerticalOffset = cursorPosition.Y / scaleY;

Explanation (thanks to codeproject user yachting):

It's needed because WinApi.GetPhysicalCursorPos return the mouse position in pixel, but WPF's measurement unit is device independent pixel (by definition, it's 1/96 inch) You need to adjust the return value of GetPhysicalCursorPos by DPI (dots per inch) setting, otherwise the position of the context menu will be incorrect if users set DPI other than the default 96.