diff --git a/Source/NotifyIconWpf/Interop/WinApi.cs b/Source/NotifyIconWpf/Interop/WinApi.cs
index c9f8ffd..8aef54a 100644
--- a/Source/NotifyIconWpf/Interop/WinApi.cs
+++ b/Source/NotifyIconWpf/Interop/WinApi.cs
@@ -79,8 +79,10 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop
///
/// Gets the screen coordinates of the current mouse position.
///
- ///
- ///
+ [DllImport("USER32.DLL", SetLastError = true)]
+ public static extern bool GetPhysicalCursorPos(ref Point lpPoint);
+
+
[DllImport("USER32.DLL", SetLastError = true)]
public static extern bool GetCursorPos(ref Point lpPoint);
}
diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs
index f7c0a16..e01b0c0 100644
--- a/Source/NotifyIconWpf/TaskbarIcon.cs
+++ b/Source/NotifyIconWpf/TaskbarIcon.cs
@@ -59,7 +59,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
/// An action that is being invoked if the
/// fires.
///
- private Action delayedTimerAction;
+ private Action singleClickTimerAction;
///
/// A timer that is used to differentiate between single
@@ -105,6 +105,8 @@ namespace Hardcodet.Wpf.TaskbarNotification
}
}
+ private double scalingFactor = double.NaN;
+
#endregion
#region Construction
@@ -216,6 +218,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
popup.StaysOpen = true;
Point position = TrayInfo.GetTrayLocation();
+ position = GetDeviceCoordinates(position);
popup.HorizontalOffset = position.X - 1;
popup.VerticalOffset = position.Y - 1;
@@ -381,7 +384,17 @@ namespace Hardcodet.Wpf.TaskbarNotification
//get mouse coordinates
Point cursorPosition = new Point();
- WinApi.GetCursorPos(ref cursorPosition);
+ if (messageSink.Version == NotifyIconVersion.Vista)
+ {
+ //physical cursor position is supported for Vista and above
+ WinApi.GetPhysicalCursorPos(ref cursorPosition);
+ }
+ else
+ {
+ WinApi.GetCursorPos(ref cursorPosition);
+ }
+
+ cursorPosition = GetDeviceCoordinates(cursorPosition);
bool isLeftClickCommandInvoked = false;
@@ -391,7 +404,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
if (me == MouseEvent.IconLeftMouseUp)
{
//show popup once we are sure it's not a double click
- delayedTimerAction = () =>
+ singleClickTimerAction = () =>
{
LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this);
ShowTrayPopup(cursorPosition);
@@ -413,7 +426,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
if (me == MouseEvent.IconLeftMouseUp)
{
//show context menu once we are sure it's not a double click
- delayedTimerAction = () =>
+ singleClickTimerAction = () =>
{
LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this);
ShowContextMenu(cursorPosition);
@@ -432,8 +445,10 @@ namespace Hardcodet.Wpf.TaskbarNotification
if (me == MouseEvent.IconLeftMouseUp && !isLeftClickCommandInvoked)
{
//show context menu once we are sure it's not a double click
- delayedTimerAction =
- () => LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this);
+ singleClickTimerAction = () =>
+ {
+ LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this);
+ };
singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite);
}
}
@@ -650,7 +665,6 @@ namespace Hardcodet.Wpf.TaskbarNotification
//open popup
TrayPopupResolved.IsOpen = true;
-
IntPtr handle = IntPtr.Zero;
if (TrayPopupResolved.Child != null)
{
@@ -703,7 +717,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
ContextMenu.IsOpen = true;
IntPtr handle = IntPtr.Zero;
-
+
//try to get a handle on the context itself
HwndSource source = (HwndSource) PresentationSource.FromVisual(ContextMenu);
if (source != null)
@@ -830,11 +844,11 @@ namespace Hardcodet.Wpf.TaskbarNotification
if (IsDisposed) return;
//run action
- Action action = delayedTimerAction;
+ Action action = singleClickTimerAction;
if (action != null)
{
//cleanup action
- delayedTimerAction = null;
+ singleClickTimerAction = null;
//switch to UI thread
this.GetDispatcher().Invoke(action);
@@ -939,6 +953,35 @@ namespace Hardcodet.Wpf.TaskbarNotification
#endregion
+ ///
+ /// Recalculates OS coordinates in order to support WPFs coordinate
+ /// system if OS scaling (DPIs) is not 100%.
+ ///
+ ///
+ ///
+ private Point GetDeviceCoordinates(Point point)
+ {
+ if (double.IsNaN(scalingFactor))
+ {
+ //calculate scaling factor in order to support non-standard DPIs
+ var presentationSource = PresentationSource.FromVisual(this);
+ if (presentationSource == null)
+ {
+ scalingFactor = 1;
+ }
+ else
+ {
+ var transform = presentationSource.CompositionTarget.TransformToDevice;
+ scalingFactor = 1/transform.M11;
+ }
+ }
+
+ //on standard DPI settings, just return the point
+ if(scalingFactor == 1.0) return point;
+
+ return new Point() {X = (int) (point.X*scalingFactor), Y = (int) (point.Y*scalingFactor)};
+ }
+
#region Dispose / Exit
///
diff --git a/Source/NotifyIconWpf/Util.cs b/Source/NotifyIconWpf/Util.cs
index 6334250..6c3f171 100644
--- a/Source/NotifyIconWpf/Util.cs
+++ b/Source/NotifyIconWpf/Util.cs
@@ -25,6 +25,7 @@
using System;
using System.ComponentModel;
using System.Drawing;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;