From 94085b72938cf4cdcc32d2e267c1b169feb247ee Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Mon, 30 Mar 2009 22:01:35 +0000 Subject: [PATCH 01/73] WPF NotifyIcon -------------- Initial import git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@52 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf.sln | 38 + Source/NotifyIconWpf.sln.cache | 236 +++++ Source/NotifyIconWpf/BalloonIcon.cs | 30 + Source/NotifyIconWpf/DefaultTrayIcon.ico | Bin 0 -> 1150 bytes Source/NotifyIconWpf/Interop/BalloonFlags.cs | 55 ++ .../NotifyIconWpf/Interop/IconDataMembers.cs | 67 ++ Source/NotifyIconWpf/Interop/IconState.cs | 23 + Source/NotifyIconWpf/Interop/MouseEvent.cs | 46 + Source/NotifyIconWpf/Interop/NotifyCommand.cs | 39 + .../NotifyIconWpf/Interop/NotifyIconData.cs | 153 +++ .../Interop/NotifyIconVersion.cs | 28 + Source/NotifyIconWpf/Interop/TrayLocator.cs | 95 ++ Source/NotifyIconWpf/Interop/WinApi.cs | 80 ++ Source/NotifyIconWpf/Interop/WindowClass.cs | 31 + .../Interop/WindowMessageSink.Handle.cs | 102 ++ .../Interop/WindowMessageSink.cs | 255 +++++ Source/NotifyIconWpf/NotifyIconWpf.csproj | 108 +++ Source/NotifyIconWpf/PopupActivationMode.cs | 45 + .../NotifyIconWpf/Properties/AssemblyInfo.cs | 59 ++ .../Properties/Resources.Designer.cs | 70 ++ .../NotifyIconWpf/Properties/Resources.resx | 124 +++ .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + Source/NotifyIconWpf/RoutedEventHelper.cs | 81 ++ .../NotifyIconWpf/TaskbarIcon.Declarations.cs | 868 ++++++++++++++++++ Source/NotifyIconWpf/TaskbarIcon.Interop.cs | 250 +++++ Source/NotifyIconWpf/TaskbarIcon.cs | 379 ++++++++ Source/NotifyIconWpf/Util.cs | 225 +++++ Source/Sample Project/App.xaml | 8 + Source/Sample Project/App.xaml.cs | 16 + Source/Sample Project/Icons/Bulb.ico | Bin 0 -> 1150 bytes Source/Sample Project/Icons/Computers.ico | Bin 0 -> 1150 bytes Source/Sample Project/Icons/NetDrives.ico | Bin 0 -> 42135 bytes .../Sample Project/Properties/AssemblyInfo.cs | 55 ++ .../Properties/Resources.Designer.cs | 84 ++ .../Sample Project/Properties/Resources.resx | 130 +++ .../Properties/Settings.Designer.cs | 30 + .../Properties/Settings.settings | 7 + Source/Sample Project/Sample Project.csproj | 121 +++ Source/Sample Project/Window1.xaml | 147 +++ Source/Sample Project/Window1.xaml.cs | 43 + 41 files changed, 4161 insertions(+) create mode 100644 Source/NotifyIconWpf.sln create mode 100644 Source/NotifyIconWpf.sln.cache create mode 100644 Source/NotifyIconWpf/BalloonIcon.cs create mode 100644 Source/NotifyIconWpf/DefaultTrayIcon.ico create mode 100644 Source/NotifyIconWpf/Interop/BalloonFlags.cs create mode 100644 Source/NotifyIconWpf/Interop/IconDataMembers.cs create mode 100644 Source/NotifyIconWpf/Interop/IconState.cs create mode 100644 Source/NotifyIconWpf/Interop/MouseEvent.cs create mode 100644 Source/NotifyIconWpf/Interop/NotifyCommand.cs create mode 100644 Source/NotifyIconWpf/Interop/NotifyIconData.cs create mode 100644 Source/NotifyIconWpf/Interop/NotifyIconVersion.cs create mode 100644 Source/NotifyIconWpf/Interop/TrayLocator.cs create mode 100644 Source/NotifyIconWpf/Interop/WinApi.cs create mode 100644 Source/NotifyIconWpf/Interop/WindowClass.cs create mode 100644 Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs create mode 100644 Source/NotifyIconWpf/Interop/WindowMessageSink.cs create mode 100644 Source/NotifyIconWpf/NotifyIconWpf.csproj create mode 100644 Source/NotifyIconWpf/PopupActivationMode.cs create mode 100644 Source/NotifyIconWpf/Properties/AssemblyInfo.cs create mode 100644 Source/NotifyIconWpf/Properties/Resources.Designer.cs create mode 100644 Source/NotifyIconWpf/Properties/Resources.resx create mode 100644 Source/NotifyIconWpf/Properties/Settings.Designer.cs create mode 100644 Source/NotifyIconWpf/Properties/Settings.settings create mode 100644 Source/NotifyIconWpf/RoutedEventHelper.cs create mode 100644 Source/NotifyIconWpf/TaskbarIcon.Declarations.cs create mode 100644 Source/NotifyIconWpf/TaskbarIcon.Interop.cs create mode 100644 Source/NotifyIconWpf/TaskbarIcon.cs create mode 100644 Source/NotifyIconWpf/Util.cs create mode 100644 Source/Sample Project/App.xaml create mode 100644 Source/Sample Project/App.xaml.cs create mode 100644 Source/Sample Project/Icons/Bulb.ico create mode 100644 Source/Sample Project/Icons/Computers.ico create mode 100644 Source/Sample Project/Icons/NetDrives.ico create mode 100644 Source/Sample Project/Properties/AssemblyInfo.cs create mode 100644 Source/Sample Project/Properties/Resources.Designer.cs create mode 100644 Source/Sample Project/Properties/Resources.resx create mode 100644 Source/Sample Project/Properties/Settings.Designer.cs create mode 100644 Source/Sample Project/Properties/Settings.settings create mode 100644 Source/Sample Project/Sample Project.csproj create mode 100644 Source/Sample Project/Window1.xaml create mode 100644 Source/Sample Project/Window1.xaml.cs diff --git a/Source/NotifyIconWpf.sln b/Source/NotifyIconWpf.sln new file mode 100644 index 0000000..f4acf09 --- /dev/null +++ b/Source/NotifyIconWpf.sln @@ -0,0 +1,38 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotifyIconWpf", "NotifyIconWpf\NotifyIconWpf.csproj", "{7AC63864-7638-41C4-969C-D3197EF2BED9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApplication2", "ConsoleApplication2\ConsoleApplication2.csproj", "{A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApplication1", "ConsoleApplication1\ConsoleApplication1.csproj", "{10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample Project", "Sample Project\Sample Project.csproj", "{71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.Build.0 = Release|Any CPU + {A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}.Release|Any CPU.Build.0 = Release|Any CPU + {10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}.Release|Any CPU.Build.0 = Release|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Source/NotifyIconWpf.sln.cache b/Source/NotifyIconWpf.sln.cache new file mode 100644 index 0000000..e57874d --- /dev/null +++ b/Source/NotifyIconWpf.sln.cache @@ -0,0 +1,236 @@ + + + <_SolutionProjectConfiguration>Debug|Any CPU + <_SolutionProjectToolsVersion>3.5 + <_SolutionProjectCacheVersion>3.5 + + + <_SolutionProjectProjects Include="ConsoleApplication1\ConsoleApplication1.csproj" /> + <_SolutionProjectProjects Include="ConsoleApplication2\ConsoleApplication2.csproj" /> + <_SolutionProjectProjects Include="NotifyIconWpf\NotifyIconWpf.csproj" /> + <_SolutionProjectProjects Include="Sample Project\Sample Project.csproj" /> + + + + Debug + AnyCPU + + + Debug + AnyCPU + + + Debug + AnyCPU + + + Debug + AnyCPU + + + + + Release + AnyCPU + + + Release + AnyCPU + + + Release + AnyCPU + + + Release + AnyCPU + + + + + + Debug + + + Any CPU + + + $(Configuration) + + + D:\Philipp\Repositories\evolve.net\WPF\NotifyIcon\Source\ + .sln + NotifyIconWpf.sln + NotifyIconWpf + D:\Philipp\Repositories\evolve.net\WPF\NotifyIcon\Source\NotifyIconWpf.sln + + + v2.0 + v3.5 + + + + + Debug|AnyCPU + Debug|AnyCPU + Debug|AnyCPU + Debug|AnyCPU + + + + + + + Release|AnyCPU + Release|AnyCPU + Release|AnyCPU + Release|AnyCPU + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/NotifyIconWpf/BalloonIcon.cs b/Source/NotifyIconWpf/BalloonIcon.cs new file mode 100644 index 0000000..018aae9 --- /dev/null +++ b/Source/NotifyIconWpf/BalloonIcon.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Supported icons for the tray's ballon messages. + /// + public enum BalloonIcon + { + /// + /// The balloon message is displayed without an icon. + /// + None, + /// + /// An information is displayed. + /// + Info, + /// + /// A warning is displayed. + /// + Warning, + /// + /// An error is displayed. + /// + Error + } +} diff --git a/Source/NotifyIconWpf/DefaultTrayIcon.ico b/Source/NotifyIconWpf/DefaultTrayIcon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e3ff3c4bf60174f7cc6140efc302f7098ae911fc GIT binary patch literal 1150 zcmZQzU<5(|0R|wcz>vYhz#zuJz@P!dKp~(AL>x$w1a$TERC983*Voq8Zn3qs)g?tU zCpWjSlZ)G?#N^cfwRLs>laiAU35$rx5o-pYfPk)xhv)0k%Ig0cHg5Xg)7$q!R7}j2 zSpDJ>68b^GA#ZbX^8PnBH~*hJY0@V(H8o3O^;;S1>%>QePs>V8Sec)dvZ^pUW4fc2 znK7~Y&jq(p@p5TifL-HtaeCEjKBj2Twl4W)iS958p* z46CxdEXNo>cYZ=<#0UErw>LGotX#I#a^duT&$WwZ2XEiJ(QVq~NluyZk%rz@hK#t( z2z9p?%TG)6S+aPs?T&3*y|!&!nYefRy4>SO4khi_zRk0$q|iAw$XgVb{wP0p^M=}L zk2R}TyB<5VzvTGgy$weX?y5U^^l<5cy}OgQZ{3p6*WO}}O}_#s17l8docFGsJ2K|Z zo$I<~!@7(;+cq_9-?YAH|BkJ#ySHrUx^?~9!i}p}W&`zO^+Rn*e!#i2XS%0Mnc_Wt z>eRrEtCqFyShsTV)-}slZd2l!QxvW<-EUOKI-h>D{fXmd>5oym{@a#*ORO zWp7wAf9;~lJ$IXmGPflMdCKC_4-(Ib4$`g5PoH;i*Y-1y9y~bt^vRP0XO11d(o~$Y zI@;5os63G1=PEI0Qcv=sJv*lzJGgJg%7t^%!rbj8vDy2_evRV~c})C)e~se@_BD + /// Flags that define the icon that is shown on a balloon + /// tooltip. + /// + public enum BalloonFlags + { + /// + /// No icon is displayed. + /// + None = 0x00, + /// + /// An information icon is displayed. + /// + Info = 0x01, + /// + /// A warning icon is displayed. + /// + Warning = 0x02, + /// + /// An error icon is displayed. + /// + Error = 0x03, + /// + /// Windows XP Service Pack 2 (SP2) and later. + /// Use a custom icon as the title icon. + /// + User = 0x04, + /// + /// Windows XP (Shell32.dll version 6.0) and later. + /// Do not play the associated sound. Applies only to balloon ToolTips. + /// + NoSound = 0x10, + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The large version + /// of the icon should be used as the balloon icon. This corresponds to the + /// icon with dimensions SM_CXICON x SM_CYICON. If this flag is not set, + /// the icon with dimensions XM_CXSMICON x SM_CYSMICON is used.
+ /// - This flag can be used with all stock icons.
+ /// - Applications that use older customized icons (NIIF_USER with hIcon) must + /// provide a new SM_CXICON x SM_CYICON version in the tray icon (hIcon). These + /// icons are scaled down when they are displayed in the System Tray or + /// System Control Area (SCA).
+ /// - New customized icons (NIIF_USER with hBalloonIcon) must supply an + /// SM_CXICON x SM_CYICON version in the supplied icon (hBalloonIcon). + ///
+ LargeIcon = 0x20, + /// + /// Windows 7 and later. + /// + RespectQuietTime = 0x80 + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/IconDataMembers.cs b/Source/NotifyIconWpf/Interop/IconDataMembers.cs new file mode 100644 index 0000000..d3dd8db --- /dev/null +++ b/Source/NotifyIconWpf/Interop/IconDataMembers.cs @@ -0,0 +1,67 @@ +using System; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Indicates which members of a structure + /// were set, and thus contain valid data or provide additional information + /// to the ToolTip as to how it should display. + /// + [Flags] + public enum IconDataMembers + { + /// + /// The message ID is set. + /// + Message = 0x01, + /// + /// The notification icon is set. + /// + Icon = 0x02, + /// + /// The tooltip is set. + /// + Tip = 0x04, + /// + /// State information () is set. This + /// applies to both and + /// . + /// + State = 0x08, + /// + /// The ballon ToolTip is set. Accordingly, the following + /// members are set: , + /// , , + /// and . + /// + Info = 0x10, + + /// + /// Internal identifier is set. Reserved, thus commented out. + /// + //Guid = 0x20, + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. If the ToolTip + /// cannot be displayed immediately, discard it.
+ /// Use this flag for ToolTips that represent real-time information which + /// would be meaningless or misleading if displayed at a later time. + /// For example, a message that states "Your telephone is ringing."
+ /// This modifies and must be combined with the flag. + ///
+ Realtime = 0x40, + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. + /// Use the standard ToolTip. Normally, when uVersion is set + /// to NOTIFYICON_VERSION_4, the standard ToolTip is replaced + /// by the application-drawn pop-up user interface (UI). + /// If the application wants to show the standard tooltip + /// in that case, regardless of whether the on-hover UI is showing, + /// it can specify NIF_SHOWTIP to indicate the standard tooltip + /// should still be shown.
+ /// Note that the NIF_SHOWTIP flag is effective until the next call + /// to Shell_NotifyIcon. + ///
+ UseLegacyToolTips = 0x80 + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/IconState.cs b/Source/NotifyIconWpf/Interop/IconState.cs new file mode 100644 index 0000000..44a9e7f --- /dev/null +++ b/Source/NotifyIconWpf/Interop/IconState.cs @@ -0,0 +1,23 @@ +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// The state of the icon - can be set to + /// hide the icon. + /// + public enum IconState + { + /// + /// The icon is visible. + /// + Visible = 0x00, + /// + /// Hide the icon. + /// + Hidden = 0x01, + + /// + /// The icon is shared - currently not supported, thus commented out. + /// + //Shared = 0x02 + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/MouseEvent.cs b/Source/NotifyIconWpf/Interop/MouseEvent.cs new file mode 100644 index 0000000..c304289 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/MouseEvent.cs @@ -0,0 +1,46 @@ +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Event flags for clicked events. + /// + public enum MouseEvent + { + /// + /// The mouse was moved withing the + /// taskbar icon's area. + /// + MouseMove, + /// + /// The right mouse button was clicked. + /// + IconRightMouseDown, + /// + /// The left mouse button was clicked. + /// + IconLeftMouseDown, + /// + /// The right mouse button was released. + /// + IconRightMouseUp, + /// + /// The left mouse button was released. + /// + IconLeftMouseUp, + /// + /// The middle mouse button was clicked. + /// + IconMiddleMouseDown, + /// + /// The middle mouse button was released. + /// + IconMiddleMouseUp, + /// + /// The taskbar icon was double clicked. + /// + IconDoubleClick, + /// + /// The balloon tip was clicked. + /// + BalloonToolTipClicked + } +} diff --git a/Source/NotifyIconWpf/Interop/NotifyCommand.cs b/Source/NotifyIconWpf/Interop/NotifyCommand.cs new file mode 100644 index 0000000..7c3abde --- /dev/null +++ b/Source/NotifyIconWpf/Interop/NotifyCommand.cs @@ -0,0 +1,39 @@ +using System; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Main operations performed on the + /// function. + /// + public enum NotifyCommand + { + /// + /// The taskbar icon is being created. + /// + Add = 0x00, + /// + /// The settings of the taskbar icon are being updated. + /// + Modify = 0x01, + /// + /// The taskbar icon is deleted. + /// + Delete = 0x02, + /// + /// Focus is returned to the taskbar icon. Currently not in use. + /// + SetFocus = 0x03, + /// + /// Shell32.dll version 5.0 and later only. Instructs the taskbar + /// to behave according to the version number specified in the + /// uVersion member of the structure pointed to by lpdata. + /// This message allows you to specify whether you want the version + /// 5.0 behavior found on Microsoft Windows 2000 systems, or the + /// behavior found on earlier Shell versions. The default value for + /// uVersion is zero, indicating that the original Windows 95 notify + /// icon behavior should be used. + /// + SetVersion = 0x04 + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/NotifyIconData.cs b/Source/NotifyIconWpf/Interop/NotifyIconData.cs new file mode 100644 index 0000000..9f6f396 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/NotifyIconData.cs @@ -0,0 +1,153 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// A struct that is submitted in order to configure + /// the taskbar icon. Provides various members that + /// can be configured partially, according to the + /// values of the + /// that were defined. + /// + [StructLayout(LayoutKind.Sequential)] + public struct NotifyIconData + { + /// + /// Size of this structure, in bytes. + /// + public uint cbSize; + + /// + /// Handle to the window that receives notification messages associated with an icon in the + /// taskbar status area. The Shell uses hWnd and uID to identify which icon to operate on + /// when Shell_NotifyIcon is invoked. + /// + public IntPtr WindowHandle; + + /// + /// Application-defined identifier of the taskbar icon. The Shell uses hWnd and uID to identify + /// which icon to operate on when Shell_NotifyIcon is invoked. You can have multiple icons + /// associated with a single hWnd by assigning each a different uID. This feature, however + /// is currently not used. + /// + public uint TaskbarIconId; + + /// + /// Flags that indicate which of the other members contain valid data. This member can be + /// a combination of the NIF_XXX constants. + /// + public IconDataMembers ValidMembers; + + /// + /// Application-defined message identifier. The system uses this identifier to send + /// notifications to the window identified in hWnd. + /// + public uint CallbackMessageId; + + /// + /// A handle to the icon that should be displayed. Just + /// . + /// + public IntPtr IconHandle; + + /// + /// String with the text for a standard ToolTip. It can have a maximum of 64 characters including + /// the terminating NULL. For Version 5.0 and later, szTip can have a maximum of + /// 128 characters, including the terminating NULL. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string ToolTipText; + + + /// + /// State of the icon. Remember to also set the . + /// + public IconState IconState; + + /// + /// A value that specifies which bits of the state member are retrieved or modified. + /// For example, setting this member to + /// causes only the item's hidden + /// state to be retrieved. + /// + public IconState StateMask; + + /// + /// String with the text for a balloon ToolTip. It can have a maximum of 255 characters. + /// To remove the ToolTip, set the NIF_INFO flag in uFlags and set szInfo to an empty string. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string BalloonText; + + /// + /// Mainly used to set the version when is invoked + /// with . However, for legacy operations, + /// the same member is also used to set timouts for balloon ToolTips. + /// + public uint VersionOrTimeout; + + /// + /// String containing a title for a balloon ToolTip. This title appears in boldface + /// above the text. It can have a maximum of 63 characters. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string BalloonTitle; + + /// + /// Adds an icon to a balloon ToolTip, which is placed to the left of the title. If the + /// member is zero-length, the icon is not shown. + /// + public BalloonFlags BalloonFlags; + + /// + /// Windows XP (Shell32.dll version 6.0) and later.
+ /// - Windows 7 and later: A registered GUID that identifies the icon. + /// This value overrides uID and is the recommended method of identifying the icon.
+ /// - Windows XP through Windows Vista: Reserved. + ///
+ public Guid TaskbarIconGuid; + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The handle of a customized + /// balloon icon provided by the application that should be used independently + /// of the tray icon. If this member is non-NULL and the + /// flag is set, this icon is used as the balloon icon.
+ /// If this member is NULL, the legacy behavior is carried out. + ///
+ public IntPtr CustomBalloonIconHandle; + + + /// + /// Creates a default data structure that provides + /// a hidden taskbar icon without the icon being set. + /// + /// + /// + public static NotifyIconData CreateDefault(IntPtr handle) + { + var data = new NotifyIconData(); + + data.cbSize = (uint) Marshal.SizeOf(data); + + data.WindowHandle = handle; + data.TaskbarIconId = 0x0; + data.CallbackMessageId = WindowMessageSink.CallbackMessageId; + data.VersionOrTimeout = (uint) NotifyIconVersion.Win95; + + data.IconHandle = IntPtr.Zero; + + //hide initially + data.IconState = IconState.Hidden; + data.StateMask = IconState.Hidden; + + //set flags + data.ValidMembers = IconDataMembers.Message + | IconDataMembers.Icon + | IconDataMembers.Tip; + + //reset strings + data.ToolTipText = data.BalloonText = data.BalloonTitle = String.Empty; + + return data; + } + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs b/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs new file mode 100644 index 0000000..8be1618 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// The notify icon version that is used. The higher + /// the version, the more capabilities are available. + /// + public enum NotifyIconVersion + { + /// + /// Default behavior (legacy Win95). + /// + Win95 = 0x0, + /// + /// Behavior representing Win2000 an higher. + /// + Win2000 = 0x3, + /// + /// Extended tooltip support, which is available + /// for Vista and later. + /// + Vista = 0x4 + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/TrayLocator.cs b/Source/NotifyIconWpf/Interop/TrayLocator.cs new file mode 100644 index 0000000..de524a8 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/TrayLocator.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + public struct Rect + { + public int left; + public int top; + public int right; + public int bottom; + public override string ToString() + { + return "(" + left + ", " + top + ") --> (" + right + ", " + bottom + ")"; + } + } + + public struct TaskbarInfo + { + public int cbSize; + public IntPtr WindowHandle; + public int uCallbackMessage; + public TaskbarPosition Position; + public Rect Rectangle; + public IntPtr lParam; + } + + + + public enum TaskbarPosition + { + Left = 0, + Top, + Right, + Bottom + } + + + + + /// + /// Locates the position of the tray area. + /// + public class TrayLocator + { + public enum ABMsg + { + ABM_NEW = 0, + ABM_REMOVE = 1, + ABM_QUERYPOS = 2, + ABM_SETPOS = 3, + ABM_GETSTATE = 4, + ABM_GETTASKBARPOS = 5, + ABM_ACTIVATE = 6, + ABM_GETAUTOHIDEBAR = 7, + ABM_SETAUTOHIDEBAR = 8, + ABM_WINDOWPOSCHANGED = 9, + ABM_SETSTATE = 10 + } + + public enum ABNotify + { + ABN_STATECHANGE = 0, + ABN_POSCHANGED, + ABN_FULLSCREENAPP, + ABN_WINDOWARRANGE + } + + [DllImport("shell32.dll", EntryPoint = "SHAppBarMessage", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern int SHAppBarMessage(int dwMessage, ref TaskbarInfo pData); + + + /// + /// Determines the current location of the taskbar. + /// + /// + public static TaskbarInfo GetTaskbarInformation() + { + TaskbarInfo tbInfo = new TaskbarInfo(); + tbInfo.cbSize = Marshal.SizeOf(tbInfo); + + //retrieve the bounding rectangle of the Windows taskbar. + SHAppBarMessage((int)ABMsg.ABM_GETTASKBARPOS, ref tbInfo); + + return tbInfo; + } + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WinApi.cs b/Source/NotifyIconWpf/Interop/WinApi.cs new file mode 100644 index 0000000..7df8f20 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/WinApi.cs @@ -0,0 +1,80 @@ +using System; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Win32 API imports. + /// + internal static class WinApi + { + /// + /// Creates, updates or deletes the taskbar icon. + /// + [DllImport("shell32.Dll")] + public static extern bool Shell_NotifyIcon(NotifyCommand cmd, [In]ref NotifyIconData data); + + + /// + /// Creates the helper window that receives messages from the taskar icon. + /// + [DllImport("USER32.DLL", EntryPoint = "CreateWindowExW", SetLastError = true)] + public static extern IntPtr CreateWindowEx(int dwExStyle, [MarshalAs(UnmanagedType.LPWStr)] string lpClassName, + [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, int dwStyle, int x, int y, + int nWidth, int nHeight, uint hWndParent, int hMenu, int hInstance, + int lpParam); + + + /// + /// Processes a default windows procedure. + /// + [DllImport("USER32.DLL")] + public static extern long DefWindowProc(IntPtr hWnd, uint msg, uint wparam, uint lparam); + + /// + /// Registers the helper window class. + /// + [DllImport("USER32.DLL", EntryPoint = "RegisterClassW", SetLastError = true)] + public static extern short RegisterClass(ref WindowClass lpWndClass); + + /// + /// Registers a listener for a window message. + /// + /// + /// + [DllImport("User32.Dll", EntryPoint = "RegisterWindowMessageW")] + public static extern uint RegisterWindowMessage([MarshalAs(UnmanagedType.LPWStr)] string lpString); + + /// + /// Used to destroy the hidden helper window that receives messages from the + /// taskbar icon. + /// + /// + /// + [DllImport("USER32.DLL", SetLastError = true)] + public static extern bool DestroyWindow(IntPtr hWnd); + + + /// + /// Gives focus to a given window. + /// + /// + /// + [DllImport("USER32.DLL")] + public static extern bool SetForegroundWindow(IntPtr hWnd); + + + /// + /// Gets the maximum number of milliseconds that can elapse between a + /// first click and a second click for the OS to consider the + /// mouse action a double-click. + /// + /// The maximum amount of time, in milliseconds, that can + /// elapse between a first click and a second click for the OS to + /// consider the mouse action a double-click. + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + public static extern int GetDoubleClickTime(); + + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowClass.cs b/Source/NotifyIconWpf/Interop/WindowClass.cs new file mode 100644 index 0000000..e4f625a --- /dev/null +++ b/Source/NotifyIconWpf/Interop/WindowClass.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Callback delegate which is used by the Windows API to + /// submit window messages. + /// + public delegate long WindowProcedureHandler(IntPtr hwnd, uint uMsg, uint wparam, uint lparam); + + + /// + /// Win API WNDCLASS struct - represents a single window. + /// Used to receive window messages. + /// + [StructLayout(LayoutKind.Sequential)] + public struct WindowClass + { + public uint style; + public WindowProcedureHandler lpfnWndProc; + public int cbClsExtra; + public int cbWndExtra; + public IntPtr hInstance; + public IntPtr hIcon; + public IntPtr hCursor; + public IntPtr hbrBackground; + [MarshalAs(UnmanagedType.LPWStr)] public string lpszMenuName; + [MarshalAs(UnmanagedType.LPWStr)] public string lpszClassName; + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs new file mode 100644 index 0000000..5a4d4e9 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs @@ -0,0 +1,102 @@ +using System; +using System.ComponentModel; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Provides low level code that is used to receive + /// window messages without having a window that + /// prevents a WPF application from shutting down + /// properly. + /// + public partial class WindowMessageSink + { + /// + /// Window class ID. + /// + private string WindowId; + + /// + /// Handle for the message window. + /// + /// The ID of the message that is being received if the + /// taskbar is (re)started. + /// + private uint taskbarRestartMessageId; + + /// + /// A delegate that processes messages of the hidden + /// native window that receives window messages. Storing + /// this reference makes sure we don't loose our reference + /// to the message window. + /// + private WindowProcedureHandler messageHandler; + + /// + /// Creates the helper message window that is used + /// to receive messages from the taskbar icon. + /// + private void CreateMessageWindow() + { + WindowId = "WPFTaskbarIcon_" + Guid.NewGuid().ToString(); + + //register window message handler + messageHandler = OnWindowMessageReceived; + + // Create a simple window class which is reference through + //the messageHandler delegate + WindowClass wc; + + wc.style = 0; + wc.lpfnWndProc = messageHandler; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = IntPtr.Zero; + wc.hIcon = IntPtr.Zero; + wc.hCursor = IntPtr.Zero; + wc.hbrBackground = IntPtr.Zero; + wc.lpszMenuName = ""; + wc.lpszClassName = WindowId; + + // Register the window class + WinApi.RegisterClass(ref wc); + + // Get the message used to indicate the taskbar has been restarted + // This is used to re-add icons when the taskbar restarts + taskbarRestartMessageId = WinApi.RegisterWindowMessage("TaskbarCreated"); + + // Create the message window + MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, 0, 0, 0, 0); + + if (MessageWindowHandle == IntPtr.Zero) + { + throw new Win32Exception(); + } + } + + + + /// + /// Callback method that receives messages from the taskbar area. + /// + private long OnWindowMessageReceived(IntPtr hwnd, uint messageId, uint wparam, uint lparam) + { + if (messageId == taskbarRestartMessageId) + { + //recreate the icon if the taskbar was restarted + //TODO refresh icon + } + + ProcessWindowMessage(messageId, wparam, lparam); + + //handle mouse clicks... + + // Pass the message to the default window procedure + return WinApi.DefWindowProc(hwnd, messageId, wparam, lparam); + } + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs new file mode 100644 index 0000000..29e2542 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -0,0 +1,255 @@ +using System; +using System.Diagnostics; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Receives messages from the taskbar icon through + /// window messages of an underlying helper window. + /// + public partial class WindowMessageSink : IDisposable + { + + #region members + + /// + /// The ID of messages that are received from the the + /// taskbar icon. + /// + public const int CallbackMessageId = 0x400; + + /// + /// The version of the underlying icon. Defines how + /// incoming messages are interpreted. + /// + public NotifyIconVersion Version { get; set; } + + #endregion + + + #region events + + /// + /// The custom tooltip should be closed or hidden. + /// + public event Action ChangeToolTipStateRequest; + + /// + /// Fired in case the user clicked or moved within + /// the taskbar icon area. + /// + public event Action MouseEventReceived; + + /// + /// Fired if a balloon ToolTip was either displayed + /// or closed (indicated by the boolean flag). + /// + public event Action BallonToolTipChanged; + + /// + /// Fired if the taskbar was created. Requires the taskbar + /// icon to be reset. + /// + public event Action TaskbarCreated; + + #endregion + + + #region construction + + /// + /// Creates a new message sink that receives message from + /// a given taskbar icon. + /// + /// + public WindowMessageSink(NotifyIconVersion version) + { + Version = version; + CreateMessageWindow(); + } + + + private WindowMessageSink() + { + } + + + /// + /// Creates a dummy instance that provides an empty + /// pointer rather than a real window handler.
+ /// Used at design time. + ///
+ /// + internal static WindowMessageSink CreateEmpty() + { + return new WindowMessageSink + { + MessageWindowHandle = IntPtr.Zero, + Version = NotifyIconVersion.Vista + }; + } + + #endregion + + + #region Process Window Messages + + /// + /// Processes incoming system messages. + /// + /// + /// + /// + /// + private void ProcessWindowMessage(uint msg, uint wParam, uint lParam) + { + if (msg != CallbackMessageId) return; + + switch (lParam) + { + case 0x200: +// Debug.WriteLine("MOVE"); + MouseEventReceived(MouseEvent.MouseMove); + break; + + case 0x201: + Debug.WriteLine("left down 1"); + MouseEventReceived(MouseEvent.IconLeftMouseDown); + break; + + case 0x202: + Debug.WriteLine("left up"); + MouseEventReceived(MouseEvent.IconLeftMouseUp); + break; + + case 0x203: + Debug.WriteLine("left click 2"); + MouseEventReceived(MouseEvent.IconDoubleClick); + break; + + case 0x204: + Debug.WriteLine("right click 1"); + MouseEventReceived(MouseEvent.IconRightMouseDown); + break; + + case 0x205: + Console.Out.WriteLine("right mouse up"); + MouseEventReceived(MouseEvent.IconRightMouseUp); + break; + + case 0x206: + //double click with right mouse button - do not trigger event + Debug.WriteLine("right click 2"); + break; + + case 0x207: + Debug.WriteLine("middle click 1"); + MouseEventReceived(MouseEvent.IconMiddleMouseDown); + break; + + case 520: + Debug.WriteLine("mouse up middle"); + MouseEventReceived(MouseEvent.IconMiddleMouseUp); + break; + + case 0x209: + //double click with middle mouse button - do not trigger event + Debug.WriteLine("middle click 2"); + break; + + case 0x402: + Debug.WriteLine("balloon shown"); + BallonToolTipChanged(true); + break; + + case 0x403: + case 0x404: + Debug.WriteLine("balloon close"); + BallonToolTipChanged(false); + break; + + case 0x405: + Debug.WriteLine("balloon clicked"); + MouseEventReceived(MouseEvent.BalloonToolTipClicked); + break; + + case 0x406: + Debug.WriteLine("show custom tooltip"); + ChangeToolTipStateRequest(true); + break; + + case 0x407: + Debug.WriteLine("close custom tooltip"); + ChangeToolTipStateRequest(false); + break; + + default: + Debug.WriteLine("Unhandled message ID: " + lParam); + break; + } + + } + + #endregion + + + + #region Dispose + + /// + /// Set to true as soon as + /// has been invoked. + /// + public bool IsDisposed { get; private set; } + + + /// + /// Disposes the object. + /// + /// This method is not virtual by design. Derived classes + /// should override . + /// + public void Dispose() + { + Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// This destructor will run only if the + /// method does not get called. This gives this base class the + /// opportunity to finalize. + /// + /// Important: Do not provide destructors in types derived from + /// this class. + /// + /// + ~WindowMessageSink() + { + Dispose(false); + } + + + /// + /// Removes the windows hook that receives window + /// messages and closes the underlying helper window. + /// + private void Dispose(bool disposing) + { + //don't do anything if the component is already disposed + if (IsDisposed || !disposing) return; + IsDisposed = true; + + WinApi.DestroyWindow(MessageWindowHandle); + messageHandler = null; + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj new file mode 100644 index 0000000..a3b1416 --- /dev/null +++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -0,0 +1,108 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {7AC63864-7638-41C4-969C-D3197EF2BED9} + library + Properties + Hardcodet.Wpf.TaskbarNotification + Hardcodet.Wpf.TaskbarNotification + v3.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + \ No newline at end of file diff --git a/Source/NotifyIconWpf/PopupActivationMode.cs b/Source/NotifyIconWpf/PopupActivationMode.cs new file mode 100644 index 0000000..81248b8 --- /dev/null +++ b/Source/NotifyIconWpf/PopupActivationMode.cs @@ -0,0 +1,45 @@ +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Defines flags that define when a popup + /// is being displyed. + /// + public enum PopupActivationMode + { + /// + /// The item is displayed if the user clicks the + /// tray icon with the left mouse button. + /// + LeftClick, + /// + /// The item is displayed if the user clicks the + /// tray icon with the right mouse button. + /// + RightClick, + /// + /// The item is displayed if the user double-clicks the + /// tray icon. + /// + DoubleClick, + /// + /// The item is displayed if the user clicks the + /// tray icon with the left or the right mouse button. + /// + LeftOrRightClick, + /// + /// The item is displayed if the user clicks the + /// tray icon with the left mouse button or if a + /// double-click is being performed. + /// + LeftOrDoubleClick, + /// + /// The item is displayed if the user clicks the + /// tray icon with the middle mouse button. + /// + MiddleClick, + /// + /// The item is displayed whenever a click occurs. + /// + All + } +} diff --git a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..adfde1d --- /dev/null +++ b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Markup; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("NotifyIconWpf")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("NotifyIconWpf")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + + +[assembly: XmlnsDefinition("http://www.hardcodet.net/taskbar", "Hardcodet.Wpf.TaskbarNotification")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/NotifyIconWpf/Properties/Resources.Designer.cs b/Source/NotifyIconWpf/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d78e26d --- /dev/null +++ b/Source/NotifyIconWpf/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Hardcodet.Wpf.TaskbarNotification.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Hardcodet.Wpf.TaskbarNotification.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Icon DefaultTrayIcon { + get { + object obj = ResourceManager.GetObject("DefaultTrayIcon", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/Source/NotifyIconWpf/Properties/Resources.resx b/Source/NotifyIconWpf/Properties/Resources.resx new file mode 100644 index 0000000..c0f916f --- /dev/null +++ b/Source/NotifyIconWpf/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\defaulttrayicon.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Source/NotifyIconWpf/Properties/Settings.Designer.cs b/Source/NotifyIconWpf/Properties/Settings.Designer.cs new file mode 100644 index 0000000..b9cf0e1 --- /dev/null +++ b/Source/NotifyIconWpf/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Hardcodet.Wpf.TaskbarNotification.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Source/NotifyIconWpf/Properties/Settings.settings b/Source/NotifyIconWpf/Properties/Settings.settings new file mode 100644 index 0000000..8f2fd95 --- /dev/null +++ b/Source/NotifyIconWpf/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/NotifyIconWpf/RoutedEventHelper.cs b/Source/NotifyIconWpf/RoutedEventHelper.cs new file mode 100644 index 0000000..127ec77 --- /dev/null +++ b/Source/NotifyIconWpf/RoutedEventHelper.cs @@ -0,0 +1,81 @@ +using System; +using System.Windows; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Helper class used by routed events of the + /// class. + /// + internal static class RoutedEventHelper + { + #region RoutedEvent Helper Methods + + /// + /// A static helper method to raise a routed event on a target UIElement or ContentElement. + /// + /// UIElement or ContentElement on which to raise the event + /// RoutedEventArgs to use when raising the event + internal static void RaiseEvent(DependencyObject target, RoutedEventArgs args) + { + if (target is UIElement) + { + (target as UIElement).RaiseEvent(args); + } + else if (target is ContentElement) + { + (target as ContentElement).RaiseEvent(args); + } + } + + /// + /// A static helper method that adds a handler for a routed event + /// to a target UIElement or ContentElement. + /// + /// UIElement or ContentElement that listens to the event + /// Event that will be handled + /// Event handler to be added + internal static void AddHandler(DependencyObject element, RoutedEvent routedEvent, Delegate handler) + { + UIElement uie = element as UIElement; + if (uie != null) + { + uie.AddHandler(routedEvent, handler); + } + else + { + ContentElement ce = element as ContentElement; + if (ce != null) + { + ce.AddHandler(routedEvent, handler); + } + } + } + + /// + /// A static helper method that removes a handler for a routed event + /// from a target UIElement or ContentElement. + /// + /// UIElement or ContentElement that listens to the event + /// Event that will no longer be handled + /// Event handler to be removed + internal static void RemoveHandler(DependencyObject element, RoutedEvent routedEvent, Delegate handler) + { + UIElement uie = element as UIElement; + if (uie != null) + { + uie.RemoveHandler(routedEvent, handler); + } + else + { + ContentElement ce = element as ContentElement; + if (ce != null) + { + ce.RemoveHandler(routedEvent, handler); + } + } + } + + #endregion + } +} diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs new file mode 100644 index 0000000..e3a893a --- /dev/null +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -0,0 +1,868 @@ +using System; +using System.Drawing; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; +using Hardcodet.Wpf.TaskbarNotification.Interop; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Contains declarations of WPF dependency properties + /// and events. + /// + partial class TaskbarIcon + { + //DEPENDENCY PROPERTIES + + #region ToolTipText dependency property + + /// + /// A tooltip text that is being displayed if no custom + /// was set or if custom tooltips are not supported. + /// + public static readonly DependencyProperty ToolTipTextProperty = + DependencyProperty.Register("ToolTipText", + typeof (string), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(String.Empty, ToolTipTextPropertyChanged)); + + + /// + /// A property wrapper for the + /// dependency property:
+ /// A tooltip text that is being displayed if no custom + /// was set or if custom tooltips are not supported. + ///
+ public string ToolTipText + { + get { return (string) GetValue(ToolTipTextProperty); } + set { SetValue(ToolTipTextProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnToolTipTextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e) + { + string newValue = (string) e.NewValue; + + iconData.ToolTipText = newValue ?? String.Empty; + WriteToolTipSettings(); + } + + #endregion + + + #region ToolTip dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnToolTipPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnToolTipPropertyChanged(DependencyPropertyChangedEventArgs e) + { + if (e.NewValue != null) + { + ToolTip tt = e.NewValue as ToolTip; + if (tt == null) + { + tt = new ToolTip(); + tt.Content = e.NewValue; + + ToolTip = tt; + return; + } + } + + WriteToolTipSettings(); + } + + #endregion + + + #region Icon property / IconSource dependency property + + private Icon icon; + + /// + /// Gets or sets the icon to be displayed. This is not a + /// dependency property - if you want to assign the property + /// through XAML, please use the + /// dependency property. + /// + public Icon Icon + { + get { return icon; } + set + { + icon = value; + iconData.IconHandle = value == null ? IntPtr.Zero : icon.Handle; + + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Icon); + } + } + + + /// + /// Resolves an image source and updates the property accordingly. + /// + public static readonly DependencyProperty IconSourceProperty = + DependencyProperty.Register("IconSource", + typeof (ImageSource), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, IconSourcePropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Resolves an image source and updates the property accordingly. + ///
+ public ImageSource IconSource + { + get { return (ImageSource) GetValue(IconSourceProperty); } + set { SetValue(IconSourceProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnIconSourcePropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e) + { + ImageSource newValue = (ImageSource) e.NewValue; + Icon = newValue.ToIcon(); + } + + #endregion + + + #region TaskbarIconPopup dependency property + + /// + /// A custom popup that is displayed when the taskbar icon is clicked. + /// + public static readonly DependencyProperty TaskbarIconPopupProperty = + DependencyProperty.Register("TaskbarIconPopup", + typeof (Popup), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, TaskbarIconPopupPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// A custom popup that is displayed when the taskbar icon is clicked. + ///
+ public Popup TaskbarIconPopup + { + get { return (Popup) GetValue(TaskbarIconPopupProperty); } + set { SetValue(TaskbarIconPopupProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void TaskbarIconPopupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnTaskbarIconPopupPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnTaskbarIconPopupPropertyChanged(DependencyPropertyChangedEventArgs e) + { + Popup newValue = (Popup) e.NewValue; + } + + #endregion + + + #region MenuActivation dependency property + + /// + /// Defines what mouse events display the context menu. + /// Defaults to . + /// + public static readonly DependencyProperty MenuActivationProperty = + DependencyProperty.Register("MenuActivation", + typeof (PopupActivationMode), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(PopupActivationMode.RightClick, MenuActivationPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Defines what mouse events display the context menu. + /// Defaults to . + ///
+ public PopupActivationMode MenuActivation + { + get { return (PopupActivationMode) GetValue(MenuActivationProperty); } + set { SetValue(MenuActivationProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void MenuActivationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnMenuActivationPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnMenuActivationPropertyChanged(DependencyPropertyChangedEventArgs e) + { + PopupActivationMode newValue = (PopupActivationMode) e.NewValue; + + //TODO provide implementation + throw new NotImplementedException("Change event handler for dependency property MenuActivation not implemented."); + } + + #endregion + + + #region PopupActivation dependency property + + /// + /// Defines what mouse events trigger the . + /// Default is . + /// + public static readonly DependencyProperty PopupActivationProperty = + DependencyProperty.Register("PopupActivation", + typeof (PopupActivationMode), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(PopupActivationMode.LeftClick, PopupActivationPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Defines what mouse events trigger the . + /// Default is . + ///
+ public PopupActivationMode PopupActivation + { + get { return (PopupActivationMode) GetValue(PopupActivationProperty); } + set { SetValue(PopupActivationProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void PopupActivationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnPopupActivationPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnPopupActivationPropertyChanged(DependencyPropertyChangedEventArgs e) + { + PopupActivationMode newValue = (PopupActivationMode) e.NewValue; + + //TODO provide implementation + throw new NotImplementedException("Change event handler for dependency property PopupActivation not implemented."); + } + + #endregion + + + #region Visibility dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnVisibilityPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnVisibilityPropertyChanged(DependencyPropertyChangedEventArgs e) + { + Visibility newValue = (Visibility) e.NewValue; + + //update + if (newValue == Visibility.Visible) + { + CreateTaskbarIcon(); + } + else + { + RemoveTaskbarIcon(); + } + } + + #endregion + + + #region ContextMenu dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnContextMenuPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) + { + ContextMenu newValue = (ContextMenu) e.NewValue; + //TODO provide implementation + } + + #endregion + + + + //EVENTS + + #region TaskbarIconLeftMouseDown + + /// + /// TaskbarIconLeftMouseDown Routed Event + /// + public static readonly RoutedEvent TaskbarIconLeftMouseDownEvent = EventManager.RegisterRoutedEvent("TaskbarIconLeftMouseDown", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user presses the left mouse button. + /// + public event RoutedEventHandler TaskbarIconLeftMouseDown + { + add { AddHandler(TaskbarIconLeftMouseDownEvent, value); } + remove { RemoveHandler(TaskbarIconLeftMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconLeftMouseDown event. + /// + protected RoutedEventArgs RaiseTaskbarIconLeftMouseDownEvent() + { + return RaiseTaskbarIconLeftMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconLeftMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconLeftMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconLeftMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconRightMouseDown + + /// + /// TaskbarIconRightMouseDown Routed Event + /// + public static readonly RoutedEvent TaskbarIconRightMouseDownEvent = EventManager.RegisterRoutedEvent("TaskbarIconRightMouseDown", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the presses the right mouse button. + /// + public event RoutedEventHandler TaskbarIconRightMouseDown + { + add { AddHandler(TaskbarIconRightMouseDownEvent, value); } + remove { RemoveHandler(TaskbarIconRightMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconRightMouseDown event. + /// + protected RoutedEventArgs RaiseTaskbarIconRightMouseDownEvent() + { + return RaiseTaskbarIconRightMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconRightMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconRightMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconRightMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconLeftMouseUp + + /// + /// TaskbarIconLeftMouseUp Routed Event + /// + public static readonly RoutedEvent TaskbarIconLeftMouseUpEvent = EventManager.RegisterRoutedEvent("TaskbarIconLeftMouseUp", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user releases the left mouse button. + /// + public event RoutedEventHandler TaskbarIconLeftMouseUp + { + add { AddHandler(TaskbarIconLeftMouseUpEvent, value); } + remove { RemoveHandler(TaskbarIconLeftMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconLeftMouseUp event. + /// + protected RoutedEventArgs RaiseTaskbarIconLeftMouseUpEvent() + { + return RaiseTaskbarIconLeftMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconLeftMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconLeftMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconLeftMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconRightMouseUp + + /// + /// TaskbarIconRightMouseUp Routed Event + /// + public static readonly RoutedEvent TaskbarIconRightMouseUpEvent = EventManager.RegisterRoutedEvent("TaskbarIconRightMouseUp", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user releases the right mouse button. + /// + public event RoutedEventHandler TaskbarIconRightMouseUp + { + add { AddHandler(TaskbarIconRightMouseUpEvent, value); } + remove { RemoveHandler(TaskbarIconRightMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconRightMouseUp event. + /// + protected RoutedEventArgs RaiseTaskbarIconRightMouseUpEvent() + { + return RaiseTaskbarIconRightMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconRightMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconRightMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconRightMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + #region TaskbarIconPopupOpen (and PreviewTaskbarIconPopupOpen) + + /// + /// TaskbarIconPopupOpen Routed Event + /// + public static readonly RoutedEvent TaskbarIconPopupOpenEvent = EventManager.RegisterRoutedEvent("TaskbarIconPopupOpen", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Bubbled event that occurs when the custom popup is being opened. + /// + public event RoutedEventHandler TaskbarIconPopupOpen + { + add { AddHandler(TaskbarIconPopupOpenEvent, value); } + remove { RemoveHandler(TaskbarIconPopupOpenEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconPopupOpen event. + /// + protected RoutedEventArgs RaiseTaskbarIconPopupOpenEvent() + { + return RaiseTaskbarIconPopupOpenEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconPopupOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconPopupOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconPopupOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTaskbarIconPopupOpen Routed Event + /// + public static readonly RoutedEvent PreviewTaskbarIconPopupOpenEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconPopupOpen", + RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Tunneled event that occurs when the custom popup is being opened. + /// + public event RoutedEventHandler PreviewTaskbarIconPopupOpen + { + add { AddHandler(PreviewTaskbarIconPopupOpenEvent, value); } + remove { RemoveHandler(PreviewTaskbarIconPopupOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTaskbarIconPopupOpen event. + /// + protected RoutedEventArgs RaisePreviewTaskbarIconPopupOpenEvent() + { + return RaisePreviewTaskbarIconPopupOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTaskbarIconPopupOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTaskbarIconPopupOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTaskbarIconPopupOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconToolTipOpen (and PreviewTaskbarIconToolTipOpen) + + /// + /// TaskbarIconToolTipOpen Routed Event + /// + public static readonly RoutedEvent TaskbarIconToolTipOpenEvent = EventManager.RegisterRoutedEvent("TaskbarIconToolTipOpen", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Bubbled event that occurs when the custom ToolTip is being displayed. + /// + public event RoutedEventHandler TaskbarIconToolTipOpen + { + add { AddHandler(TaskbarIconToolTipOpenEvent, value); } + remove { RemoveHandler(TaskbarIconToolTipOpenEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconToolTipOpen event. + /// + protected RoutedEventArgs RaiseTaskbarIconToolTipOpenEvent() + { + return RaiseTaskbarIconToolTipOpenEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconToolTipOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconToolTipOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconToolTipOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTaskbarIconToolTipOpen Routed Event + /// + public static readonly RoutedEvent PreviewTaskbarIconToolTipOpenEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconToolTipOpen", + RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Tunneled event that occurs when the custom ToolTip is being displayed. + /// + public event RoutedEventHandler PreviewTaskbarIconToolTipOpen + { + add { AddHandler(PreviewTaskbarIconToolTipOpenEvent, value); } + remove { RemoveHandler(PreviewTaskbarIconToolTipOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTaskbarIconToolTipOpen event. + /// + protected RoutedEventArgs RaisePreviewTaskbarIconToolTipOpenEvent() + { + return RaisePreviewTaskbarIconToolTipOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTaskbarIconToolTipOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTaskbarIconToolTipOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTaskbarIconToolTipOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconContextMenuOpen (and PreviewTaskbarIconContextMenuOpen) + + /// + /// TaskbarIconContextMenuOpen Routed Event + /// + public static readonly RoutedEvent TaskbarIconContextMenuOpenEvent = EventManager.RegisterRoutedEvent("TaskbarIconContextMenuOpen", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Bubbled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler TaskbarIconContextMenuOpen + { + add { AddHandler(TaskbarIconContextMenuOpenEvent, value); } + remove { RemoveHandler(TaskbarIconContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconContextMenuOpen event. + /// + protected RoutedEventArgs RaiseTaskbarIconContextMenuOpenEvent() + { + return RaiseTaskbarIconContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTaskbarIconContextMenuOpen Routed Event + /// + public static readonly RoutedEvent PreviewTaskbarIconContextMenuOpenEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconContextMenuOpen", + RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Tunneled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler PreviewTaskbarIconContextMenuOpen + { + add { AddHandler(PreviewTaskbarIconContextMenuOpenEvent, value); } + remove { RemoveHandler(PreviewTaskbarIconContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTaskbarIconContextMenuOpen event. + /// + protected RoutedEventArgs RaisePreviewTaskbarIconContextMenuOpenEvent() + { + return RaisePreviewTaskbarIconContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTaskbarIconContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTaskbarIconContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTaskbarIconContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + + + //CONSTRUCTOR DECLARATIONS + + /// + /// Registers properties. + /// + static TaskbarIcon() + { + //register change listener for the Visibility property + PropertyMetadata md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); + VisibilityProperty.OverrideMetadata(typeof(TaskbarIcon), md); + + //register change listener for the ContextMenu property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); + ContextMenuProperty.OverrideMetadata(typeof (TaskbarIcon), md); + + //register change listener for the ToolTip property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ToolTipPropertyChanged)); + ToolTipProperty.OverrideMetadata(typeof(TaskbarIcon), md); + + } + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.Interop.cs b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs new file mode 100644 index 0000000..4921a97 --- /dev/null +++ b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using Hardcodet.Wpf.TaskbarNotification.Interop; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + partial class TaskbarIcon + { + /// + /// An action that is being invoked if the + /// fires. + /// + private Action delayedTimerAction; + + /// + /// A timer that is used to differentiate between single + /// and double clicks. + /// + private readonly Timer singleClickTimer; + + + #region SetVersion + + /// + /// Sets the version flag for the . + /// + private void SetVersion() + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Vista; + bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); + + if (!status) + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win2000; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + iconData.VersionOrTimeout = (uint)NotifyIconVersion.Win95; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + Debug.Fail("Could not set version"); + } + } + + #endregion + + + /// + /// Sets tooltip settings for the class. + /// + private void WriteToolTipSettings() + { + IconDataMembers flags = IconDataMembers.Tip; + iconData.ToolTipText = ToolTipText; + + if (messageSink.Version == NotifyIconVersion.Vista) + { + if (String.IsNullOrEmpty(ToolTipText) && ToolTip != null) + { + //if we have not tooltip text but a custom tooltip, we + //need to set a dummy value + iconData.ToolTipText = "ToolTip"; + } + else if (!String.IsNullOrEmpty(ToolTipText) && ToolTip == null) + { + //if a tooltip text was set but there is no custom tooltip, + //we need to fall back to legacy operations + flags |= IconDataMembers.UseLegacyToolTips; + } + } + + //just write the the tooltip + Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); + } + + + #region Show / Hide Balloon ToolTip + + /// + /// Displays a balloon tip with the specified title, + /// text, and icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// Indicates the severity. + public void ShowBalloonTip(string title, string message, BalloonIcon icon) + { + lock(this) + { + ShowBalloonTip(title, message, icon.GetBalloonFlag(), IntPtr.Zero); + } + } + + + /// + /// Displays a balloon tip with the specified title, + /// text, and a custom icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A custom icon. + /// If + /// is a null reference. + public void ShowBalloonTip(string title, string message, Icon customIcon) + { + if (customIcon == null) throw new ArgumentNullException("customIcon"); + + lock(this) + { + ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); + } + } + + + + /// + /// Invokes in order to display + /// a given balloon ToolTip. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// Indicates what icon to use. + /// A handle to a custom icon, if any, or + /// . + private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) + { + EnsureNotDisposed(); + + iconData.BalloonText = message; + iconData.BalloonTitle = title; + + iconData.BalloonFlags = flags; + iconData.CustomBalloonIconHandle = balloonIconHandle; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + } + + + + /// + /// Hides a balloon ToolTip, if any is displayed. + /// + public void HideBalloonTip() + { + EnsureNotDisposed(); + + //reset balloon by just setting the info to an empty string + iconData.BalloonText = iconData.BalloonTitle = String.Empty; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + } + + #endregion + + + #region Single Click Timer event + + /// + /// Performs a delayed action if the user requested an action + /// based on a single click of the left mouse.
+ /// This method is invoked by the . + ///
+ private void DoSingleClickAction(object state) + { + if (IsDisposed) return; + + //run action + Action action = delayedTimerAction; + if (action != null) + { + //cleanup action + delayedTimerAction = null; + + //switch to UI thread + Application.Current.Dispatcher.Invoke(action); + } + } + + #endregion + + + #region Show Tray Popup / Context Menu + + /// + /// Displays the control if + /// it was set. + /// + private void ShowTrayPopup() + { + if (IsDisposed) return; + + if (TaskbarIconPopup != null) + { + //raise preview event + var args = RaisePreviewTaskbarIconPopupOpenEvent(); + if (args.Handled) return; + + //open popup + TaskbarIconPopup.IsOpen = true; + + //activate the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); + + //bubble event + RaiseTaskbarIconPopupOpenEvent(); + } + } + + + /// + /// Displays the if + /// it was set. + /// + private void ShowContextMenu() + { + if (IsDisposed) return; + + if (ContextMenu != null) + { + //raise preview event + var args = RaisePreviewTaskbarIconContextMenuOpenEvent(); + if (args.Handled) return; + + //CreateActivationWindow(); + ContextMenu.IsOpen = true; + + //activate the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); + + //bubble event + RaiseTaskbarIconContextMenuOpenEvent(); + } + } + + #endregion + } +} diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs new file mode 100644 index 0000000..d13005a --- /dev/null +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -0,0 +1,379 @@ +using System; +using System.ComponentModel; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; +using Hardcodet.Wpf.TaskbarNotification.Interop; +using Rect=Hardcodet.Wpf.TaskbarNotification.Interop.Rect; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + internal class MyClass + { + public void Test() + { + TaskbarIcon icon = new TaskbarIcon(); + icon.Icon = Properties.Resources.DefaultTrayIcon; + Console.Out.WriteLine("DISPLAY NOW..."); + Thread.CurrentThread.Join(1500); + //icon.ShowBalloonTip("some title", "hello world", Properties.Resources.DefaultTrayIcon); + //Console.Out.WriteLine("status = {0}", status); + Thread.CurrentThread.Join(5000); + } + + public void Test2() + { + var tbInfo = TrayLocator.GetTaskbarInformation(); + var w = new Window(); + w.Background = Brushes.Red; + w.WindowStyle = WindowStyle.None; + + Rect rect = tbInfo.Rectangle; + w.Width = Math.Max(20, rect.right - rect.left); + w.Height = Math.Max(20, rect.bottom - rect.top); + w.Left = rect.left; + w.Top = rect.top - 100; + w.ShowDialog(); + } + } + + /// + /// Represent a taskbar icon that sits in the system + /// tray. + /// + public partial class TaskbarIcon : FrameworkElement, IDisposable + { + /// + /// Represents the current icon data. + /// + private NotifyIconData iconData; + + /// + /// Receives messages from the taskbar icon. + /// + private readonly WindowMessageSink messageSink; + + /// + /// Indicates whether the taskbar icon has been created or not. + /// + public bool IsTaskbarIconCreated { get; set; } + + + /// + /// Indicates whether custom tooltips are supported. + /// + public bool SupportsCustomToolTips + { + get { return messageSink.Version == NotifyIconVersion.Vista; } + } + + + /// + /// Inits the taskbar icon and registers a message listener + /// in order to receive events from the taskbar area. + /// + public TaskbarIcon() + { + //do nothing if in design mode + if (Util.IsDesignMode) + { + messageSink = WindowMessageSink.CreateEmpty(); + } + else + { + //create message sink that receives window messages + messageSink = new WindowMessageSink(NotifyIconVersion.Win95); + } + + //init icon data structure + iconData = NotifyIconData.CreateDefault(messageSink.MessageWindowHandle); + + //create the taskbar icon + CreateTaskbarIcon(); + + //register event listeners + messageSink.MouseEventReceived += OnMouseEvent; + messageSink.TaskbarCreated += OnTaskbarCreated; + messageSink.ChangeToolTipStateRequest += OnToolTipChange; + messageSink.BallonToolTipChanged += OnBalloonToolTipChanged; + + //init single click timer + singleClickTimer = new Timer(DoSingleClickAction); + + + //register listener in order to get notified when the application closes + if (Application.Current != null) Application.Current.Exit += OnExit; + + } + + + + /// + /// Processes mouse events, which are bubbled + /// through the class' routed events, trigger + /// certain actions (e.g. show a popup), or + /// both. + /// + /// Event flag. + private void OnMouseEvent(MouseEvent me) + { + if (IsDisposed) return; + + switch(me) + { + case MouseEvent.MouseMove: + break; + case MouseEvent.IconRightMouseDown: + RaiseTaskbarIconRightMouseDownEvent(); + break; + case MouseEvent.IconLeftMouseDown: + RaiseTaskbarIconLeftMouseDownEvent(); + break; + case MouseEvent.IconRightMouseUp: + RaiseTaskbarIconRightMouseUpEvent(); + break; + case MouseEvent.IconLeftMouseUp: + RaiseTaskbarIconLeftMouseUpEvent(); + break; + case MouseEvent.IconMiddleMouseDown: + break; + case MouseEvent.IconMiddleMouseUp: + break; + case MouseEvent.IconDoubleClick: + + //cancel single click timer + singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); + + break; + case MouseEvent.BalloonToolTipClicked: + break; + default: + throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); + + } + + + //show popup, if requested + if (me.IsMatch(PopupActivation)) + { + if (me == MouseEvent.IconLeftMouseUp) + { + //show popup once we are sure it's not a double click + delayedTimerAction = ShowTrayPopup; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + } + else + { + //show popup immediately + ShowTrayPopup(); + } + } + + + //show context menu, if requested + if (me.IsMatch(MenuActivation)) + { + if (me == MouseEvent.IconLeftMouseUp) + { + //show context menu once we are sure it's not a double click + delayedTimerAction = ShowContextMenu; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + } + else + { + //show context menu immediately + ShowContextMenu(); + } + } + } + + + + private void OnToolTipChange(bool visible) + { + //if we have a custom tooltip, show it now + if (ToolTip == null) return; + + ToolTip tt = (ToolTip)ToolTip; + tt.IsOpen = visible; + } + + + private void OnBalloonToolTipChanged(bool visible) + { + //TODO just raise event + } + + + + /// + /// Recreates the taskbar icon if the whole taskbar was + /// recreated (e.g. because Explorer was shut down). + /// + private void OnTaskbarCreated() + { + IsTaskbarIconCreated = false; + CreateTaskbarIcon(); + } + + + + + + + #region create / remove taskbar icon + + /// + /// Creates the taskbar icon. This message is invoked during initialization, + /// if the taskbar is restarted, and whenever the icon is displayed. + /// + private void CreateTaskbarIcon() + { + lock (this) + { + if (!IsTaskbarIconCreated) + { + const IconDataMembers members = IconDataMembers.Message + | IconDataMembers.Icon + | IconDataMembers.Tip; + + //write initial configuration + var status = Util.WriteIconData(ref iconData, NotifyCommand.Add, members); + if (!status) + { + throw new Win32Exception("Could not create icon data"); + } + + //set to most recent version + SetVersion(); + messageSink.Version = (NotifyIconVersion) iconData.VersionOrTimeout; + + IsTaskbarIconCreated = true; + } + } + } + + + /// + /// Closes the taskbar icon if required. + /// + private void RemoveTaskbarIcon() + { + lock (this) + { + if (IsTaskbarIconCreated) + { + Util.WriteIconData(ref iconData, NotifyCommand.Delete, IconDataMembers.Message); + IsTaskbarIconCreated = false; + } + } + } + + #endregion + + + #region Dispose / Exit + + /// + /// Set to true as soon as + /// has been invoked. + /// + public bool IsDisposed { get; private set; } + + + /// + /// Checks if the object has been disposed and + /// raises a in case + /// the flag is true. + /// + private void EnsureNotDisposed() + { + if (IsDisposed) throw new ObjectDisposedException(Name ?? GetType().FullName); + } + + + /// + /// Disposes the class if the application exits. + /// + private void OnExit(object sender, EventArgs e) + { + Dispose(); + } + + + /// + /// This destructor will run only if the + /// method does not get called. This gives this base class the + /// opportunity to finalize. + /// + /// Important: Do not provide destructors in types derived from + /// this class. + /// + /// + ~TaskbarIcon() + { + Dispose(false); + } + + + /// + /// Disposes the object. + /// + /// This method is not virtual by design. Derived classes + /// should override . + /// + public void Dispose() + { + Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + + /// + /// Closes the tray and releases all resources. + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// + /// If disposing equals false, the method + /// has been called by the runtime from inside the finalizer and you + /// should not reference other objects. Only unmanaged resources can + /// be disposed. + /// Check the property to determine whether + /// the method has already been called. + private void Dispose(bool disposing) + { + //don't do anything if the component is already disposed + if (IsDisposed || !disposing) return; + + lock (this) + { + IsDisposed = true; + + //deregister application event listener + Application.Current.Exit -= OnExit; + + //stop timer + singleClickTimer.Dispose(); + + //dispose message sink + messageSink.Dispose(); + + RemoveTaskbarIcon(); + } + } + + #endregion + } +} diff --git a/Source/NotifyIconWpf/Util.cs b/Source/NotifyIconWpf/Util.cs new file mode 100644 index 0000000..55e773d --- /dev/null +++ b/Source/NotifyIconWpf/Util.cs @@ -0,0 +1,225 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows; +using System.Windows.Media; +using System.Windows.Resources; +using Hardcodet.Wpf.TaskbarNotification.Interop; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Util and extension methods. + /// + internal static class Util + { + public static readonly object SyncRoot = new object(); + + + #region IsDesignMode + + private static readonly bool isDesignMode; + + /// + /// Checks whether the application is currently in design mode. + /// + public static bool IsDesignMode + { + get { return isDesignMode; } + } + + #endregion + + + #region construction + + static Util() + { + isDesignMode = + (bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement)) + .Metadata.DefaultValue; + } + + #endregion + + + #region CreateHelperWindow + + /// + /// Creates an transparent window without dimension that + /// can be used to temporarily obtain focus and/or + /// be used as a window message sink. + /// + /// Empty window. + public static Window CreateHelperWindow() + { + return new Window + { + Width = 0, + Height = 0, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None, + AllowsTransparency = true, + Opacity = 0 + }; + } + + #endregion + + + #region WriteIconData + + /// + /// Updates the taskbar icons with data provided by a given + /// instance. + /// + /// + /// + /// + public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command) + { + return WriteIconData(ref data, command, data.ValidMembers); + } + + + /// + /// Updates the taskbar icons with data provided by a given + /// instance. + /// + /// + /// + /// + /// + public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command, IconDataMembers flags) + { + //do nothing if in design mode + if (IsDesignMode) return true; + + data.ValidMembers = flags; + lock (SyncRoot) + { + return WinApi.Shell_NotifyIcon(command, ref data); + } + } + + #endregion + + + #region GetBalloonFlag + + /// + /// Gets a enum value that + /// matches a given . + /// + public static BalloonFlags GetBalloonFlag(this BalloonIcon icon) + { + switch (icon) + { + case BalloonIcon.None: + return BalloonFlags.None; + case BalloonIcon.Info: + return BalloonFlags.Info; + case BalloonIcon.Warning: + return BalloonFlags.Warning; + case BalloonIcon.Error: + return BalloonFlags.Error; + default: + throw new ArgumentOutOfRangeException("icon"); + } + } + + #endregion + + + #region ImageSource to Icon + + /// + /// Reads a given image resource into a WinForms icon. + /// + /// Image source pointing to + /// an icon file (*.ico). + /// An icon object that can be used with the + /// taskbar area. + public static Icon ToIcon(this ImageSource imageSource) + { + if (imageSource == null) return null; + + Uri uri = new Uri(imageSource.ToString()); + StreamResourceInfo streamInfo = Application.GetResourceStream(uri); + + if (streamInfo == null) + { + string msg = "The supplied image source '{0}' could not be resolved."; + msg = String.Format(msg, imageSource); + throw new ArgumentException(msg); + } + + return new Icon(streamInfo.Stream); + } + + #endregion + + + #region evaluate listings + + /// + /// Checks a list of candidates for equality to a given + /// reference value. + /// + /// + /// The evaluated value. + /// A liste of possible values that are + /// regarded valid. + /// True if one of the submitted + /// matches the evaluated value. If the + /// parameter itself is null, too, the method returns false as well, + /// which allows to check with null values, too. + /// If + /// is a null reference. + public static bool Is(this T value, params T[] candidates) + { + if (candidates == null) return false; + + foreach (var t in candidates) + { + if (value.Equals(t)) return true; + } + + return false; + } + + #endregion + + + #region match MouseEvent to PopupActivation + + /// + /// Checks if a given is a match for + /// an effectively pressed mouse button. + /// + public static bool IsMatch(this MouseEvent me, PopupActivationMode activationMode) + { + switch (activationMode) + { + case PopupActivationMode.LeftClick: + return me == MouseEvent.IconLeftMouseUp; + case PopupActivationMode.RightClick: + return me == MouseEvent.IconRightMouseUp; + case PopupActivationMode.LeftOrRightClick: + return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconRightMouseUp); + case PopupActivationMode.LeftOrDoubleClick: + return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconDoubleClick); + case PopupActivationMode.DoubleClick: + return me.Is(MouseEvent.IconDoubleClick); + case PopupActivationMode.MiddleClick: + return me == MouseEvent.IconMiddleMouseUp; + case PopupActivationMode.All: + return true; + default: + throw new ArgumentOutOfRangeException("activationMode"); + } + } + + #endregion + } +} diff --git a/Source/Sample Project/App.xaml b/Source/Sample Project/App.xaml new file mode 100644 index 0000000..0c9c882 --- /dev/null +++ b/Source/Sample Project/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Source/Sample Project/App.xaml.cs b/Source/Sample Project/App.xaml.cs new file mode 100644 index 0000000..92b661a --- /dev/null +++ b/Source/Sample Project/App.xaml.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace Sample_Project +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Source/Sample Project/Icons/Bulb.ico b/Source/Sample Project/Icons/Bulb.ico new file mode 100644 index 0000000000000000000000000000000000000000..e3ff3c4bf60174f7cc6140efc302f7098ae911fc GIT binary patch literal 1150 zcmZQzU<5(|0R|wcz>vYhz#zuJz@P!dKp~(AL>x$w1a$TERC983*Voq8Zn3qs)g?tU zCpWjSlZ)G?#N^cfwRLs>laiAU35$rx5o-pYfPk)xhv)0k%Ig0cHg5Xg)7$q!R7}j2 zSpDJ>68b^GA#ZbX^8PnBH~*hJY0@V(H8o3O^;;S1>%>QePs>V8Sec)dvZ^pUW4fc2 znK7~Y&jq(p@p5TifL-HtaeCEjKBj2Twl4W)iS958p* z46CxdEXNo>cYZ=<#0UErw>LGotX#I#a^duT&$WwZ2XEiJ(QVq~NluyZk%rz@hK#t( z2z9p?%TG)6S+aPs?T&3*y|!&!nYefRy4>SO4khi_zRk0$q|iAw$XgVb{wP0p^M=}L zk2R}TyB<5VzvTGgy$weX?y5U^^l<5cy}OgQZ{3p6*WO}}O}_#s17l8docFGsJ2K|Z zo$I<~!@7(;+cq_9-?YAH|BkJ#ySHrUx^?~9!i}p}W&`zO^+Rn*e!#i2XS%0Mnc_Wt z>eRrEtCqFyShsTV)-}slZd2l!QxvW<-EUOKI-h>D{fXmd>5oym{@a#*ORO zWp7wAf9;~lJ$IXmGPflMdCKC_4-(Ib4$`g5PoH;i*Y-1y9y~bt^vRP0XO11d(o~$Y zI@;5os63G1=PEI0Qcv=sJv*lzJGgJg%7t^%!rbj8vDy2_evRV~c})C)e~se@_BDV6vwa0qS=RKell^%l6~8Z8WhHh z(?u6GI!Fm(2gs;}wiJ*Ty#;!2OK;m-DB4n)w=cAX_SV+Y7WVD$skj7%otyvjJUKc4 zb54GjVHVN1bSXpU8_fQf7-kv6FmI74MVZ+=UH=zLwr|_^cB|&r!G0rqUa!~H^!D~N z3|jc6J|kP-+1XLurqfm^|Gc()>y|HGTd2ujD%H!;X!P|^DDs{w^x%faJ0ISt{ zU6Q1=kx1m7a459=?*|y$ZCK z;yFKOVm;*wM9SYoq+%r^=khRdVKpW%y^rWs1!7g}A=i9_c-wsop}Q*`rAJ|A-9#6CPOA@cSf>#mor~n;_V1wkn?E*oeLesm{Yl zbsxpl-6EuoKOM_xO1u=6q#U-K)sXml$l3!)G<}Y7bpb|cevZL^;dZ+}u&6H~R=XLpY762G z#ItD!66#$@wh&Jpv1}_Kp1Uz&*tekHs=G$~_aM>oE!FR(+I__4Af~#1K>E&Mr2CE$ znI5o%JN@gni{&WkbebtN6UImD%K}7v*XSdHawzdCq3<~ p{NVOe#k`$tPUH7FSepL_^Qz{gg+0 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 literal 0 HcmV?d00001 diff --git a/Source/Sample Project/Properties/AssemblyInfo.cs b/Source/Sample Project/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c10547a --- /dev/null +++ b/Source/Sample Project/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Sample Project")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Sample Project")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/Sample Project/Properties/Resources.Designer.cs b/Source/Sample Project/Properties/Resources.Designer.cs new file mode 100644 index 0000000..1646b08 --- /dev/null +++ b/Source/Sample Project/Properties/Resources.Designer.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sample_Project.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sample_Project.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Icon Bulb { + get { + object obj = ResourceManager.GetObject("Bulb", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + internal static System.Drawing.Icon Computers { + get { + object obj = ResourceManager.GetObject("Computers", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + internal static System.Drawing.Icon NetDrives { + get { + object obj = ResourceManager.GetObject("NetDrives", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/Source/Sample Project/Properties/Resources.resx b/Source/Sample Project/Properties/Resources.resx new file mode 100644 index 0000000..98e1ee3 --- /dev/null +++ b/Source/Sample Project/Properties/Resources.resx @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\icons\bulb.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\computers.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\netdrives.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Source/Sample Project/Properties/Settings.Designer.cs b/Source/Sample Project/Properties/Settings.Designer.cs new file mode 100644 index 0000000..4a1169a --- /dev/null +++ b/Source/Sample Project/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sample_Project.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Source/Sample Project/Properties/Settings.settings b/Source/Sample Project/Properties/Settings.settings new file mode 100644 index 0000000..8f2fd95 --- /dev/null +++ b/Source/Sample Project/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/Sample Project/Sample Project.csproj b/Source/Sample Project/Sample Project.csproj new file mode 100644 index 0000000..6a3b392 --- /dev/null +++ b/Source/Sample Project/Sample Project.csproj @@ -0,0 +1,121 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC} + WinExe + Properties + Sample_Project + Sample Project + v3.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + Window1.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + {7AC63864-7638-41C4-969C-D3197EF2BED9} + NotifyIconWpf + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Sample Project/Window1.xaml b/Source/Sample Project/Window1.xaml new file mode 100644 index 0000000..8c449cf --- /dev/null +++ b/Source/Sample Project/Window1.xaml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Sample Project/Window1.xaml.cs b/Source/Sample Project/Window1.xaml.cs new file mode 100644 index 0000000..639bfe1 --- /dev/null +++ b/Source/Sample Project/Window1.xaml.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Sample_Project +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class Window1 : Window + { + public Window1() + { + InitializeComponent(); + + //set icon in code - setting the IconSource in XAML + //works just fine but breaks the VS designer + tb.Icon = Properties.Resources.Computers; + } + + private void OnClick(object sender, RoutedEventArgs e) + { + if (tb.Visibility == System.Windows.Visibility.Visible) + { + tb.Visibility = System.Windows.Visibility.Collapsed; + } + else + { + tb.Visibility = Visibility.Visible; + } + } + } +} From 6cc31cea5bac0712558f1d17391693fa516772bd Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Mon, 30 Mar 2009 23:00:01 +0000 Subject: [PATCH 02/73] WPF NotifyIcon -------------- ADD Completed events. FIX Suppressing second left mouse click event in case of a double click. CHG General cleanup. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@53 9f600761-6f11-4665-b6dc-0185e9171623 --- .../Interop/WindowMessageSink.Handle.cs | 11 +- .../Interop/WindowMessageSink.cs | 17 +- .../NotifyIconWpf/TaskbarIcon.Declarations.cs | 448 ++++++++++++++++-- Source/NotifyIconWpf/TaskbarIcon.Interop.cs | 55 +-- Source/NotifyIconWpf/TaskbarIcon.cs | 132 ++++-- Source/Sample Project/Window1.xaml | 4 +- 6 files changed, 520 insertions(+), 147 deletions(-) diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs index 5a4d4e9..d99dd34 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs @@ -35,13 +35,15 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// private WindowProcedureHandler messageHandler; + /// /// Creates the helper message window that is used /// to receive messages from the taskbar icon. /// private void CreateMessageWindow() { - WindowId = "WPFTaskbarIcon_" + Guid.NewGuid().ToString(); + //generate a unique ID for the window + WindowId = "WPFTaskbarIcon_" + DateTime.Now.Ticks; //register window message handler messageHandler = OnWindowMessageReceived; @@ -86,14 +88,13 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop { if (messageId == taskbarRestartMessageId) { - //recreate the icon if the taskbar was restarted - //TODO refresh icon + //recreate the icon if the taskbar was restarted (e.g. due to Win Explorer shutdown) + TaskbarCreated(); } + //forward message ProcessWindowMessage(messageId, wparam, lparam); - //handle mouse clicks... - // Pass the message to the default window procedure return WinApi.DefWindowProc(hwnd, messageId, wparam, lparam); } diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 29e2542..3e59a39 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -24,6 +24,14 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// public NotifyIconVersion Version { get; set; } + + /// + /// Used to track whether a mouse-up event is just + /// the aftermath of a double-click and therefore needs + /// to be suppressed. + /// + private bool isDoubleClick; + #endregion @@ -47,7 +55,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop public event Action BallonToolTipChanged; /// - /// Fired if the taskbar was created. Requires the taskbar + /// Fired if the taskbar was created or restarted. Requires the taskbar /// icon to be reset. /// public event Action TaskbarCreated; @@ -119,11 +127,16 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop case 0x202: Debug.WriteLine("left up"); - MouseEventReceived(MouseEvent.IconLeftMouseUp); + if (!isDoubleClick) + { + MouseEventReceived(MouseEvent.IconLeftMouseUp); + } + isDoubleClick = false; break; case 0x203: Debug.WriteLine("left click 2"); + isDoubleClick = true; MouseEventReceived(MouseEvent.IconDoubleClick); break; diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index e3a893a..21aead1 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -74,7 +74,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region ToolTip dependency property override /// @@ -119,7 +118,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region Icon property / IconSource dependency property private Icon icon; @@ -194,7 +192,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region TaskbarIconPopup dependency property /// @@ -242,12 +239,11 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Provides information about the updated property. private void OnTaskbarIconPopupPropertyChanged(DependencyPropertyChangedEventArgs e) { - Popup newValue = (Popup) e.NewValue; + //currently not needed } #endregion - #region MenuActivation dependency property /// @@ -297,19 +293,15 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Provides information about the updated property. private void OnMenuActivationPropertyChanged(DependencyPropertyChangedEventArgs e) { - PopupActivationMode newValue = (PopupActivationMode) e.NewValue; - - //TODO provide implementation - throw new NotImplementedException("Change event handler for dependency property MenuActivation not implemented."); + //currently not needed } #endregion - #region PopupActivation dependency property /// - /// Defines what mouse events trigger the . + /// Defines what mouse events trigger the . /// Default is . /// public static readonly DependencyProperty PopupActivationProperty = @@ -321,7 +313,7 @@ namespace Hardcodet.Wpf.TaskbarNotification /// /// A property wrapper for the /// dependency property:
- /// Defines what mouse events trigger the . + /// Defines what mouse events trigger the . /// Default is . ///
public PopupActivationMode PopupActivation @@ -355,15 +347,11 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Provides information about the updated property. private void OnPopupActivationPropertyChanged(DependencyPropertyChangedEventArgs e) { - PopupActivationMode newValue = (PopupActivationMode) e.NewValue; - - //TODO provide implementation - throw new NotImplementedException("Change event handler for dependency property PopupActivation not implemented."); + //currently not needed } #endregion - #region Visibility dependency property override /// @@ -405,7 +393,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region ContextMenu dependency property override /// @@ -432,8 +419,7 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Provides information about the updated property. private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) { - ContextMenu newValue = (ContextMenu) e.NewValue; - //TODO provide implementation + //currently not needed } #endregion @@ -524,6 +510,48 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + #region TaskbarIconMiddleMouseDown + + /// + /// TaskbarIconMiddleMouseDown Routed Event + /// + public static readonly RoutedEvent TaskbarIconMiddleMouseDownEvent = EventManager.RegisterRoutedEvent("TaskbarIconMiddleMouseDown", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user presses the middle mouse button. + /// + public event RoutedEventHandler TaskbarIconMiddleMouseDown + { + add { AddHandler(TaskbarIconMiddleMouseDownEvent, value); } + remove { RemoveHandler(TaskbarIconMiddleMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconMiddleMouseDown event. + /// + protected RoutedEventArgs RaiseTaskbarIconMiddleMouseDownEvent() + { + return RaiseTaskbarIconMiddleMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconMiddleMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconMiddleMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconMiddleMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconLeftMouseUp /// @@ -606,6 +634,332 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + #region TaskbarIconMiddleMouseUp + + /// + /// TaskbarIconMiddleMouseUp Routed Event + /// + public static readonly RoutedEvent TaskbarIconMiddleMouseUpEvent = EventManager.RegisterRoutedEvent("TaskbarIconMiddleMouseUp", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user releases the middle mouse button. + /// + public event RoutedEventHandler TaskbarIconMiddleMouseUp + { + add { AddHandler(TaskbarIconMiddleMouseUpEvent, value); } + remove { RemoveHandler(TaskbarIconMiddleMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconMiddleMouseUp event. + /// + protected RoutedEventArgs RaiseTaskbarIconMiddleMouseUpEvent() + { + return RaiseTaskbarIconMiddleMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconMiddleMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconMiddleMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconMiddleMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + #region TaskbarIconMouseDoubleClick + + /// + /// TaskbarIconMouseDoubleClick Routed Event + /// + public static readonly RoutedEvent TaskbarIconMouseDoubleClickEvent = EventManager.RegisterRoutedEvent("TaskbarIconMouseDoubleClick", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user double-clicks the taskbar icon. + /// + public event RoutedEventHandler TaskbarIconMouseDoubleClick + { + add { AddHandler(TaskbarIconMouseDoubleClickEvent, value); } + remove { RemoveHandler(TaskbarIconMouseDoubleClickEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconMouseDoubleClick event. + /// + protected RoutedEventArgs RaiseTaskbarIconMouseDoubleClickEvent() + { + return RaiseTaskbarIconMouseDoubleClickEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconMouseDoubleClick event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconMouseDoubleClickEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconMouseDoubleClickEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconMouseMove + + /// + /// TaskbarIconMouseMove Routed Event + /// + public static readonly RoutedEvent TaskbarIconMouseMoveEvent = EventManager.RegisterRoutedEvent("TaskbarIconMouseMove", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user moves the mouse over the taskbar icon. + /// + public event RoutedEventHandler TaskbarIconMouseMove + { + add { AddHandler(TaskbarIconMouseMoveEvent, value); } + remove { RemoveHandler(TaskbarIconMouseMoveEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconMouseMove event. + /// + protected RoutedEventArgs RaiseTaskbarIconMouseMoveEvent() + { + return RaiseTaskbarIconMouseMoveEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconMouseMove event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconMouseMoveEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconMouseMoveEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + #region TaskbarIconBalloonTipShown + + /// + /// TaskbarIconBalloonTipShown Routed Event + /// + public static readonly RoutedEvent TaskbarIconBalloonTipShownEvent = EventManager.RegisterRoutedEvent("TaskbarIconBalloonTipShown", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when a balloon ToolTip is displayed. + /// + public event RoutedEventHandler TaskbarIconBalloonTipShown + { + add { AddHandler(TaskbarIconBalloonTipShownEvent, value); } + remove { RemoveHandler(TaskbarIconBalloonTipShownEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconBalloonTipShown event. + /// + protected RoutedEventArgs RaiseTaskbarIconBalloonTipShownEvent() + { + return RaiseTaskbarIconBalloonTipShownEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconBalloonTipShown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconBalloonTipShownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconBalloonTipShownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconBalloonTipClosed + + /// + /// TaskbarIconBalloonTipClosed Routed Event + /// + public static readonly RoutedEvent TaskbarIconBalloonTipClosedEvent = EventManager.RegisterRoutedEvent("TaskbarIconBalloonTipClosed", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when a balloon ToolTip was closed. + /// + public event RoutedEventHandler TaskbarIconBalloonTipClosed + { + add { AddHandler(TaskbarIconBalloonTipClosedEvent, value); } + remove { RemoveHandler(TaskbarIconBalloonTipClosedEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconBalloonTipClosed event. + /// + protected RoutedEventArgs RaiseTaskbarIconBalloonTipClosedEvent() + { + return RaiseTaskbarIconBalloonTipClosedEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconBalloonTipClosed event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconBalloonTipClosedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconBalloonTipClosedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconBalloonTipClicked + + /// + /// TaskbarIconBalloonTipClicked Routed Event + /// + public static readonly RoutedEvent TaskbarIconBalloonTipClickedEvent = EventManager.RegisterRoutedEvent("TaskbarIconBalloonTipClicked", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user clicks on a balloon ToolTip. + /// + public event RoutedEventHandler TaskbarIconBalloonTipClicked + { + add { AddHandler(TaskbarIconBalloonTipClickedEvent, value); } + remove { RemoveHandler(TaskbarIconBalloonTipClickedEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconBalloonTipClicked event. + /// + protected RoutedEventArgs RaiseTaskbarIconBalloonTipClickedEvent() + { + return RaiseTaskbarIconBalloonTipClickedEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconBalloonTipClicked event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconBalloonTipClickedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconBalloonTipClickedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + #region TaskbarIconContextMenuOpen (and PreviewTaskbarIconContextMenuOpen) + + /// + /// TaskbarIconContextMenuOpen Routed Event + /// + public static readonly RoutedEvent TaskbarIconContextMenuOpenEvent = EventManager.RegisterRoutedEvent("TaskbarIconContextMenuOpen", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Bubbled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler TaskbarIconContextMenuOpen + { + add { AddHandler(TaskbarIconContextMenuOpenEvent, value); } + remove { RemoveHandler(TaskbarIconContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconContextMenuOpen event. + /// + protected RoutedEventArgs RaiseTaskbarIconContextMenuOpenEvent() + { + return RaiseTaskbarIconContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTaskbarIconContextMenuOpen Routed Event + /// + public static readonly RoutedEvent PreviewTaskbarIconContextMenuOpenEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconContextMenuOpen", + RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Tunneled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler PreviewTaskbarIconContextMenuOpen + { + add { AddHandler(PreviewTaskbarIconContextMenuOpenEvent, value); } + remove { RemoveHandler(PreviewTaskbarIconContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTaskbarIconContextMenuOpen event. + /// + protected RoutedEventArgs RaisePreviewTaskbarIconContextMenuOpenEvent() + { + return RaisePreviewTaskbarIconContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTaskbarIconContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTaskbarIconContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTaskbarIconContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion #region TaskbarIconPopupOpen (and PreviewTaskbarIconPopupOpen) @@ -685,6 +1039,7 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + #region TaskbarIconToolTipOpen (and PreviewTaskbarIconToolTipOpen) /// @@ -763,88 +1118,87 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region TaskbarIconContextMenuOpen (and PreviewTaskbarIconContextMenuOpen) + #region TaskbarIconToolTipClose (and PreviewTaskbarIconToolTipClose) /// - /// TaskbarIconContextMenuOpen Routed Event + /// TaskbarIconToolTipClose Routed Event /// - public static readonly RoutedEvent TaskbarIconContextMenuOpenEvent = EventManager.RegisterRoutedEvent("TaskbarIconContextMenuOpen", + public static readonly RoutedEvent TaskbarIconToolTipCloseEvent = EventManager.RegisterRoutedEvent("TaskbarIconToolTipClose", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); /// - /// Bubbled event that occurs when the context menu of the taskbar icon is being displayed. + /// Bubbled event that occurs when a custom tooltip is being closed. /// - public event RoutedEventHandler TaskbarIconContextMenuOpen + public event RoutedEventHandler TaskbarIconToolTipClose { - add { AddHandler(TaskbarIconContextMenuOpenEvent, value); } - remove { RemoveHandler(TaskbarIconContextMenuOpenEvent, value); } + add { AddHandler(TaskbarIconToolTipCloseEvent, value); } + remove { RemoveHandler(TaskbarIconToolTipCloseEvent, value); } } /// - /// A helper method to raise the TaskbarIconContextMenuOpen event. + /// A helper method to raise the TaskbarIconToolTipClose event. /// - protected RoutedEventArgs RaiseTaskbarIconContextMenuOpenEvent() + protected RoutedEventArgs RaiseTaskbarIconToolTipCloseEvent() { - return RaiseTaskbarIconContextMenuOpenEvent(this); + return RaiseTaskbarIconToolTipCloseEvent(this); } /// - /// A static helper method to raise the TaskbarIconContextMenuOpen event on a target element. + /// A static helper method to raise the TaskbarIconToolTipClose event on a target element. /// /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTaskbarIconContextMenuOpenEvent(DependencyObject target) + internal static RoutedEventArgs RaiseTaskbarIconToolTipCloseEvent(DependencyObject target) { if (target == null) return null; RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TaskbarIconContextMenuOpenEvent; + args.RoutedEvent = TaskbarIconToolTipCloseEvent; RoutedEventHelper.RaiseEvent(target, args); return args; } /// - /// PreviewTaskbarIconContextMenuOpen Routed Event + /// PreviewTaskbarIconToolTipClose Routed Event /// - public static readonly RoutedEvent PreviewTaskbarIconContextMenuOpenEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconContextMenuOpen", + public static readonly RoutedEvent PreviewTaskbarIconToolTipCloseEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconToolTipClose", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); /// - /// Tunneled event that occurs when the context menu of the taskbar icon is being displayed. + /// Tunneled event that occurs when a custom tooltip is being closed. /// - public event RoutedEventHandler PreviewTaskbarIconContextMenuOpen + public event RoutedEventHandler PreviewTaskbarIconToolTipClose { - add { AddHandler(PreviewTaskbarIconContextMenuOpenEvent, value); } - remove { RemoveHandler(PreviewTaskbarIconContextMenuOpenEvent, value); } + add { AddHandler(PreviewTaskbarIconToolTipCloseEvent, value); } + remove { RemoveHandler(PreviewTaskbarIconToolTipCloseEvent, value); } } /// - /// A helper method to raise the PreviewTaskbarIconContextMenuOpen event. + /// A helper method to raise the PreviewTaskbarIconToolTipClose event. /// - protected RoutedEventArgs RaisePreviewTaskbarIconContextMenuOpenEvent() + protected RoutedEventArgs RaisePreviewTaskbarIconToolTipCloseEvent() { - return RaisePreviewTaskbarIconContextMenuOpenEvent(this); + return RaisePreviewTaskbarIconToolTipCloseEvent(this); } /// - /// A static helper method to raise the PreviewTaskbarIconContextMenuOpen event on a target element. + /// A static helper method to raise the PreviewTaskbarIconToolTipClose event on a target element. /// /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTaskbarIconContextMenuOpenEvent(DependencyObject target) + internal static RoutedEventArgs RaisePreviewTaskbarIconToolTipCloseEvent(DependencyObject target) { if (target == null) return null; RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTaskbarIconContextMenuOpenEvent; + args.RoutedEvent = PreviewTaskbarIconToolTipCloseEvent; RoutedEventHelper.RaiseEvent(target, args); return args; } #endregion - - //CONSTRUCTOR DECLARATIONS + //BASE CLASS PROPERTY OVERRIDES /// /// Registers properties. diff --git a/Source/NotifyIconWpf/TaskbarIcon.Interop.cs b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs index 4921a97..43ef54d 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Interop.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs @@ -1,13 +1,9 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Drawing; -using System.Linq; -using System.Text; using System.Threading; using System.Windows; using System.Windows.Controls; -using System.Windows.Controls.Primitives; using Hardcodet.Wpf.TaskbarNotification.Interop; namespace Hardcodet.Wpf.TaskbarNotification @@ -27,39 +23,11 @@ namespace Hardcodet.Wpf.TaskbarNotification private readonly Timer singleClickTimer; - #region SetVersion + #region Update ToolTip Settings /// - /// Sets the version flag for the . - /// - private void SetVersion() - { - iconData.VersionOrTimeout = (uint) NotifyIconVersion.Vista; - bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); - - if (!status) - { - iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win2000; - status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); - } - - if (!status) - { - iconData.VersionOrTimeout = (uint)NotifyIconVersion.Win95; - status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); - } - - if (!status) - { - Debug.Fail("Could not set version"); - } - } - - #endregion - - - /// - /// Sets tooltip settings for the class. + /// Sets tooltip settings for the class depending on defined + /// dependency properties and OS support. /// private void WriteToolTipSettings() { @@ -86,6 +54,7 @@ namespace Hardcodet.Wpf.TaskbarNotification Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); } + #endregion #region Show / Hide Balloon ToolTip @@ -98,7 +67,7 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Indicates the severity. public void ShowBalloonTip(string title, string message, BalloonIcon icon) { - lock(this) + lock (this) { ShowBalloonTip(title, message, icon.GetBalloonFlag(), IntPtr.Zero); } @@ -118,14 +87,13 @@ namespace Hardcodet.Wpf.TaskbarNotification { if (customIcon == null) throw new ArgumentNullException("customIcon"); - lock(this) + lock (this) { ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); } } - /// /// Invokes in order to display /// a given balloon ToolTip. @@ -148,7 +116,6 @@ namespace Hardcodet.Wpf.TaskbarNotification } - /// /// Hides a balloon ToolTip, if any is displayed. /// @@ -163,7 +130,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region Single Click Timer event /// @@ -175,6 +141,8 @@ namespace Hardcodet.Wpf.TaskbarNotification { if (IsDisposed) return; + Console.Out.WriteLine("TIMER EVENT"); + //run action Action action = delayedTimerAction; if (action != null) @@ -189,7 +157,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region Show Tray Popup / Context Menu /// @@ -232,10 +199,10 @@ namespace Hardcodet.Wpf.TaskbarNotification //raise preview event var args = RaisePreviewTaskbarIconContextMenuOpenEvent(); if (args.Handled) return; - + //CreateActivationWindow(); ContextMenu.IsOpen = true; - + //activate the message window to track deactivation - otherwise, the context menu //does not close if the user clicks somewhere else WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); @@ -247,4 +214,4 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion } -} +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index d13005a..b8b711d 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -1,47 +1,18 @@ using System; using System.ComponentModel; +using System.Diagnostics; using System.Threading; using System.Windows; using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Media; using Hardcodet.Wpf.TaskbarNotification.Interop; -using Rect=Hardcodet.Wpf.TaskbarNotification.Interop.Rect; + + namespace Hardcodet.Wpf.TaskbarNotification { - internal class MyClass - { - public void Test() - { - TaskbarIcon icon = new TaskbarIcon(); - icon.Icon = Properties.Resources.DefaultTrayIcon; - Console.Out.WriteLine("DISPLAY NOW..."); - Thread.CurrentThread.Join(1500); - //icon.ShowBalloonTip("some title", "hello world", Properties.Resources.DefaultTrayIcon); - //Console.Out.WriteLine("status = {0}", status); - Thread.CurrentThread.Join(5000); - } - - public void Test2() - { - var tbInfo = TrayLocator.GetTaskbarInformation(); - var w = new Window(); - w.Background = Brushes.Red; - w.WindowStyle = WindowStyle.None; - - Rect rect = tbInfo.Rectangle; - w.Width = Math.Max(20, rect.right - rect.left); - w.Height = Math.Max(20, rect.bottom - rect.top); - w.Left = rect.left; - w.Top = rect.top - 100; - w.ShowDialog(); - } - } - /// - /// Represent a taskbar icon that sits in the system - /// tray. + /// A WPF proxy to for a taskbar icon (NotifyIcon) that sits in the system's + /// taskbar notification area ("system tray"). /// public partial class TaskbarIcon : FrameworkElement, IDisposable { @@ -62,7 +33,9 @@ namespace Hardcodet.Wpf.TaskbarNotification /// - /// Indicates whether custom tooltips are supported. + /// Indicates whether custom tooltips are supported, which depends + /// on the OS. Windows Vista or higher is required in order to + /// support this feature. /// public bool SupportsCustomToolTips { @@ -102,10 +75,8 @@ namespace Hardcodet.Wpf.TaskbarNotification //init single click timer singleClickTimer = new Timer(DoSingleClickAction); - //register listener in order to get notified when the application closes if (Application.Current != null) Application.Current.Exit += OnExit; - } @@ -124,6 +95,7 @@ namespace Hardcodet.Wpf.TaskbarNotification switch(me) { case MouseEvent.MouseMove: + RaiseTaskbarIconMouseMoveEvent(); break; case MouseEvent.IconRightMouseDown: RaiseTaskbarIconRightMouseDownEvent(); @@ -138,16 +110,19 @@ namespace Hardcodet.Wpf.TaskbarNotification RaiseTaskbarIconLeftMouseUpEvent(); break; case MouseEvent.IconMiddleMouseDown: + RaiseTaskbarIconMiddleMouseDownEvent(); break; case MouseEvent.IconMiddleMouseUp: + RaiseTaskbarIconMiddleMouseUpEvent(); break; case MouseEvent.IconDoubleClick: - //cancel single click timer singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); - + //bubble event + RaiseTaskbarIconMouseDoubleClickEvent(); break; case MouseEvent.BalloonToolTipClicked: + RaiseTaskbarIconBalloonTipClickedEvent(); break; default: throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); @@ -191,23 +166,92 @@ namespace Hardcodet.Wpf.TaskbarNotification + /// + /// Displays a custom tooltip, if available. This functionality + /// is only available for Windows Vista and above. + /// + /// Whether to show or hide the tooltip. private void OnToolTipChange(bool visible) { //if we have a custom tooltip, show it now if (ToolTip == null) return; + ToolTip tt = (ToolTip)ToolTip; - tt.IsOpen = visible; + + if (visible) + { + var args = RaisePreviewTaskbarIconToolTipOpenEvent(); + if (args.Handled) return; + + tt.IsOpen = true; + RaiseTaskbarIconToolTipOpenEvent(); + } + else + { + var args = RaisePreviewTaskbarIconToolTipCloseEvent(); + if (args.Handled) return; + + tt.IsOpen = false; + RaiseTaskbarIconToolTipCloseEvent(); + } } + /// + /// Bubbles events if a balloon ToolTip was displayed + /// or removed. + /// + /// Whether the ToolTip was just displayed + /// or removed. private void OnBalloonToolTipChanged(bool visible) { - //TODO just raise event + if (visible) + { + RaiseTaskbarIconBalloonTipShownEvent(); + } + else + { + RaiseTaskbarIconBalloonTipClosedEvent(); + } } + + #region SetVersion + + /// + /// Sets the version flag for the . + /// + private void SetVersion() + { + iconData.VersionOrTimeout = (uint)NotifyIconVersion.Vista; + bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); + + if (!status) + { + iconData.VersionOrTimeout = (uint)NotifyIconVersion.Win2000; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + iconData.VersionOrTimeout = (uint)NotifyIconVersion.Win95; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + Debug.Fail("Could not set version"); + } + } + + #endregion + + + #region Create / Remove Taskbar Icon + /// /// Recreates the taskbar icon if the whole taskbar was /// recreated (e.g. because Explorer was shut down). @@ -219,12 +263,6 @@ namespace Hardcodet.Wpf.TaskbarNotification } - - - - - #region create / remove taskbar icon - /// /// Creates the taskbar icon. This message is invoked during initialization, /// if the taskbar is restarted, and whenever the icon is displayed. diff --git a/Source/Sample Project/Window1.xaml b/Source/Sample Project/Window1.xaml index 8c449cf..d373d1e 100644 --- a/Source/Sample Project/Window1.xaml +++ b/Source/Sample Project/Window1.xaml @@ -68,8 +68,8 @@ Title="Window1" Height="480" Width="579"> x:Name="tb" ToolTip="{StaticResource yb}" Height="23" VerticalAlignment="Top" > - - + + Date: Mon, 30 Mar 2009 23:04:09 +0000 Subject: [PATCH 03/73] WPF NotifyIcon -------------- CHG Merged partial classes of WindowMessageSink.cs into a single file. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@54 9f600761-6f11-4665-b6dc-0185e9171623 --- .../Interop/WindowMessageSink.Handle.cs | 103 ------------------ .../Interop/WindowMessageSink.cs | 102 ++++++++++++++++- Source/NotifyIconWpf/NotifyIconWpf.csproj | 1 - 3 files changed, 96 insertions(+), 110 deletions(-) delete mode 100644 Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs deleted file mode 100644 index d99dd34..0000000 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.ComponentModel; - -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Provides low level code that is used to receive - /// window messages without having a window that - /// prevents a WPF application from shutting down - /// properly. - /// - public partial class WindowMessageSink - { - /// - /// Window class ID. - /// - private string WindowId; - - /// - /// Handle for the message window. - /// - /// The ID of the message that is being received if the - /// taskbar is (re)started. - /// - private uint taskbarRestartMessageId; - - /// - /// A delegate that processes messages of the hidden - /// native window that receives window messages. Storing - /// this reference makes sure we don't loose our reference - /// to the message window. - /// - private WindowProcedureHandler messageHandler; - - - /// - /// Creates the helper message window that is used - /// to receive messages from the taskbar icon. - /// - private void CreateMessageWindow() - { - //generate a unique ID for the window - WindowId = "WPFTaskbarIcon_" + DateTime.Now.Ticks; - - //register window message handler - messageHandler = OnWindowMessageReceived; - - // Create a simple window class which is reference through - //the messageHandler delegate - WindowClass wc; - - wc.style = 0; - wc.lpfnWndProc = messageHandler; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = IntPtr.Zero; - wc.hIcon = IntPtr.Zero; - wc.hCursor = IntPtr.Zero; - wc.hbrBackground = IntPtr.Zero; - wc.lpszMenuName = ""; - wc.lpszClassName = WindowId; - - // Register the window class - WinApi.RegisterClass(ref wc); - - // Get the message used to indicate the taskbar has been restarted - // This is used to re-add icons when the taskbar restarts - taskbarRestartMessageId = WinApi.RegisterWindowMessage("TaskbarCreated"); - - // Create the message window - MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, 0, 0, 0, 0); - - if (MessageWindowHandle == IntPtr.Zero) - { - throw new Win32Exception(); - } - } - - - - /// - /// Callback method that receives messages from the taskbar area. - /// - private long OnWindowMessageReceived(IntPtr hwnd, uint messageId, uint wparam, uint lparam) - { - if (messageId == taskbarRestartMessageId) - { - //recreate the icon if the taskbar was restarted (e.g. due to Win Explorer shutdown) - TaskbarCreated(); - } - - //forward message - ProcessWindowMessage(messageId, wparam, lparam); - - // Pass the message to the default window procedure - return WinApi.DefWindowProc(hwnd, messageId, wparam, lparam); - } - - } -} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 3e59a39..9a42b85 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Diagnostics; namespace Hardcodet.Wpf.TaskbarNotification.Interop @@ -19,11 +20,10 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop public const int CallbackMessageId = 0x400; /// - /// The version of the underlying icon. Defines how - /// incoming messages are interpreted. + /// The ID of the message that is being received if the + /// taskbar is (re)started. /// - public NotifyIconVersion Version { get; set; } - + private uint taskbarRestartMessageId; /// /// Used to track whether a mouse-up event is just @@ -32,6 +32,30 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// private bool isDoubleClick; + /// + /// A delegate that processes messages of the hidden + /// native window that receives window messages. Storing + /// this reference makes sure we don't loose our reference + /// to the message window. + /// + private WindowProcedureHandler messageHandler; + + /// + /// Window class ID. + /// + internal string WindowId { get; private set; } + + /// + /// Handle for the message window. + /// + /// The version of the underlying icon. Defines how + /// incoming messages are interpreted. + /// + public NotifyIconVersion Version { get; set; } + #endregion @@ -100,7 +124,74 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop #endregion - #region Process Window Messages + #region CreateMessageWindow + + /// + /// Creates the helper message window that is used + /// to receive messages from the taskbar icon. + /// + private void CreateMessageWindow() + { + //generate a unique ID for the window + WindowId = "WPFTaskbarIcon_" + DateTime.Now.Ticks; + + //register window message handler + messageHandler = OnWindowMessageReceived; + + // Create a simple window class which is reference through + //the messageHandler delegate + WindowClass wc; + + wc.style = 0; + wc.lpfnWndProc = messageHandler; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = IntPtr.Zero; + wc.hIcon = IntPtr.Zero; + wc.hCursor = IntPtr.Zero; + wc.hbrBackground = IntPtr.Zero; + wc.lpszMenuName = ""; + wc.lpszClassName = WindowId; + + // Register the window class + WinApi.RegisterClass(ref wc); + + // Get the message used to indicate the taskbar has been restarted + // This is used to re-add icons when the taskbar restarts + taskbarRestartMessageId = WinApi.RegisterWindowMessage("TaskbarCreated"); + + // Create the message window + MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, 0, 0, 0, 0); + + if (MessageWindowHandle == IntPtr.Zero) + { + throw new Win32Exception(); + } + } + + #endregion + + + #region Handle Window Messages + + /// + /// Callback method that receives messages from the taskbar area. + /// + private long OnWindowMessageReceived(IntPtr hwnd, uint messageId, uint wparam, uint lparam) + { + if (messageId == taskbarRestartMessageId) + { + //recreate the icon if the taskbar was restarted (e.g. due to Win Explorer shutdown) + TaskbarCreated(); + } + + //forward message + ProcessWindowMessage(messageId, wparam, lparam); + + // Pass the message to the default window procedure + return WinApi.DefWindowProc(hwnd, messageId, wparam, lparam); + } + /// /// Processes incoming system messages. @@ -206,7 +297,6 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop #endregion - #region Dispose /// diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj index a3b1416..f0afef6 100644 --- a/Source/NotifyIconWpf/NotifyIconWpf.csproj +++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -54,7 +54,6 @@ - From 354ba1ca43a492594ed5196dd89179d427c6f0a6 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Tue, 31 Mar 2009 22:20:07 +0000 Subject: [PATCH 04/73] NotifyWPF --------- CHG Lot of plumbing, some fixes CHG Work on sample project. CHG Popups and ContextMenu now store coordinates - otherwise delayed opending may happen elsewhere. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@55 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/Interop/Point.cs | 14 + Source/NotifyIconWpf/Interop/WinApi.cs | 9 +- .../Interop/WindowMessageSink.cs | 11 +- Source/NotifyIconWpf/NotifyIconWpf.csproj | 1 + .../NotifyIconWpf/TaskbarIcon.Declarations.cs | 252 ++++---- Source/NotifyIconWpf/TaskbarIcon.Interop.cs | 197 ++++++- Source/NotifyIconWpf/TaskbarIcon.cs | 63 +- Source/NotifyIconWpf/Util.cs | 3 +- Source/Sample Project/App.xaml | 6 + .../Commands/HideMainWindowCommand.cs | 39 ++ .../Commands/ShowMainWindowCommand.cs | 38 ++ .../Commands/TaskbarIconCommands.cs | 27 + Source/Sample Project/FancyPopup.xaml | 92 +++ Source/Sample Project/FancyPopup.xaml.cs | 46 ++ Source/Sample Project/FancyToolTip.xaml | 68 +++ Source/Sample Project/FancyToolTip.xaml.cs | 80 +++ Source/Sample Project/Icons/Error.ico | Bin 0 -> 1150 bytes Source/Sample Project/Icons/Inactive.ico | Bin 0 -> 1150 bytes Source/Sample Project/Images/Add.png | Bin 0 -> 502 bytes Source/Sample Project/Images/Info.png | Bin 0 -> 7030 bytes Source/Sample Project/Images/Remove.png | Bin 0 -> 237 bytes Source/Sample Project/Images/preferences.png | Bin 0 -> 7825 bytes Source/Sample Project/Sample Project.csproj | 51 +- .../Sample Project/TaskbarIconResources.xaml | 142 +++++ Source/Sample Project/Window1.xaml | 541 ++++++++++++++---- Source/Sample Project/Window1.xaml.cs | 7 +- 26 files changed, 1379 insertions(+), 308 deletions(-) create mode 100644 Source/NotifyIconWpf/Interop/Point.cs create mode 100644 Source/Sample Project/Commands/HideMainWindowCommand.cs create mode 100644 Source/Sample Project/Commands/ShowMainWindowCommand.cs create mode 100644 Source/Sample Project/Commands/TaskbarIconCommands.cs create mode 100644 Source/Sample Project/FancyPopup.xaml create mode 100644 Source/Sample Project/FancyPopup.xaml.cs create mode 100644 Source/Sample Project/FancyToolTip.xaml create mode 100644 Source/Sample Project/FancyToolTip.xaml.cs create mode 100644 Source/Sample Project/Icons/Error.ico create mode 100644 Source/Sample Project/Icons/Inactive.ico create mode 100644 Source/Sample Project/Images/Add.png create mode 100644 Source/Sample Project/Images/Info.png create mode 100644 Source/Sample Project/Images/Remove.png create mode 100644 Source/Sample Project/Images/preferences.png create mode 100644 Source/Sample Project/TaskbarIconResources.xaml diff --git a/Source/NotifyIconWpf/Interop/Point.cs b/Source/NotifyIconWpf/Interop/Point.cs new file mode 100644 index 0000000..219adcb --- /dev/null +++ b/Source/NotifyIconWpf/Interop/Point.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Win API struct providing coordinates for a single point. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Point + { + public int X; + public int Y; + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WinApi.cs b/Source/NotifyIconWpf/Interop/WinApi.cs index 7df8f20..e0d61ba 100644 --- a/Source/NotifyIconWpf/Interop/WinApi.cs +++ b/Source/NotifyIconWpf/Interop/WinApi.cs @@ -74,7 +74,14 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// consider the mouse action a double-click. [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern int GetDoubleClickTime(); - + + /// + /// Gets the screen coordinates of the current mouse position. + /// + /// + /// + [DllImport("USER32.DLL", SetLastError = true)] + public static extern bool GetCursorPos(ref Point lpPoint); } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 9a42b85..9aa2a2f 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -8,7 +8,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// Receives messages from the taskbar icon through /// window messages of an underlying helper window. /// - public partial class WindowMessageSink : IDisposable + public class WindowMessageSink : IDisposable { #region members @@ -196,10 +196,11 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// /// Processes incoming system messages. /// - /// - /// - /// - /// + /// Callback ID. + /// If the version is + /// or higher, this parameter can be used to resolve mouse coordinates. + /// Currently not in use. + /// Provides information about the event. private void ProcessWindowMessage(uint msg, uint wParam, uint lParam) { if (msg != CallbackMessageId) return; diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj index f0afef6..255b6c1 100644 --- a/Source/NotifyIconWpf/NotifyIconWpf.csproj +++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -53,6 +53,7 @@ + diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 21aead1..937bbc7 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Drawing; using System.Windows; using System.Windows.Controls; @@ -14,8 +15,107 @@ namespace Hardcodet.Wpf.TaskbarNotification /// partial class TaskbarIcon { + /// + /// Category name that is set on designer properties. + /// + public const string CategoryName = "NotifyIcon"; + + /// + /// A control that was created + /// in order to display either + /// or . + /// + internal ToolTip CustomToolTip { get; private set; } + + /// + /// A which is either the + /// control itself or a + /// that wraps it. + /// + internal Popup CustomPopup { get; private set; } + + //DEPENDENCY PROPERTIES + #region Icon property / IconSource dependency property + + private Icon icon; + + /// + /// Gets or sets the icon to be displayed. This is not a + /// dependency property - if you want to assign the property + /// through XAML, please use the + /// dependency property. + /// + [Browsable(false)] + public Icon Icon + { + get { return icon; } + set + { + icon = value; + iconData.IconHandle = value == null ? IntPtr.Zero : icon.Handle; + + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Icon); + } + } + + + /// + /// Resolves an image source and updates the property accordingly. + /// + public static readonly DependencyProperty IconSourceProperty = + DependencyProperty.Register("IconSource", + typeof(ImageSource), + typeof(TaskbarIcon), + new FrameworkPropertyMetadata(null, IconSourcePropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Resolves an image source and updates the property accordingly. + ///
+ [Category(CategoryName)] + [Description("Sets the displayed taskbar icon.")] + public ImageSource IconSource + { + get { return (ImageSource)GetValue(IconSourceProperty); } + set { SetValue(IconSourceProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon)d; + owner.OnIconSourcePropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e) + { + ImageSource newValue = (ImageSource)e.NewValue; + + //resolving the ImageSource at design time probably won't work + if (!Util.IsDesignMode) Icon = newValue.ToIcon(); + } + + #endregion + #region ToolTipText dependency property /// @@ -35,6 +135,8 @@ namespace Hardcodet.Wpf.TaskbarNotification /// A tooltip text that is being displayed if no custom /// was set or if custom tooltips are not supported. /// + [Category(CategoryName)] + [Description("Alternative to a fully blown ToolTip, which is only displayed on Vista and above.")] public string ToolTipText { get { return (string) GetValue(ToolTipTextProperty); } @@ -66,128 +168,77 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Provides information about the updated property. private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e) { - string newValue = (string) e.NewValue; - - iconData.ToolTipText = newValue ?? String.Empty; + //only recreate tooltip if we're not using a custom control + if (CustomToolTip == null || CustomToolTip.Content is string) + { + CreateCustomToolTip(); + } + WriteToolTipSettings(); } #endregion - #region ToolTip dependency property override + #region TaskbarIconToolTip dependency property /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. + /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. + /// Works only with Vista and above. Accordingly, you should make sure that + /// the property is set as well. /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void ToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnToolTipPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnToolTipPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null) - { - ToolTip tt = e.NewValue as ToolTip; - if (tt == null) - { - tt = new ToolTip(); - tt.Content = e.NewValue; - - ToolTip = tt; - return; - } - } - - WriteToolTipSettings(); - } - - #endregion - - #region Icon property / IconSource dependency property - - private Icon icon; - - /// - /// Gets or sets the icon to be displayed. This is not a - /// dependency property - if you want to assign the property - /// through XAML, please use the - /// dependency property. - /// - public Icon Icon - { - get { return icon; } - set - { - icon = value; - iconData.IconHandle = value == null ? IntPtr.Zero : icon.Handle; - - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Icon); - } - } - - - /// - /// Resolves an image source and updates the property accordingly. - /// - public static readonly DependencyProperty IconSourceProperty = - DependencyProperty.Register("IconSource", - typeof (ImageSource), + public static readonly DependencyProperty TaskbarIconToolTipProperty = + DependencyProperty.Register("TaskbarIconToolTip", + typeof (UIElement), typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null, IconSourcePropertyChanged)); + new FrameworkPropertyMetadata(null, TaskbarIconToolTipPropertyChanged)); /// - /// A property wrapper for the + /// A property wrapper for the /// dependency property:
- /// Resolves an image source and updates the property accordingly. + /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. + /// Works only with Vista and above. Accordingly, you should make sure that + /// the property is set as well. ///
- public ImageSource IconSource + [Category(CategoryName)] + [Description("Custom UI element that is displayed as a tooltip. Only on Vista and above")] + public UIElement TaskbarIconToolTip { - get { return (ImageSource) GetValue(IconSourceProperty); } - set { SetValue(IconSourceProperty, value); } + get { return (UIElement) GetValue(TaskbarIconToolTipProperty); } + set { SetValue(TaskbarIconToolTipProperty, value); } } /// /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the + /// dependency property has + /// been changed. Invokes the /// instance method of the changed instance. /// /// The currently processed owner of the property. /// Provides information about the updated property. - private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + private static void TaskbarIconToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TaskbarIcon owner = (TaskbarIcon) d; - owner.OnIconSourcePropertyChanged(e); + owner.OnTaskbarIconToolTipPropertyChanged(e); } /// - /// Handles changes of the dependency property. As + /// Handles changes of the dependency property. As /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value + /// property wrapper, updates of the property's value /// should be handled here. /// Provides information about the updated property. - private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e) + private void OnTaskbarIconToolTipPropertyChanged(DependencyPropertyChangedEventArgs e) { - ImageSource newValue = (ImageSource) e.NewValue; - Icon = newValue.ToIcon(); + //recreate tooltip control + CreateCustomToolTip(); + + //udpate tooltip settings - needed to make sure a string is set, even + //if the ToolTipText property is not set. Otherwise, the event that + //triggers tooltip display is never fired. + WriteToolTipSettings(); } #endregion @@ -195,22 +246,24 @@ namespace Hardcodet.Wpf.TaskbarNotification #region TaskbarIconPopup dependency property /// - /// A custom popup that is displayed when the taskbar icon is clicked. + /// A control that is displayed as a popup when the taskbar icon is clicked. /// public static readonly DependencyProperty TaskbarIconPopupProperty = DependencyProperty.Register("TaskbarIconPopup", - typeof (Popup), + typeof(UIElement), typeof (TaskbarIcon), new FrameworkPropertyMetadata(null, TaskbarIconPopupPropertyChanged)); /// /// A property wrapper for the /// dependency property:
- /// A custom popup that is displayed when the taskbar icon is clicked. + /// A control that is displayed as a popup when the taskbar icon is clicked. ///
- public Popup TaskbarIconPopup + [Category(CategoryName)] + [Description("Displayed as a Popup if the user clicks on the taskbar icon.")] + public UIElement TaskbarIconPopup { - get { return (Popup) GetValue(TaskbarIconPopupProperty); } + get { return (UIElement)GetValue(TaskbarIconPopupProperty); } set { SetValue(TaskbarIconPopupProperty, value); } } @@ -240,10 +293,12 @@ namespace Hardcodet.Wpf.TaskbarNotification private void OnTaskbarIconPopupPropertyChanged(DependencyPropertyChangedEventArgs e) { //currently not needed + CreatePopup(); } #endregion + #region MenuActivation dependency property /// @@ -262,6 +317,8 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Defines what mouse events display the context menu. /// Defaults to . /// + [Category(CategoryName)] + [Description("Defines what mouse events display the context menu.")] public PopupActivationMode MenuActivation { get { return (PopupActivationMode) GetValue(MenuActivationProperty); } @@ -316,6 +373,8 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Defines what mouse events trigger the . /// Default is . ///
+ [Category(CategoryName)] + [Description("Defines what mouse events display the TaskbarIconPopup.")] public PopupActivationMode PopupActivation { get { return (PopupActivationMode) GetValue(PopupActivationProperty); } @@ -352,6 +411,7 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + #region Visibility dependency property override /// @@ -439,6 +499,7 @@ namespace Hardcodet.Wpf.TaskbarNotification /// /// Occurs when the user presses the left mouse button. /// + [Category(CategoryName)] public event RoutedEventHandler TaskbarIconLeftMouseDown { add { AddHandler(TaskbarIconLeftMouseDownEvent, value); } @@ -1212,11 +1273,6 @@ namespace Hardcodet.Wpf.TaskbarNotification //register change listener for the ContextMenu property md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); ContextMenuProperty.OverrideMetadata(typeof (TaskbarIcon), md); - - //register change listener for the ToolTip property - md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ToolTipPropertyChanged)); - ToolTipProperty.OverrideMetadata(typeof(TaskbarIcon), md); - } } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.Interop.cs b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs index 43ef54d..57c07dc 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Interop.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs @@ -1,10 +1,12 @@ using System; -using System.Diagnostics; using System.Drawing; using System.Threading; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using Hardcodet.Wpf.TaskbarNotification.Interop; +using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point; + namespace Hardcodet.Wpf.TaskbarNotification { @@ -23,7 +25,94 @@ namespace Hardcodet.Wpf.TaskbarNotification private readonly Timer singleClickTimer; - #region Update ToolTip Settings + #region ToolTip + + /// + /// Displays a custom tooltip, if available. This method is only + /// invoked for Windows Vista and above. + /// + /// Whether to show or hide the tooltip. + private void OnToolTipChange(bool visible) + { + //if we don't have a tooltip, there's nothing to do here... + if (CustomToolTip == null) return; + + if (visible) + { + if (ContextMenu != null && ContextMenu.IsOpen || + CustomPopup != null && CustomPopup.IsOpen) + { + //ignore if we have an open context menu or popup + return; + } + + var args = RaisePreviewTaskbarIconToolTipOpenEvent(); + if (args.Handled) return; + + CustomToolTip.IsOpen = true; + RaiseTaskbarIconToolTipOpenEvent(); + } + else + { + var args = RaisePreviewTaskbarIconToolTipCloseEvent(); + if (args.Handled) return; + + CustomToolTip.IsOpen = false; + RaiseTaskbarIconToolTipCloseEvent(); + } + } + + /// + /// Creates a control that either + /// wraps the currently set + /// control or the string.
+ /// If itself is already + /// a instance, it will be used directly. + ///
+ /// We use a rather than + /// because there was no way to prevent a + /// popup from causing cyclic open/close commands if it was + /// placed under the mouse. ToolTip internally uses a Popup of + /// its own, but takes advance of Popup's internal + /// property which prevents this issue. + private void CreateCustomToolTip() + { + //check if the item itself is a tooltip + ToolTip tt = TaskbarIconToolTip as ToolTip; + + if (tt == null && TaskbarIconToolTip != null) + { + //create an invisible tooltip that hosts the UIElement + tt = new ToolTip(); + tt.Placement = PlacementMode.Mouse; + tt.PlacementTarget = this; + + //the tooltip (and implicitly its context) explicitly gets + //the DataContext of this instance. If there is no DataContext, + //the TaskbarIcon sets itself + tt.DataContext = DataContext ?? this; + + //make sure the tooltip is invisible + tt.HasDropShadow = false; + tt.BorderThickness = new Thickness(0); + tt.Background = System.Windows.Media.Brushes.Transparent; + + //setting the + tt.StaysOpen = true; + + tt.Content = TaskbarIconToolTip; + } + else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) + { + //create a simple tooltip for the string + tt = new ToolTip(); + tt.Content = ToolTipText; + } + + //store a reference to the used tooltip + CustomToolTip = tt; + } + /// /// Sets tooltip settings for the class depending on defined @@ -31,32 +120,28 @@ namespace Hardcodet.Wpf.TaskbarNotification /// private void WriteToolTipSettings() { - IconDataMembers flags = IconDataMembers.Tip; + const IconDataMembers flags = IconDataMembers.Tip; iconData.ToolTipText = ToolTipText; if (messageSink.Version == NotifyIconVersion.Vista) { - if (String.IsNullOrEmpty(ToolTipText) && ToolTip != null) + //we need to set a tooltip text to get tooltip events from the + //taskbar icon + if (String.IsNullOrEmpty(iconData.ToolTipText) && CustomToolTip != null) { //if we have not tooltip text but a custom tooltip, we - //need to set a dummy value + //need to set a dummy value (we're displaying the ToolTip control, not the string) iconData.ToolTipText = "ToolTip"; } - else if (!String.IsNullOrEmpty(ToolTipText) && ToolTip == null) - { - //if a tooltip text was set but there is no custom tooltip, - //we need to fall back to legacy operations - flags |= IconDataMembers.UseLegacyToolTips; - } } - //just write the the tooltip + //update the tooltip text Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); } #endregion - #region Show / Hide Balloon ToolTip + #region Show / Hide Balloon Tip /// /// Displays a balloon tip with the specified title, @@ -64,12 +149,12 @@ namespace Hardcodet.Wpf.TaskbarNotification /// /// The title to display on the balloon tip. /// The text to display on the balloon tip. - /// Indicates the severity. - public void ShowBalloonTip(string title, string message, BalloonIcon icon) + /// A symbol that indicates the severity. + public void ShowBalloonTip(string title, string message, BalloonIcon symbol) { lock (this) { - ShowBalloonTip(title, message, icon.GetBalloonFlag(), IntPtr.Zero); + ShowBalloonTip(title, message, symbol.GetBalloonFlag(), IntPtr.Zero); } } @@ -157,24 +242,78 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + #region Create Popup + + /// + /// Creates a control that either + /// wraps the currently set + /// control or the string.
+ /// If itself is already + /// a instance, it will be used directly. + ///
+ /// We use a rather than + /// because there was no way to prevent a + /// popup from causing cyclic open/close commands if it was + /// placed under the mouse. ToolTip internally uses a Popup of + /// its own, but takes advance of Popup's internal + /// property which prevents this issue. + private void CreatePopup() + { + //no popup is available + if (TaskbarIconPopup == null) return; + + //check if the item itself is a popup + Popup popup = TaskbarIconPopup as Popup; + + if (popup == null) + { + //create an invisible popup that hosts the UIElement + popup = new Popup(); + popup.AllowsTransparency = true; + popup.PopupAnimation = PopupAnimation.Fade; + + //the tooltip (and implicitly its context) explicitly gets + //the DataContext of this instance. If there is no DataContext, + //the TaskbarIcon assigns itself + popup.DataContext = DataContext ?? this; + + Popup.CreateRootPopup(popup, TaskbarIconPopup); + + popup.PlacementTarget = this; + popup.Placement = PlacementMode.AbsolutePoint; + popup.StaysOpen = false; + } + + //store a reference to the used tooltip + CustomPopup = popup; + } + + #endregion + #region Show Tray Popup / Context Menu /// /// Displays the control if /// it was set. /// - private void ShowTrayPopup() + private void ShowTrayPopup(Point cursorPosition) { if (IsDisposed) return; + //raise preview event no matter whether popup is currently set + //or not (enables client to set it on demand) + var args = RaisePreviewTaskbarIconPopupOpenEvent(); + if (args.Handled) return; + if (TaskbarIconPopup != null) { - //raise preview event - var args = RaisePreviewTaskbarIconPopupOpenEvent(); - if (args.Handled) return; + //use absolute position, but place the popup centered above the icon + CustomPopup.Placement = PlacementMode.AbsolutePoint; + CustomPopup.HorizontalOffset = cursorPosition.X; //+ TaskbarIconPopup.ActualWidth/2; + CustomPopup.VerticalOffset = cursorPosition.Y; //open popup - TaskbarIconPopup.IsOpen = true; + CustomPopup.IsOpen = true; //activate the message window to track deactivation - otherwise, the context menu //does not close if the user clicks somewhere else @@ -190,17 +329,21 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Displays the if /// it was set. ///
- private void ShowContextMenu() + private void ShowContextMenu(Point cursorPosition) { if (IsDisposed) return; + //raise preview event no matter whether context menu is currently set + //or not (enables client to set it on demand) + var args = RaisePreviewTaskbarIconContextMenuOpenEvent(); + if (args.Handled) return; + if (ContextMenu != null) { - //raise preview event - var args = RaisePreviewTaskbarIconContextMenuOpenEvent(); - if (args.Handled) return; - - //CreateActivationWindow(); + //use absolute position + ContextMenu.Placement = PlacementMode.AbsolutePoint; + ContextMenu.HorizontalOffset = cursorPosition.X; + ContextMenu.VerticalOffset = cursorPosition.Y; ContextMenu.IsOpen = true; //activate the message window to track deactivation - otherwise, the context menu diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index b8b711d..1e6bb1d 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -1,11 +1,15 @@ using System; using System.ComponentModel; using System.Diagnostics; +using System.Reflection; using System.Threading; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; using Hardcodet.Wpf.TaskbarNotification.Interop; - +using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point; namespace Hardcodet.Wpf.TaskbarNotification @@ -43,6 +47,8 @@ namespace Hardcodet.Wpf.TaskbarNotification } + #region Construction + /// /// Inits the taskbar icon and registers a message listener /// in order to receive events from the taskbar area. @@ -79,8 +85,11 @@ namespace Hardcodet.Wpf.TaskbarNotification if (Application.Current != null) Application.Current.Exit += OnExit; } + #endregion + #region Handle Mouse Events + /// /// Processes mouse events, which are bubbled /// through the class' routed events, trigger @@ -96,7 +105,8 @@ namespace Hardcodet.Wpf.TaskbarNotification { case MouseEvent.MouseMove: RaiseTaskbarIconMouseMoveEvent(); - break; + //immediately return - there's nothing left to evaluate + return; case MouseEvent.IconRightMouseDown: RaiseTaskbarIconRightMouseDownEvent(); break; @@ -130,19 +140,23 @@ namespace Hardcodet.Wpf.TaskbarNotification } + //get mouse coordinates + Point cursorPosition = new Point(); + WinApi.GetCursorPos(ref cursorPosition); + //show popup, if requested if (me.IsMatch(PopupActivation)) { if (me == MouseEvent.IconLeftMouseUp) { //show popup once we are sure it's not a double click - delayedTimerAction = ShowTrayPopup; + delayedTimerAction = () => ShowTrayPopup(cursorPosition); singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); } else { //show popup immediately - ShowTrayPopup(); + ShowTrayPopup(cursorPosition); } } @@ -153,51 +167,18 @@ namespace Hardcodet.Wpf.TaskbarNotification if (me == MouseEvent.IconLeftMouseUp) { //show context menu once we are sure it's not a double click - delayedTimerAction = ShowContextMenu; + delayedTimerAction = () => ShowContextMenu(cursorPosition); singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); } else { //show context menu immediately - ShowContextMenu(); + ShowContextMenu(cursorPosition); } } } - - /// - /// Displays a custom tooltip, if available. This functionality - /// is only available for Windows Vista and above. - /// - /// Whether to show or hide the tooltip. - private void OnToolTipChange(bool visible) - { - //if we have a custom tooltip, show it now - if (ToolTip == null) return; - - - ToolTip tt = (ToolTip)ToolTip; - - if (visible) - { - var args = RaisePreviewTaskbarIconToolTipOpenEvent(); - if (args.Handled) return; - - tt.IsOpen = true; - RaiseTaskbarIconToolTipOpenEvent(); - } - else - { - var args = RaisePreviewTaskbarIconToolTipCloseEvent(); - if (args.Handled) return; - - tt.IsOpen = false; - RaiseTaskbarIconToolTipCloseEvent(); - } - } - - /// /// Bubbles events if a balloon ToolTip was displayed /// or removed. @@ -208,7 +189,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { if (visible) { - RaiseTaskbarIconBalloonTipShownEvent(); + RaiseTaskbarIconBalloonTipShownEvent(); } else { @@ -216,7 +197,7 @@ namespace Hardcodet.Wpf.TaskbarNotification } } - + #endregion #region SetVersion diff --git a/Source/NotifyIconWpf/Util.cs b/Source/NotifyIconWpf/Util.cs index 55e773d..4b2acc4 100644 --- a/Source/NotifyIconWpf/Util.cs +++ b/Source/NotifyIconWpf/Util.cs @@ -214,7 +214,8 @@ namespace Hardcodet.Wpf.TaskbarNotification case PopupActivationMode.MiddleClick: return me == MouseEvent.IconMiddleMouseUp; case PopupActivationMode.All: - return true; + //return true for everything except mouse movements + return me != MouseEvent.MouseMove; default: throw new ArgumentOutOfRangeException("activationMode"); } diff --git a/Source/Sample Project/App.xaml b/Source/Sample Project/App.xaml index 0c9c882..04fb858 100644 --- a/Source/Sample Project/App.xaml +++ b/Source/Sample Project/App.xaml @@ -4,5 +4,11 @@ StartupUri="Window1.xaml"> + + + + + + diff --git a/Source/Sample Project/Commands/HideMainWindowCommand.cs b/Source/Sample Project/Commands/HideMainWindowCommand.cs new file mode 100644 index 0000000..c91b4b8 --- /dev/null +++ b/Source/Sample Project/Commands/HideMainWindowCommand.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Input; + +namespace Sample_Project.Commands +{ + /// + /// Hides the main window. + /// + public class HideMainWindowCommand : ICommand + { + public event EventHandler CanExecuteChanged; + + public void Execute(object parameter) + { + Application.Current.MainWindow.Hide(); + TaskbarIconCommands.RefreshCommands(); + } + + + public bool CanExecute(object parameter) + { + return Application.Current.MainWindow.IsVisible; + } + + + /// + /// Raises the event. + /// + internal void RaiseCanExcecuteChanged() + { + if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty); + } + + } +} diff --git a/Source/Sample Project/Commands/ShowMainWindowCommand.cs b/Source/Sample Project/Commands/ShowMainWindowCommand.cs new file mode 100644 index 0000000..8367ccf --- /dev/null +++ b/Source/Sample Project/Commands/ShowMainWindowCommand.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Input; + +namespace Sample_Project.Commands +{ + /// + /// Shows the main window. + /// + public class ShowMainWindowCommand : ICommand + { + public event EventHandler CanExecuteChanged; + + public void Execute(object parameter) + { + Application.Current.MainWindow.Show(); + TaskbarIconCommands.RefreshCommands(); + } + + + public bool CanExecute(object parameter) + { + return Application.Current.MainWindow.IsVisible == false; + } + + /// + /// Raises the event. + /// + internal void RaiseCanExcecuteChanged() + { + if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty); + } + + } +} diff --git a/Source/Sample Project/Commands/TaskbarIconCommands.cs b/Source/Sample Project/Commands/TaskbarIconCommands.cs new file mode 100644 index 0000000..abcd757 --- /dev/null +++ b/Source/Sample Project/Commands/TaskbarIconCommands.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Input; + +namespace Sample_Project.Commands +{ + public static class TaskbarIconCommands + { + public static HideMainWindowCommand HideMain { get; set; } + public static ShowMainWindowCommand ShowMain { get; set; } + + + static TaskbarIconCommands() + { + HideMain = new HideMainWindowCommand(); + ShowMain =new ShowMainWindowCommand(); + } + + public static void RefreshCommands() + { + HideMain.RaiseCanExcecuteChanged(); + ShowMain.RaiseCanExcecuteChanged(); + } + } +} diff --git a/Source/Sample Project/FancyPopup.xaml b/Source/Sample Project/FancyPopup.xaml new file mode 100644 index 0000000..cd1804c --- /dev/null +++ b/Source/Sample Project/FancyPopup.xaml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Sample Project/FancyPopup.xaml.cs b/Source/Sample Project/FancyPopup.xaml.cs new file mode 100644 index 0000000..7d5d028 --- /dev/null +++ b/Source/Sample Project/FancyPopup.xaml.cs @@ -0,0 +1,46 @@ +using System.Windows; +using System.Windows.Controls; + +namespace Sample_Project +{ + /// + /// Interaction logic for FancyPopup.xaml + /// + public partial class FancyPopup : UserControl + { + #region ClickCount dependency property + + /// + /// The number of clicks on the popup button. + /// + public static readonly DependencyProperty ClickCountProperty = + DependencyProperty.Register("ClickCount", + typeof (int), + typeof (FancyPopup), + new FrameworkPropertyMetadata(0)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The number of clicks on the popup button. + ///
+ public int ClickCount + { + get { return (int) GetValue(ClickCountProperty); } + set { SetValue(ClickCountProperty, value); } + } + + #endregion + + public FancyPopup() + { + InitializeComponent(); + } + + private void OnButtonClick(object sender, RoutedEventArgs e) + { + //just increment a counter - will be displayed on screen + ClickCount++; + } + } +} \ No newline at end of file diff --git a/Source/Sample Project/FancyToolTip.xaml b/Source/Sample Project/FancyToolTip.xaml new file mode 100644 index 0000000..8afe84c --- /dev/null +++ b/Source/Sample Project/FancyToolTip.xaml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Sample Project/FancyToolTip.xaml.cs b/Source/Sample Project/FancyToolTip.xaml.cs new file mode 100644 index 0000000..d3c9e2a --- /dev/null +++ b/Source/Sample Project/FancyToolTip.xaml.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Sample_Project +{ + /// + /// Interaction logic for FancyToolTip.xaml + /// + public partial class FancyToolTip + { + #region InfoText dependency property + + /// + /// The tooltip details. + /// + public static readonly DependencyProperty InfoTextProperty = + DependencyProperty.Register("InfoText", + typeof (string), + typeof (FancyToolTip), + new FrameworkPropertyMetadata("", InfoTextPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The tooltip details. + ///
+ public string InfoText + { + get { return (string) GetValue(InfoTextProperty); } + set { SetValue(InfoTextProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void InfoTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + FancyToolTip owner = (FancyToolTip) d; + owner.OnInfoTextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnInfoTextPropertyChanged(DependencyPropertyChangedEventArgs e) + { +// string newValue = (string) e.NewValue; + } + + #endregion + + + + public FancyToolTip() + { + this.InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Source/Sample Project/Icons/Error.ico b/Source/Sample Project/Icons/Error.ico new file mode 100644 index 0000000000000000000000000000000000000000..8a8bbafa87909fb28ea0375bf2347fa3d3768d26 GIT binary patch literal 1150 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 e_Z%*j3ugJkm?&CG8KkMMtA4 + 3.5 @@ -46,29 +47,63 @@ - - - + + 3.0 + + + 3.0 + + + 3.0 + + + 3.0 + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + FancyToolTip.xaml + MSBuild:Compile Designer + + Designer + MSBuild:Compile + MSBuild:Compile Designer - App.xaml Code + App.xaml - Window1.xaml Code + Window1.xaml + + + + + FancyPopup.xaml + Code @@ -79,8 +114,8 @@ True - Settings.settings True + Settings.settings ResXFileCodeGenerator @@ -107,6 +142,10 @@ + + + + diff --git a/Source/Sample Project/TaskbarIconResources.xaml b/Source/Sample Project/TaskbarIconResources.xaml new file mode 100644 index 0000000..bb31716 --- /dev/null +++ b/Source/Sample Project/TaskbarIconResources.xaml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Sample Project/Window1.xaml b/Source/Sample Project/Window1.xaml index d373d1e..f7b8f30 100644 --- a/Source/Sample Project/Window1.xaml +++ b/Source/Sample Project/Window1.xaml @@ -2,146 +2,437 @@ x:Class="Sample_Project.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:tb="http://www.hardcodet.net/taskbar" -Title="Window1" Height="480" Width="579"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:tb="http://www.hardcodet.net/taskbar" + xmlns:sys="clr-namespace:System;assembly=mscorlib" + Title="Window1" + Height="808" + Width="769" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + mc:Ignorable="d" + xmlns:local="clr-namespace:Sample_Project"> + - - - + - - - - - - - - - - - - - - - - - - - - - + Height="549" + d:IsHidden="True" + d:IsLocked="True"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
public partial class Window1 : Window { + + public Window1() { InitializeComponent(); - - //set icon in code - setting the IconSource in XAML - //works just fine but breaks the VS designer - tb.Icon = Properties.Resources.Computers; } private void OnClick(object sender, RoutedEventArgs e) From 1242596214f336895c19440407d2556cd331591a Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Wed, 1 Apr 2009 07:34:50 +0000 Subject: [PATCH 05/73] NotifyIcon WPF -------------- CHG Merged partial classes of TaskbarIcon - no only 2 files. ADD Added attached events that indicate an opened popup/tooltip ADD Added storyboards in samples that make use of attached events. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@56 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/NotifyIconWpf.csproj | 1 - .../NotifyIconWpf/TaskbarIcon.Declarations.cs | 268 ++++++++++-- Source/NotifyIconWpf/TaskbarIcon.Interop.cs | 360 ---------------- Source/NotifyIconWpf/TaskbarIcon.cs | 400 ++++++++++++++++-- Source/Sample Project/FancyPopup.xaml | 25 +- Source/Sample Project/FancyToolTip.xaml | 45 +- Source/Sample Project/FancyToolTip.xaml.cs | 32 +- Source/Sample Project/Window1.xaml | 169 +------- 8 files changed, 682 insertions(+), 618 deletions(-) delete mode 100644 Source/NotifyIconWpf/TaskbarIcon.Interop.cs diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj index 255b6c1..b78f889 100644 --- a/Source/NotifyIconWpf/NotifyIconWpf.csproj +++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -58,7 +58,6 @@ - diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 937bbc7..cc115d0 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -25,14 +25,98 @@ namespace Hardcodet.Wpf.TaskbarNotification /// in order to display either /// or . ///
- internal ToolTip CustomToolTip { get; private set; } + internal ToolTip CustomToolTip + { + get { return IconToolTipResolved; } + private set { SetIconToolTipResolved(value); } + } /// /// A which is either the /// control itself or a /// that wraps it. /// - internal Popup CustomPopup { get; private set; } + internal Popup CustomPopup + { + get { return IconPopupResolved; } + private set { SetIconPopupResolved(value); } + } + + + + //RESOLVED POPUPS CONTROLS + #region IconPopupResolved + + /// + /// IconPopupResolved Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey IconPopupResolvedPropertyKey + = DependencyProperty.RegisterReadOnly("IconPopupResolved", typeof(Popup), typeof(TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + public static readonly DependencyProperty IconPopupResolvedProperty + = IconPopupResolvedPropertyKey.DependencyProperty; + + /// + /// Gets the IconPopupResolved property. This dependency property + /// indicates .... + /// + [Category(CategoryName)] + public Popup IconPopupResolved + { + get { return (Popup)GetValue(IconPopupResolvedProperty); } + } + + /// + /// Provides a secure method for setting the IconPopupResolved property. + /// This dependency property indicates .... + /// + /// The new value for the property. + protected void SetIconPopupResolved(Popup value) + { + SetValue(IconPopupResolvedPropertyKey, value); + } + + #endregion + + #region IconToolTipResolved + + /// + /// IconToolTipResolved Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey IconToolTipResolvedPropertyKey + = DependencyProperty.RegisterReadOnly("IconToolTipResolved", typeof(ToolTip), typeof(TaskbarIcon), + new FrameworkPropertyMetadata(null )); + + public static readonly DependencyProperty IconToolTipResolvedProperty + = IconToolTipResolvedPropertyKey.DependencyProperty; + + /// + /// Gets the IconToolTipResolved property. This dependency property + /// indicates .... + /// + [Category(CategoryName)] + [Browsable(true)] + [Bindable(true)] + public ToolTip IconToolTipResolved + { + get { return (ToolTip)GetValue(IconToolTipResolvedProperty); } + } + + /// + /// Provides a secure method for setting the IconToolTipResolved property. + /// This dependency property indicates .... + /// + /// The new value for the property. + protected void SetIconToolTipResolved(ToolTip value) + { + SetValue(IconToolTipResolvedPropertyKey, value); + } + + #endregion + + + //DEPENDENCY PROPERTIES @@ -292,7 +376,7 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Provides information about the updated property. private void OnTaskbarIconPopupPropertyChanged(DependencyPropertyChangedEventArgs e) { - //currently not needed + //create a pop CreatePopup(); } @@ -453,38 +537,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region ContextMenu dependency property override - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnContextMenuPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) - { - //currently not needed - } - - #endregion - - //EVENTS @@ -1258,6 +1310,148 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + //ATTACHED EVENTS + + #region PopupOpened + + /// + /// PopupOpened Attached Routed Event + /// + public static readonly RoutedEvent PopupOpenedEvent = EventManager.RegisterRoutedEvent("PopupOpened", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Adds a handler for the PopupOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddPopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, PopupOpenedEvent, handler); + } + + /// + /// Removes a handler for the PopupOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemovePopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, PopupOpenedEvent, handler); + } + + /// + /// A static helper method to raise the PopupOpened event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePopupOpenedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PopupOpenedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + + #region ToolTipOpened + + /// + /// ToolTipOpened Attached Routed Event + /// + public static readonly RoutedEvent ToolTipOpenedEvent = EventManager.RegisterRoutedEvent("ToolTipOpened", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Adds a handler for the ToolTipOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, ToolTipOpenedEvent, handler); + } + + /// + /// Removes a handler for the ToolTipOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, ToolTipOpenedEvent, handler); + } + + /// + /// A static helper method to raise the ToolTipOpened event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseToolTipOpenedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = ToolTipOpenedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region ToolTipClose + + /// + /// ToolTipClose Attached Routed Event + /// + public static readonly RoutedEvent ToolTipCloseEvent = EventManager.RegisterRoutedEvent("ToolTipClose", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Adds a handler for the ToolTipClose attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, ToolTipCloseEvent, handler); + } + + /// + /// Removes a handler for the ToolTipClose attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, ToolTipCloseEvent, handler); + } + + /// + /// A static helper method to raise the ToolTipClose event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseToolTipCloseEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = ToolTipCloseEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + + + + + //BASE CLASS PROPERTY OVERRIDES @@ -1269,10 +1463,6 @@ namespace Hardcodet.Wpf.TaskbarNotification //register change listener for the Visibility property PropertyMetadata md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); VisibilityProperty.OverrideMetadata(typeof(TaskbarIcon), md); - - //register change listener for the ContextMenu property - md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); - ContextMenuProperty.OverrideMetadata(typeof (TaskbarIcon), md); } } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.Interop.cs b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs deleted file mode 100644 index 57c07dc..0000000 --- a/Source/NotifyIconWpf/TaskbarIcon.Interop.cs +++ /dev/null @@ -1,360 +0,0 @@ -using System; -using System.Drawing; -using System.Threading; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using Hardcodet.Wpf.TaskbarNotification.Interop; -using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point; - - -namespace Hardcodet.Wpf.TaskbarNotification -{ - partial class TaskbarIcon - { - /// - /// An action that is being invoked if the - /// fires. - /// - private Action delayedTimerAction; - - /// - /// A timer that is used to differentiate between single - /// and double clicks. - /// - private readonly Timer singleClickTimer; - - - #region ToolTip - - /// - /// Displays a custom tooltip, if available. This method is only - /// invoked for Windows Vista and above. - /// - /// Whether to show or hide the tooltip. - private void OnToolTipChange(bool visible) - { - //if we don't have a tooltip, there's nothing to do here... - if (CustomToolTip == null) return; - - if (visible) - { - if (ContextMenu != null && ContextMenu.IsOpen || - CustomPopup != null && CustomPopup.IsOpen) - { - //ignore if we have an open context menu or popup - return; - } - - var args = RaisePreviewTaskbarIconToolTipOpenEvent(); - if (args.Handled) return; - - CustomToolTip.IsOpen = true; - RaiseTaskbarIconToolTipOpenEvent(); - } - else - { - var args = RaisePreviewTaskbarIconToolTipCloseEvent(); - if (args.Handled) return; - - CustomToolTip.IsOpen = false; - RaiseTaskbarIconToolTipCloseEvent(); - } - } - - /// - /// Creates a control that either - /// wraps the currently set - /// control or the string.
- /// If itself is already - /// a instance, it will be used directly. - ///
- /// We use a rather than - /// because there was no way to prevent a - /// popup from causing cyclic open/close commands if it was - /// placed under the mouse. ToolTip internally uses a Popup of - /// its own, but takes advance of Popup's internal - /// property which prevents this issue. - private void CreateCustomToolTip() - { - //check if the item itself is a tooltip - ToolTip tt = TaskbarIconToolTip as ToolTip; - - if (tt == null && TaskbarIconToolTip != null) - { - //create an invisible tooltip that hosts the UIElement - tt = new ToolTip(); - tt.Placement = PlacementMode.Mouse; - tt.PlacementTarget = this; - - //the tooltip (and implicitly its context) explicitly gets - //the DataContext of this instance. If there is no DataContext, - //the TaskbarIcon sets itself - tt.DataContext = DataContext ?? this; - - //make sure the tooltip is invisible - tt.HasDropShadow = false; - tt.BorderThickness = new Thickness(0); - tt.Background = System.Windows.Media.Brushes.Transparent; - - //setting the - tt.StaysOpen = true; - - tt.Content = TaskbarIconToolTip; - } - else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) - { - //create a simple tooltip for the string - tt = new ToolTip(); - tt.Content = ToolTipText; - } - - //store a reference to the used tooltip - CustomToolTip = tt; - } - - - /// - /// Sets tooltip settings for the class depending on defined - /// dependency properties and OS support. - /// - private void WriteToolTipSettings() - { - const IconDataMembers flags = IconDataMembers.Tip; - iconData.ToolTipText = ToolTipText; - - if (messageSink.Version == NotifyIconVersion.Vista) - { - //we need to set a tooltip text to get tooltip events from the - //taskbar icon - if (String.IsNullOrEmpty(iconData.ToolTipText) && CustomToolTip != null) - { - //if we have not tooltip text but a custom tooltip, we - //need to set a dummy value (we're displaying the ToolTip control, not the string) - iconData.ToolTipText = "ToolTip"; - } - } - - //update the tooltip text - Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); - } - - #endregion - - #region Show / Hide Balloon Tip - - /// - /// Displays a balloon tip with the specified title, - /// text, and icon in the taskbar for the specified time period. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// A symbol that indicates the severity. - public void ShowBalloonTip(string title, string message, BalloonIcon symbol) - { - lock (this) - { - ShowBalloonTip(title, message, symbol.GetBalloonFlag(), IntPtr.Zero); - } - } - - - /// - /// Displays a balloon tip with the specified title, - /// text, and a custom icon in the taskbar for the specified time period. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// A custom icon. - /// If - /// is a null reference. - public void ShowBalloonTip(string title, string message, Icon customIcon) - { - if (customIcon == null) throw new ArgumentNullException("customIcon"); - - lock (this) - { - ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); - } - } - - - /// - /// Invokes in order to display - /// a given balloon ToolTip. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// Indicates what icon to use. - /// A handle to a custom icon, if any, or - /// . - private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) - { - EnsureNotDisposed(); - - iconData.BalloonText = message; - iconData.BalloonTitle = title; - - iconData.BalloonFlags = flags; - iconData.CustomBalloonIconHandle = balloonIconHandle; - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); - } - - - /// - /// Hides a balloon ToolTip, if any is displayed. - /// - public void HideBalloonTip() - { - EnsureNotDisposed(); - - //reset balloon by just setting the info to an empty string - iconData.BalloonText = iconData.BalloonTitle = String.Empty; - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); - } - - #endregion - - #region Single Click Timer event - - /// - /// Performs a delayed action if the user requested an action - /// based on a single click of the left mouse.
- /// This method is invoked by the . - ///
- private void DoSingleClickAction(object state) - { - if (IsDisposed) return; - - Console.Out.WriteLine("TIMER EVENT"); - - //run action - Action action = delayedTimerAction; - if (action != null) - { - //cleanup action - delayedTimerAction = null; - - //switch to UI thread - Application.Current.Dispatcher.Invoke(action); - } - } - - #endregion - - #region Create Popup - - /// - /// Creates a control that either - /// wraps the currently set - /// control or the string.
- /// If itself is already - /// a instance, it will be used directly. - ///
- /// We use a rather than - /// because there was no way to prevent a - /// popup from causing cyclic open/close commands if it was - /// placed under the mouse. ToolTip internally uses a Popup of - /// its own, but takes advance of Popup's internal - /// property which prevents this issue. - private void CreatePopup() - { - //no popup is available - if (TaskbarIconPopup == null) return; - - //check if the item itself is a popup - Popup popup = TaskbarIconPopup as Popup; - - if (popup == null) - { - //create an invisible popup that hosts the UIElement - popup = new Popup(); - popup.AllowsTransparency = true; - popup.PopupAnimation = PopupAnimation.Fade; - - //the tooltip (and implicitly its context) explicitly gets - //the DataContext of this instance. If there is no DataContext, - //the TaskbarIcon assigns itself - popup.DataContext = DataContext ?? this; - - Popup.CreateRootPopup(popup, TaskbarIconPopup); - - popup.PlacementTarget = this; - popup.Placement = PlacementMode.AbsolutePoint; - popup.StaysOpen = false; - } - - //store a reference to the used tooltip - CustomPopup = popup; - } - - #endregion - - #region Show Tray Popup / Context Menu - - /// - /// Displays the control if - /// it was set. - /// - private void ShowTrayPopup(Point cursorPosition) - { - if (IsDisposed) return; - - //raise preview event no matter whether popup is currently set - //or not (enables client to set it on demand) - var args = RaisePreviewTaskbarIconPopupOpenEvent(); - if (args.Handled) return; - - if (TaskbarIconPopup != null) - { - //use absolute position, but place the popup centered above the icon - CustomPopup.Placement = PlacementMode.AbsolutePoint; - CustomPopup.HorizontalOffset = cursorPosition.X; //+ TaskbarIconPopup.ActualWidth/2; - CustomPopup.VerticalOffset = cursorPosition.Y; - - //open popup - CustomPopup.IsOpen = true; - - //activate the message window to track deactivation - otherwise, the context menu - //does not close if the user clicks somewhere else - WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); - - //bubble event - RaiseTaskbarIconPopupOpenEvent(); - } - } - - - /// - /// Displays the if - /// it was set. - /// - private void ShowContextMenu(Point cursorPosition) - { - if (IsDisposed) return; - - //raise preview event no matter whether context menu is currently set - //or not (enables client to set it on demand) - var args = RaisePreviewTaskbarIconContextMenuOpenEvent(); - if (args.Handled) return; - - if (ContextMenu != null) - { - //use absolute position - ContextMenu.Placement = PlacementMode.AbsolutePoint; - ContextMenu.HorizontalOffset = cursorPosition.X; - ContextMenu.VerticalOffset = cursorPosition.Y; - ContextMenu.IsOpen = true; - - //activate the message window to track deactivation - otherwise, the context menu - //does not close if the user clicks somewhere else - WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); - - //bubble event - RaiseTaskbarIconContextMenuOpenEvent(); - } - } - - #endregion - } -} \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 1e6bb1d..4872628 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -1,17 +1,14 @@ using System; using System.ComponentModel; using System.Diagnostics; -using System.Reflection; +using System.Drawing; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; -using System.Windows.Input; -using System.Windows.Media; using Hardcodet.Wpf.TaskbarNotification.Interop; using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point; - namespace Hardcodet.Wpf.TaskbarNotification { /// @@ -30,11 +27,22 @@ namespace Hardcodet.Wpf.TaskbarNotification /// private readonly WindowMessageSink messageSink; + /// + /// An action that is being invoked if the + /// fires. + /// + private Action delayedTimerAction; + + /// + /// A timer that is used to differentiate between single + /// and double clicks. + /// + private readonly Timer singleClickTimer; + /// /// Indicates whether the taskbar icon has been created or not. /// - public bool IsTaskbarIconCreated { get; set; } - + public bool IsTaskbarIconCreated { get; private set; } /// /// Indicates whether custom tooltips are supported, which depends @@ -46,7 +54,6 @@ namespace Hardcodet.Wpf.TaskbarNotification get { return messageSink.Version == NotifyIconVersion.Vista; } } - #region Construction /// @@ -55,16 +62,10 @@ namespace Hardcodet.Wpf.TaskbarNotification /// public TaskbarIcon() { - //do nothing if in design mode - if (Util.IsDesignMode) - { - messageSink = WindowMessageSink.CreateEmpty(); - } - else - { - //create message sink that receives window messages - messageSink = new WindowMessageSink(NotifyIconVersion.Win95); - } + //using dummy sink in design mode + messageSink = Util.IsDesignMode + ? WindowMessageSink.CreateEmpty() + : new WindowMessageSink(NotifyIconVersion.Win95); //init icon data structure iconData = NotifyIconData.CreateDefault(messageSink.MessageWindowHandle); @@ -87,8 +88,7 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - - #region Handle Mouse Events + #region Process Incoming Mouse Events /// /// Processes mouse events, which are bubbled @@ -101,7 +101,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { if (IsDisposed) return; - switch(me) + switch (me) { case MouseEvent.MouseMove: RaiseTaskbarIconMouseMoveEvent(); @@ -136,7 +136,6 @@ namespace Hardcodet.Wpf.TaskbarNotification break; default: throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); - } @@ -178,6 +177,252 @@ namespace Hardcodet.Wpf.TaskbarNotification } } + #endregion + + #region ToolTips + + /// + /// Displays a custom tooltip, if available. This method is only + /// invoked for Windows Vista and above. + /// + /// Whether to show or hide the tooltip. + private void OnToolTipChange(bool visible) + { + //if we don't have a tooltip, there's nothing to do here... + if (CustomToolTip == null) return; + + if (visible) + { + if (ContextMenu != null && ContextMenu.IsOpen || + CustomPopup != null && CustomPopup.IsOpen) + { + //ignore if we have an open context menu or popup + return; + } + + var args = RaisePreviewTaskbarIconToolTipOpenEvent(); + if (args.Handled) return; + + CustomToolTip.IsOpen = true; + + //raise attached event first + if (TaskbarIconToolTip != null) RaiseToolTipOpenedEvent(TaskbarIconToolTip); + + //bubble routed event + RaiseTaskbarIconToolTipOpenEvent(); + } + else + { + var args = RaisePreviewTaskbarIconToolTipCloseEvent(); + if (args.Handled) return; + + //raise attached event first + if (TaskbarIconToolTip != null) RaiseToolTipCloseEvent(TaskbarIconToolTip); + + //CustomToolTip.IsOpen = false; + RaiseTaskbarIconToolTipCloseEvent(); + } + } + + + /// + /// Creates a control that either + /// wraps the currently set + /// control or the string.
+ /// If itself is already + /// a instance, it will be used directly. + ///
+ /// We use a rather than + /// because there was no way to prevent a + /// popup from causing cyclic open/close commands if it was + /// placed under the mouse. ToolTip internally uses a Popup of + /// its own, but takes advance of Popup's internal + /// property which prevents this issue. + private void CreateCustomToolTip() + { + //check if the item itself is a tooltip + ToolTip tt = TaskbarIconToolTip as ToolTip; + + if (tt == null && TaskbarIconToolTip != null) + { + //create an invisible tooltip that hosts the UIElement + tt = new ToolTip(); + tt.Placement = PlacementMode.Mouse; + tt.PlacementTarget = this; + + //the tooltip (and implicitly its context) explicitly gets + //the DataContext of this instance. If there is no DataContext, + //the TaskbarIcon sets itself + tt.DataContext = DataContext ?? this; + + //make sure the tooltip is invisible + tt.HasDropShadow = false; + tt.BorderThickness = new Thickness(0); + tt.Background = System.Windows.Media.Brushes.Transparent; + + //setting the + tt.StaysOpen = true; + + tt.Content = TaskbarIconToolTip; + } + else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) + { + //create a simple tooltip for the string + tt = new ToolTip(); + tt.Content = ToolTipText; + } + + //store a reference to the used tooltip + CustomToolTip = tt; + } + + + /// + /// Sets tooltip settings for the class depending on defined + /// dependency properties and OS support. + /// + private void WriteToolTipSettings() + { + const IconDataMembers flags = IconDataMembers.Tip; + iconData.ToolTipText = ToolTipText; + + if (messageSink.Version == NotifyIconVersion.Vista) + { + //we need to set a tooltip text to get tooltip events from the + //taskbar icon + if (String.IsNullOrEmpty(iconData.ToolTipText) && CustomToolTip != null) + { + //if we have not tooltip text but a custom tooltip, we + //need to set a dummy value (we're displaying the ToolTip control, not the string) + iconData.ToolTipText = "ToolTip"; + } + } + + //update the tooltip text + Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); + } + + #endregion + + #region Custom Popup + + /// + /// Creates a control that either + /// wraps the currently set + /// control or the string.
+ /// If itself is already + /// a instance, it will be used directly. + ///
+ /// We use a rather than + /// because there was no way to prevent a + /// popup from causing cyclic open/close commands if it was + /// placed under the mouse. ToolTip internally uses a Popup of + /// its own, but takes advance of Popup's internal + /// property which prevents this issue. + private void CreatePopup() + { + //no popup is available + if (TaskbarIconPopup == null) return; + + //check if the item itself is a popup + Popup popup = TaskbarIconPopup as Popup; + + if (popup == null) + { + //create an invisible popup that hosts the UIElement + popup = new Popup(); + popup.AllowsTransparency = true; + popup.PopupAnimation = PopupAnimation.Fade; + + //the tooltip (and implicitly its context) explicitly gets + //the DataContext of this instance. If there is no DataContext, + //the TaskbarIcon assigns itself + popup.DataContext = DataContext ?? this; + + Popup.CreateRootPopup(popup, TaskbarIconPopup); + + popup.PlacementTarget = this; + popup.Placement = PlacementMode.AbsolutePoint; + popup.StaysOpen = false; + } + + //store a reference to the used tooltip + CustomPopup = popup; + } + + /// + /// Displays the control if + /// it was set. + /// + private void ShowTrayPopup(Point cursorPosition) + { + if (IsDisposed) return; + + //raise preview event no matter whether popup is currently set + //or not (enables client to set it on demand) + var args = RaisePreviewTaskbarIconPopupOpenEvent(); + if (args.Handled) return; + + if (TaskbarIconPopup != null) + { + //use absolute position, but place the popup centered above the icon + CustomPopup.Placement = PlacementMode.AbsolutePoint; + CustomPopup.HorizontalOffset = cursorPosition.X; //+ TaskbarIconPopup.ActualWidth/2; + CustomPopup.VerticalOffset = cursorPosition.Y; + + //open popup + CustomPopup.IsOpen = true; + + //activate the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); + + //raise attached event - item should never be null unless developers + //changed the CustomPopup directly... + if (TaskbarIconPopup != null) RaisePopupOpenedEvent(TaskbarIconPopup); + + //bubble routed event + RaiseTaskbarIconPopupOpenEvent(); + } + } + + #endregion + + #region Context Menu + + /// + /// Displays the if + /// it was set. + /// + private void ShowContextMenu(Point cursorPosition) + { + if (IsDisposed) return; + + //raise preview event no matter whether context menu is currently set + //or not (enables client to set it on demand) + var args = RaisePreviewTaskbarIconContextMenuOpenEvent(); + if (args.Handled) return; + + if (ContextMenu != null) + { + //use absolute position + ContextMenu.Placement = PlacementMode.AbsolutePoint; + ContextMenu.HorizontalOffset = cursorPosition.X; + ContextMenu.VerticalOffset = cursorPosition.Y; + ContextMenu.IsOpen = true; + + //activate the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); + + //bubble event + RaiseTaskbarIconContextMenuOpenEvent(); + } + } + + #endregion + + #region Balloon Tips /// /// Bubbles events if a balloon ToolTip was displayed @@ -197,28 +442,122 @@ namespace Hardcodet.Wpf.TaskbarNotification } } + /// + /// Displays a balloon tip with the specified title, + /// text, and icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A symbol that indicates the severity. + public void ShowBalloonTip(string title, string message, BalloonIcon symbol) + { + lock (this) + { + ShowBalloonTip(title, message, symbol.GetBalloonFlag(), IntPtr.Zero); + } + } + + + /// + /// Displays a balloon tip with the specified title, + /// text, and a custom icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A custom icon. + /// If + /// is a null reference. + public void ShowBalloonTip(string title, string message, Icon customIcon) + { + if (customIcon == null) throw new ArgumentNullException("customIcon"); + + lock (this) + { + ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); + } + } + + + /// + /// Invokes in order to display + /// a given balloon ToolTip. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// Indicates what icon to use. + /// A handle to a custom icon, if any, or + /// . + private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) + { + EnsureNotDisposed(); + + iconData.BalloonText = message; + iconData.BalloonTitle = title; + + iconData.BalloonFlags = flags; + iconData.CustomBalloonIconHandle = balloonIconHandle; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + } + + + /// + /// Hides a balloon ToolTip, if any is displayed. + /// + public void HideBalloonTip() + { + EnsureNotDisposed(); + + //reset balloon by just setting the info to an empty string + iconData.BalloonText = iconData.BalloonTitle = String.Empty; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + } + #endregion + #region Single Click Timer event - #region SetVersion + /// + /// Performs a delayed action if the user requested an action + /// based on a single click of the left mouse.
+ /// This method is invoked by the . + ///
+ private void DoSingleClickAction(object state) + { + if (IsDisposed) return; + + //run action + Action action = delayedTimerAction; + if (action != null) + { + //cleanup action + delayedTimerAction = null; + + //switch to UI thread + Application.Current.Dispatcher.Invoke(action); + } + } + + #endregion + + #region Set Version (API) /// /// Sets the version flag for the . /// private void SetVersion() { - iconData.VersionOrTimeout = (uint)NotifyIconVersion.Vista; + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Vista; bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); if (!status) { - iconData.VersionOrTimeout = (uint)NotifyIconVersion.Win2000; + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win2000; status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); } if (!status) { - iconData.VersionOrTimeout = (uint)NotifyIconVersion.Win95; + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win95; status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); } @@ -230,7 +569,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region Create / Remove Taskbar Icon /// @@ -292,7 +630,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region Dispose / Exit /// @@ -311,7 +648,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { if (IsDisposed) throw new ObjectDisposedException(Name ?? GetType().FullName); } - + /// /// Disposes the class if the application exits. @@ -320,7 +657,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { Dispose(); } - + /// /// This destructor will run only if the @@ -372,7 +709,7 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Check the property to determine whether /// the method has already been called. private void Dispose(bool disposing) - { + { //don't do anything if the component is already disposed if (IsDisposed || !disposing) return; @@ -389,10 +726,11 @@ namespace Hardcodet.Wpf.TaskbarNotification //dispose message sink messageSink.Dispose(); + //remove icon RemoveTaskbarIcon(); } } #endregion } -} +} \ No newline at end of file diff --git a/Source/Sample Project/FancyPopup.xaml b/Source/Sample Project/FancyPopup.xaml index cd1804c..c6cddc8 100644 --- a/Source/Sample Project/FancyPopup.xaml +++ b/Source/Sample Project/FancyPopup.xaml @@ -2,8 +2,22 @@ x:Class="Sample_Project.FancyPopup" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:tb="http://www.hardcodet.net/taskbar" Height="215" Width="300" x:Name="me"> + + + + + + + + + + + + + + Stretch="Fill" x:Name="image" RenderTransformOrigin="0.5,0.5" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -19,7 +49,7 @@ Height="Auto" CornerRadius="6,6,6,6" BorderThickness="3,3,3,3" - Margin="0,0,5,5"> + Margin="0,0,5,5" x:Name="border"> @@ -44,7 +74,16 @@ Source="Images\Info.png" Stretch="Fill" VerticalAlignment="Top" - RenderTransformOrigin="0.792,0.486" /> + RenderTransformOrigin="0.792,0.486" x:Name="image" > + + + + + + + + + /// A property wrapper for the @@ -40,34 +41,6 @@ namespace Sample_Project set { SetValue(InfoTextProperty, value); } } - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void InfoTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FancyToolTip owner = (FancyToolTip) d; - owner.OnInfoTextPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnInfoTextPropertyChanged(DependencyPropertyChangedEventArgs e) - { -// string newValue = (string) e.NewValue; - } - #endregion @@ -76,5 +49,6 @@ namespace Sample_Project { this.InitializeComponent(); } + } } \ No newline at end of file diff --git a/Source/Sample Project/Window1.xaml b/Source/Sample Project/Window1.xaml index f7b8f30..1938cd5 100644 --- a/Source/Sample Project/Window1.xaml +++ b/Source/Sample Project/Window1.xaml @@ -25,117 +25,25 @@ TypeName="tb:PopupActivationMode" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + + + + + @@ -148,6 +56,13 @@ + + + + + + + public partial class TaskbarIcon : FrameworkElement, IDisposable { + #region Members + /// /// Represents the current icon data. /// @@ -39,6 +42,11 @@ namespace Hardcodet.Wpf.TaskbarNotification /// private readonly Timer singleClickTimer; + /// + /// A timer that is used to close open balloon tooltips. + /// + private readonly Timer balloonCloseTimer; + /// /// Indicates whether the taskbar icon has been created or not. /// @@ -54,6 +62,29 @@ namespace Hardcodet.Wpf.TaskbarNotification get { return messageSink.Version == NotifyIconVersion.Vista; } } + + + /// + /// Checks whether a non-tooltip popup is currently opened. + /// + private bool IsPopupOpen + { + get + { + var popup = TrayPopupResolved; + var menu = ContextMenu; + var balloon = CustomBalloon; + + return popup != null && popup.IsOpen || + menu != null && menu.IsOpen || + balloon != null && balloon.IsOpen; + + } + } + + #endregion + + #region Construction /// @@ -79,8 +110,9 @@ namespace Hardcodet.Wpf.TaskbarNotification messageSink.ChangeToolTipStateRequest += OnToolTipChange; messageSink.BallonToolTipChanged += OnBalloonToolTipChanged; - //init single click timer + //init single click / balloon timers singleClickTimer = new Timer(DoSingleClickAction); + balloonCloseTimer = new Timer(CloseBalloonCallback); //register listener in order to get notified when the application closes if (Application.Current != null) Application.Current.Exit += OnExit; @@ -88,6 +120,112 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + + /// + /// Shows a custom control as a tooltip in the tray location. + /// + /// + /// An optional animation for the popup. + /// The time after which the popup is being closed. + /// + /// If + /// is a null reference. + public void ShowCustomBalloon(UIElement balloon, PopupAnimation animation, int? timeout) + { + if (balloon == null) throw new ArgumentNullException("balloon"); + if (timeout.HasValue && timeout < 500) + { + string msg = "Invalid timeout of {0} milliseconds. Timeout must be at least 500 ms"; + msg = String.Format(msg, timeout); + throw new ArgumentOutOfRangeException("timeout", msg); + } + + EnsureNotDisposed(); + + //make sure we don't have an open balloon + lock (this) + { + CloseBalloon(); + } + + //create an invisible popup that hosts the UIElement + Popup popup = new Popup(); + popup.AllowsTransparency = true; + + //don't animate by default - devs can use attached + //events or override + popup.PopupAnimation = animation; + + Popup.CreateRootPopup(popup, balloon); + + popup.PlacementTarget = this; + popup.Placement = PlacementMode.AbsolutePoint; + popup.StaysOpen = true; + + Point position = TrayInfo.GetTrayLocation(); + popup.HorizontalOffset = position.X -1; + popup.VerticalOffset = position.Y -1; + + //store reference + lock (this) + { + SetCustomBalloon(popup); + } + + //fire attached event + RaiseBalloonShowingEvent(balloon); + + //display item + popup.IsOpen = true; + + if (timeout.HasValue) + { + //register timer to close the popup + balloonCloseTimer.Change(timeout.Value, Timeout.Infinite); + } + + return; + } + + + /// + /// Closes the current , if it's set. + /// + private void CloseBalloon() + { + if (IsDisposed) return; + + lock (this) + { + //reset timer in any case + balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); + + //reset old popup, if we still have one + Popup popup = CustomBalloon; + if (popup != null) + { + //if a balloon message is already displayed, close it immediately + popup.IsOpen = false; + SetCustomBalloon(null); + } + } + } + + + /// + /// Timer-invoke event which closes the currently open balloon and + /// resets the dependency property. + /// + private void CloseBalloonCallback(object state) + { + if (IsDisposed) return; + + //switch to UI thread + Action action = CloseBalloon; + Application.Current.Dispatcher.Invoke(action); + } + + #region Process Incoming Mouse Events /// @@ -104,35 +242,35 @@ namespace Hardcodet.Wpf.TaskbarNotification switch (me) { case MouseEvent.MouseMove: - RaiseTaskbarIconMouseMoveEvent(); + RaiseTrayMouseMoveEvent(); //immediately return - there's nothing left to evaluate return; case MouseEvent.IconRightMouseDown: - RaiseTaskbarIconRightMouseDownEvent(); + RaiseTrayRightMouseDownEvent(); break; case MouseEvent.IconLeftMouseDown: - RaiseTaskbarIconLeftMouseDownEvent(); + RaiseTrayLeftMouseDownEvent(); break; case MouseEvent.IconRightMouseUp: - RaiseTaskbarIconRightMouseUpEvent(); + RaiseTrayRightMouseUpEvent(); break; case MouseEvent.IconLeftMouseUp: - RaiseTaskbarIconLeftMouseUpEvent(); + RaiseTrayLeftMouseUpEvent(); break; case MouseEvent.IconMiddleMouseDown: - RaiseTaskbarIconMiddleMouseDownEvent(); + RaiseTrayMiddleMouseDownEvent(); break; case MouseEvent.IconMiddleMouseUp: - RaiseTaskbarIconMiddleMouseUpEvent(); + RaiseTrayMiddleMouseUpEvent(); break; case MouseEvent.IconDoubleClick: //cancel single click timer singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); //bubble event - RaiseTaskbarIconMouseDoubleClickEvent(); + RaiseTrayMouseDoubleClickEvent(); break; case MouseEvent.BalloonToolTipClicked: - RaiseTaskbarIconBalloonTipClickedEvent(); + RaiseTrayBalloonTipClickedEvent(); break; default: throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); @@ -189,47 +327,49 @@ namespace Hardcodet.Wpf.TaskbarNotification private void OnToolTipChange(bool visible) { //if we don't have a tooltip, there's nothing to do here... - if (CustomToolTip == null) return; + if (TrayToolTipResolved == null) return; if (visible) { if (ContextMenu != null && ContextMenu.IsOpen || - CustomPopup != null && CustomPopup.IsOpen) + TrayPopupResolved != null && TrayPopupResolved.IsOpen) { //ignore if we have an open context menu or popup return; } - var args = RaisePreviewTaskbarIconToolTipOpenEvent(); + var args = RaisePreviewTrayToolTipOpenEvent(); if (args.Handled) return; - CustomToolTip.IsOpen = true; + TrayToolTipResolved.IsOpen = true; //raise attached event first - if (TaskbarIconToolTip != null) RaiseToolTipOpenedEvent(TaskbarIconToolTip); + if (TrayToolTip != null) RaiseToolTipOpenedEvent(TrayToolTip); //bubble routed event - RaiseTaskbarIconToolTipOpenEvent(); + RaiseTrayToolTipOpenEvent(); } else { - var args = RaisePreviewTaskbarIconToolTipCloseEvent(); + var args = RaisePreviewTrayToolTipCloseEvent(); if (args.Handled) return; //raise attached event first - if (TaskbarIconToolTip != null) RaiseToolTipCloseEvent(TaskbarIconToolTip); + if (TrayToolTip != null) RaiseToolTipCloseEvent(TrayToolTip); - //CustomToolTip.IsOpen = false; - RaiseTaskbarIconToolTipCloseEvent(); + TrayToolTipResolved.IsOpen = false; + + //bubble event + RaiseTrayToolTipCloseEvent(); } } /// /// Creates a control that either - /// wraps the currently set + /// wraps the currently set /// control or the string.
- /// If itself is already + /// If itself is already /// a instance, it will be used directly. ///
/// We use a rather than @@ -241,9 +381,9 @@ namespace Hardcodet.Wpf.TaskbarNotification private void CreateCustomToolTip() { //check if the item itself is a tooltip - ToolTip tt = TaskbarIconToolTip as ToolTip; + ToolTip tt = TrayToolTip as ToolTip; - if (tt == null && TaskbarIconToolTip != null) + if (tt == null && TrayToolTip != null) { //create an invisible tooltip that hosts the UIElement tt = new ToolTip(); @@ -262,8 +402,7 @@ namespace Hardcodet.Wpf.TaskbarNotification //setting the tt.StaysOpen = true; - - tt.Content = TaskbarIconToolTip; + tt.Content = TrayToolTip; } else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) { @@ -273,7 +412,7 @@ namespace Hardcodet.Wpf.TaskbarNotification } //store a reference to the used tooltip - CustomToolTip = tt; + SetTrayToolTipResolved(tt); } @@ -290,7 +429,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { //we need to set a tooltip text to get tooltip events from the //taskbar icon - if (String.IsNullOrEmpty(iconData.ToolTipText) && CustomToolTip != null) + if (String.IsNullOrEmpty(iconData.ToolTipText) && TrayToolTipResolved != null) { //if we have not tooltip text but a custom tooltip, we //need to set a dummy value (we're displaying the ToolTip control, not the string) @@ -308,9 +447,9 @@ namespace Hardcodet.Wpf.TaskbarNotification /// /// Creates a control that either - /// wraps the currently set + /// wraps the currently set /// control or the string.
- /// If itself is already + /// If itself is already /// a instance, it will be used directly. ///
/// We use a rather than @@ -322,24 +461,27 @@ namespace Hardcodet.Wpf.TaskbarNotification private void CreatePopup() { //no popup is available - if (TaskbarIconPopup == null) return; + if (TrayPopup == null) return; //check if the item itself is a popup - Popup popup = TaskbarIconPopup as Popup; + Popup popup = TrayPopup as Popup; if (popup == null) { //create an invisible popup that hosts the UIElement popup = new Popup(); popup.AllowsTransparency = true; - popup.PopupAnimation = PopupAnimation.Fade; + + //don't animate by default - devs can use attached + //events or override + popup.PopupAnimation = PopupAnimation.None; //the tooltip (and implicitly its context) explicitly gets //the DataContext of this instance. If there is no DataContext, //the TaskbarIcon assigns itself popup.DataContext = DataContext ?? this; - Popup.CreateRootPopup(popup, TaskbarIconPopup); + Popup.CreateRootPopup(popup, TrayPopup); popup.PlacementTarget = this; popup.Placement = PlacementMode.AbsolutePoint; @@ -347,11 +489,12 @@ namespace Hardcodet.Wpf.TaskbarNotification } //store a reference to the used tooltip - CustomPopup = popup; + SetTrayPopupResolved(popup); } + /// - /// Displays the control if + /// Displays the control if /// it was set. /// private void ShowTrayPopup(Point cursorPosition) @@ -360,18 +503,18 @@ namespace Hardcodet.Wpf.TaskbarNotification //raise preview event no matter whether popup is currently set //or not (enables client to set it on demand) - var args = RaisePreviewTaskbarIconPopupOpenEvent(); + var args = RaisePreviewTrayPopupOpenEvent(); if (args.Handled) return; - if (TaskbarIconPopup != null) + if (TrayPopup != null) { //use absolute position, but place the popup centered above the icon - CustomPopup.Placement = PlacementMode.AbsolutePoint; - CustomPopup.HorizontalOffset = cursorPosition.X; //+ TaskbarIconPopup.ActualWidth/2; - CustomPopup.VerticalOffset = cursorPosition.Y; + TrayPopupResolved.Placement = PlacementMode.AbsolutePoint; + TrayPopupResolved.HorizontalOffset = cursorPosition.X; + TrayPopupResolved.VerticalOffset = cursorPosition.Y; //open popup - CustomPopup.IsOpen = true; + TrayPopupResolved.IsOpen = true; //activate the message window to track deactivation - otherwise, the context menu //does not close if the user clicks somewhere else @@ -379,10 +522,10 @@ namespace Hardcodet.Wpf.TaskbarNotification //raise attached event - item should never be null unless developers //changed the CustomPopup directly... - if (TaskbarIconPopup != null) RaisePopupOpenedEvent(TaskbarIconPopup); + if (TrayPopup != null) RaisePopupOpenedEvent(TrayPopup); //bubble routed event - RaiseTaskbarIconPopupOpenEvent(); + RaiseTrayPopupOpenEvent(); } } @@ -400,7 +543,7 @@ namespace Hardcodet.Wpf.TaskbarNotification //raise preview event no matter whether context menu is currently set //or not (enables client to set it on demand) - var args = RaisePreviewTaskbarIconContextMenuOpenEvent(); + var args = RaisePreviewTrayContextMenuOpenEvent(); if (args.Handled) return; if (ContextMenu != null) @@ -416,7 +559,7 @@ namespace Hardcodet.Wpf.TaskbarNotification WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); //bubble event - RaiseTaskbarIconContextMenuOpenEvent(); + RaiseTrayContextMenuOpenEvent(); } } @@ -434,11 +577,11 @@ namespace Hardcodet.Wpf.TaskbarNotification { if (visible) { - RaiseTaskbarIconBalloonTipShownEvent(); + RaiseTrayBalloonTipShownEvent(); } else { - RaiseTaskbarIconBalloonTipClosedEvent(); + RaiseTrayBalloonTipClosedEvent(); } } @@ -491,12 +634,12 @@ namespace Hardcodet.Wpf.TaskbarNotification { EnsureNotDisposed(); - iconData.BalloonText = message; - iconData.BalloonTitle = title; + iconData.BalloonText = message ?? String.Empty; + iconData.BalloonTitle = title ?? String.Empty; iconData.BalloonFlags = flags; iconData.CustomBalloonIconHandle = balloonIconHandle; - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info | IconDataMembers.Icon); } @@ -720,8 +863,9 @@ namespace Hardcodet.Wpf.TaskbarNotification //deregister application event listener Application.Current.Exit -= OnExit; - //stop timer + //stop timers singleClickTimer.Dispose(); + balloonCloseTimer.Dispose(); //dispose message sink messageSink.Dispose(); diff --git a/Source/Sample Project/FancyPopup.xaml b/Source/Sample Project/FancyPopup.xaml index c6cddc8..44c32ce 100644 --- a/Source/Sample Project/FancyPopup.xaml +++ b/Source/Sample Project/FancyPopup.xaml @@ -63,11 +63,11 @@
public partial class Window1 : Window { - - public Window1() { InitializeComponent(); } - private void OnClick(object sender, RoutedEventArgs e) + + /// + /// Displays a balloon tip. + /// + private void showBalloonTip_Click(object sender, RoutedEventArgs e) { - if (tb.Visibility == System.Windows.Visibility.Visible) + string title = txtBalloonTitle.Text; + string message = txtBalloonText.Text; + + if (rbCustomIcon.IsChecked == true) { - tb.Visibility = System.Windows.Visibility.Collapsed; + //just display the icon on the tray + var icon = tb.Icon; + tb.ShowBalloonTip(title, message, icon); } else { - tb.Visibility = Visibility.Visible; + BalloonIcon bi = rbInfo.IsChecked == true ? BalloonIcon.Info : BalloonIcon.Error; + tb.ShowBalloonTip(title, message, bi); } } + + private void hideBalloonTip_Click(object sender, RoutedEventArgs e) + { + tb.HideBalloonTip(); + } + + + /// + /// Resets the tooltip. + /// + private void removeToolTip_Click(object sender, RoutedEventArgs e) + { + tb.TrayToolTip = null; + } + + + + private void showCustomBalloon_Click(object sender, RoutedEventArgs e) + { + FancyBalloon balloon = new FancyBalloon(); + balloon.BalloonText = customBalloonTitle.Text; + //show and close after 2.5 seconds + tb.ShowCustomBalloon(balloon, PopupAnimation.Slide, 5000); + } } -} +} \ No newline at end of file From dc0a2167fe12ce679fc81f44b1bc0bfb825a2f3b Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Wed, 1 Apr 2009 15:06:01 +0000 Subject: [PATCH 07/73] NotifyIcon WPF -------------- FIX Removed invalid using statement. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@58 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 89162bf..9a9a454 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -8,7 +8,8 @@ using System.Windows.Controls; using System.Windows.Controls.Primitives; using Hardcodet.Wpf.TaskbarNotification.Interop; using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point; -using Rect=Hardcodet.Wpf.TaskbarNotification.Interop.Rect; + + namespace Hardcodet.Wpf.TaskbarNotification { From d792f1c5a409319e6829382621b873ec3af0fe75 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 26 Apr 2009 17:14:39 +0000 Subject: [PATCH 08/73] WPF NotifyIcon -------------- CHG Remove PlacementTarget assignment for popups and others. Did not provide advantages, but hid popups if taskbar owner isn't visible. ADD Added double click command declaration. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@83 9f600761-6f11-4665-b6dc-0185e9171623 --- .../NotifyIconWpf/TaskbarIcon.Declarations.cs | 180 +++++++++++++++++- Source/NotifyIconWpf/TaskbarIcon.cs | 24 ++- Source/Sample Project/FancyPopup.xaml | 1 + Source/Sample Project/Window1.xaml | 14 +- Source/Sample Project/Window1.xaml.cs | 7 + 5 files changed, 212 insertions(+), 14 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index bb52d1c..d817b55 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -4,6 +4,7 @@ using System.Drawing; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; +using System.Windows.Input; using System.Windows.Media; using Hardcodet.Wpf.TaskbarNotification.Interop; @@ -207,7 +208,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { ImageSource newValue = (ImageSource)e.NewValue; - //resolving the ImageSource at design time probably won't work + //resolving the ImageSource at design time is unlikely to work if (!Util.IsDesignMode) Icon = newValue.ToIcon(); } @@ -550,6 +551,169 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + #region DataContext dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnDataContextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e) + { + object newValue = e.NewValue; + object oldValue = e.OldValue; + + //replace custom data context for popup and tooltip, if + //they are reflecting the data context's data context + var popup = TrayPopupResolved; + var toolTip = TrayToolTipResolved; + + if (popup != null && Equals(popup.DataContext, oldValue)) + { + popup.DataContext = newValue; + } + + if (toolTip != null && Equals(toolTip.DataContext, oldValue)) + { + toolTip.DataContext = newValue; + } + } + + #endregion + + + #region DoubleClickCommand dependency property + + /// + /// Associates a command that is being executed if the tray icon is being + /// double clicked. + /// + public static readonly DependencyProperty DoubleClickCommandProperty = + DependencyProperty.Register("DoubleClickCommand", + typeof (ICommand), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Associates a command that is being executed if the tray icon is being + /// double clicked. + ///
+ public ICommand DoubleClickCommand + { + get { return (ICommand) GetValue(DoubleClickCommandProperty); } + set { SetValue(DoubleClickCommandProperty, value); } + } + + #endregion + + #region DoubleClickCommandParameter dependency property + + /// + /// Command parameter for the . + /// + public static readonly DependencyProperty DoubleClickCommandParameterProperty = + DependencyProperty.Register("DoubleClickCommandParameter", + typeof (object), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Command parameter for the . + ///
+ public object DoubleClickCommandParameter + { + get { return GetValue(DoubleClickCommandParameterProperty); } + set { SetValue(DoubleClickCommandParameterProperty, value); } + } + + #endregion + + #region LeftClickCommand dependency property + + /// + /// Associates a command that is being executed if the tray icon is being + /// double clicked. + /// + public static readonly DependencyProperty LeftClickCommandProperty = + DependencyProperty.Register("LeftClickCommand", + typeof (ICommand), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Associates a command that is being executed if the tray icon is being + /// double clicked. + ///
+ public ICommand LeftClickCommand + { + get { return (ICommand) GetValue(LeftClickCommandProperty); } + set { SetValue(LeftClickCommandProperty, value); } + } + + #endregion + + #region LeftClickCommandParameter dependency property + + /// + /// Command parameter for the . + /// + public static readonly DependencyProperty LeftClickCommandParameterProperty = + DependencyProperty.Register("LeftClickCommandParameter", + typeof (object), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Command parameter for the . + ///
+ public object LeftClickCommandParameter + { + get { return GetValue(LeftClickCommandParameterProperty); } + set { SetValue(LeftClickCommandParameterProperty, value); } + } + + #endregion + + /// + /// Executes a given command. + /// + /// The command to be executed. + /// An optional parameter that was associated with + /// the command. + private static void RunCommand(ICommand command, object commandParameter) + { + if (command == null) return; + if (command.CanExecute(commandParameter)) + { + command.Execute(commandParameter); + } + } + //EVENTS @@ -576,7 +740,10 @@ namespace Hardcodet.Wpf.TaskbarNotification ///
protected RoutedEventArgs RaiseTrayLeftMouseDownEvent() { - return RaiseTrayLeftMouseDownEvent(this); + //first raise event, then command + RoutedEventArgs args = RaiseTrayLeftMouseDownEvent(this); + RunCommand(LeftClickCommand, LeftClickCommandParameter); + return args; } /// @@ -824,7 +991,9 @@ namespace Hardcodet.Wpf.TaskbarNotification /// protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent() { - return RaiseTrayMouseDoubleClickEvent(this); + RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this); + RunCommand(DoubleClickCommand, DoubleClickCommandParameter); + return args; } /// @@ -1515,6 +1684,11 @@ namespace Hardcodet.Wpf.TaskbarNotification //register change listener for the Visibility property PropertyMetadata md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); VisibilityProperty.OverrideMetadata(typeof(TaskbarIcon), md); + + //register change listener for the DataContext property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged)); + DataContextProperty.OverrideMetadata(typeof(TaskbarIcon), md); } + } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 9a9a454..97bc38e 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -149,17 +149,24 @@ namespace Hardcodet.Wpf.TaskbarNotification CloseBalloon(); } + //create an invisible popup that hosts the UIElement Popup popup = new Popup(); popup.AllowsTransparency = true; + //provide the popup with the taskbar icon's data context + popup.DataContext = DataContext; + //don't animate by default - devs can use attached //events or override popup.PopupAnimation = animation; Popup.CreateRootPopup(popup, balloon); - popup.PlacementTarget = this; + //TODO we don't really need this and it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too... + //popup.PlacementTarget = this; + popup.Placement = PlacementMode.AbsolutePoint; popup.StaysOpen = true; @@ -332,10 +339,9 @@ namespace Hardcodet.Wpf.TaskbarNotification if (visible) { - if (ContextMenu != null && ContextMenu.IsOpen || - TrayPopupResolved != null && TrayPopupResolved.IsOpen) + if (IsPopupOpen) { - //ignore if we have an open context menu or popup + //ignore if we are already displaying something down there return; } @@ -389,7 +395,10 @@ namespace Hardcodet.Wpf.TaskbarNotification //create an invisible tooltip that hosts the UIElement tt = new ToolTip(); tt.Placement = PlacementMode.Mouse; - tt.PlacementTarget = this; + + //TODO we don't really need this and it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. + //tt.PlacementTarget = this; //the tooltip (and implicitly its context) explicitly gets //the DataContext of this instance. If there is no DataContext, @@ -484,7 +493,10 @@ namespace Hardcodet.Wpf.TaskbarNotification Popup.CreateRootPopup(popup, TrayPopup); - popup.PlacementTarget = this; + //TODO we don't really need this and it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. + //popup.PlacementTarget = this; + popup.Placement = PlacementMode.AbsolutePoint; popup.StaysOpen = false; } diff --git a/Source/Sample Project/FancyPopup.xaml b/Source/Sample Project/FancyPopup.xaml index 44c32ce..432b97e 100644 --- a/Source/Sample Project/FancyPopup.xaml +++ b/Source/Sample Project/FancyPopup.xaml @@ -72,6 +72,7 @@ Language="de-ch" /> Error } -} +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/MouseEvent.cs b/Source/NotifyIconWpf/Interop/MouseEvent.cs index c304289..6f57593 100644 --- a/Source/NotifyIconWpf/Interop/MouseEvent.cs +++ b/Source/NotifyIconWpf/Interop/MouseEvent.cs @@ -1,4 +1,6 @@ -namespace Hardcodet.Wpf.TaskbarNotification.Interop + + +namespace Hardcodet.Wpf.TaskbarNotification.Interop { /// /// Event flags for clicked events. diff --git a/Source/NotifyIconWpf/Interop/NotifyCommand.cs b/Source/NotifyIconWpf/Interop/NotifyCommand.cs index 7c3abde..de0a639 100644 --- a/Source/NotifyIconWpf/Interop/NotifyCommand.cs +++ b/Source/NotifyIconWpf/Interop/NotifyCommand.cs @@ -1,4 +1,4 @@ -using System; + namespace Hardcodet.Wpf.TaskbarNotification.Interop { diff --git a/Source/NotifyIconWpf/Interop/TrayInfo.cs b/Source/NotifyIconWpf/Interop/TrayInfo.cs new file mode 100644 index 0000000..ded285b --- /dev/null +++ b/Source/NotifyIconWpf/Interop/TrayInfo.cs @@ -0,0 +1,172 @@ +// Interop code taken from Mike Marshall's AnyForm + +using System; +using System.Drawing; +using System.Runtime.InteropServices; + + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Resolves the current tray position. + /// + public static class TrayInfo + { + + [DllImport("user32.dll")] + private static extern Int32 GetWindowLong(IntPtr hWnd, Int32 Offset); + + + public static Point GetTrayLocation() + { + var info = new AppBarInfo(); + info.GetSystemTaskBarPosition(); + + Rectangle rcWorkArea = info.WorkArea; + + int x = 0, y = 0; + if (info.Edge == AppBarInfo.ScreenEdge.Left) + { + x = rcWorkArea.Left + 2; + y = rcWorkArea.Bottom; + } + else if (info.Edge == AppBarInfo.ScreenEdge.Bottom) + { + x = rcWorkArea.Right; + y = rcWorkArea.Bottom; + } + else if (info.Edge == AppBarInfo.ScreenEdge.Top) + { + x = rcWorkArea.Right; + y = rcWorkArea.Top; + } + else if (info.Edge == AppBarInfo.ScreenEdge.Right) + { + x = rcWorkArea.Right; + y = rcWorkArea.Bottom; + } + + return new Point { X = x, Y = y}; + } + } + + + + + internal class AppBarInfo + { + + [DllImport("user32.dll")] + private static extern IntPtr FindWindow(String lpClassName, String lpWindowName); + + [DllImport("shell32.dll")] + private static extern UInt32 SHAppBarMessage(UInt32 dwMessage, ref APPBARDATA data); + + [DllImport("user32.dll")] + private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, + IntPtr pvParam, UInt32 fWinIni); + + + private const int ABE_BOTTOM = 3; + private const int ABE_LEFT = 0; + private const int ABE_RIGHT = 2; + private const int ABE_TOP = 1; + + private const int ABM_GETTASKBARPOS = 0x00000005; + + // SystemParametersInfo constants + private const UInt32 SPI_GETWORKAREA = 0x0030; + + private APPBARDATA m_data; + + public ScreenEdge Edge + { + get { return (ScreenEdge) m_data.uEdge; } + } + + + public Rectangle WorkArea + { + get + { + Int32 bResult = 0; + var rc = new RECT(); + IntPtr rawRect = Marshal.AllocHGlobal(Marshal.SizeOf(rc)); + bResult = SystemParametersInfo(SPI_GETWORKAREA, 0, rawRect, 0); + rc = (RECT) Marshal.PtrToStructure(rawRect, rc.GetType()); + + if (bResult == 1) + { + Marshal.FreeHGlobal(rawRect); + return new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); + } + + return new Rectangle(0, 0, 0, 0); + } + } + + + + public void GetPosition(string strClassName, string strWindowName) + { + m_data = new APPBARDATA(); + m_data.cbSize = (UInt32) Marshal.SizeOf(m_data.GetType()); + + IntPtr hWnd = FindWindow(strClassName, strWindowName); + + if (hWnd != IntPtr.Zero) + { + UInt32 uResult = SHAppBarMessage(ABM_GETTASKBARPOS, ref m_data); + + if (uResult != 1) + { + throw new Exception("Failed to communicate with the given AppBar"); + } + } + else + { + throw new Exception("Failed to find an AppBar that matched the given criteria"); + } + } + + + public void GetSystemTaskBarPosition() + { + GetPosition("Shell_TrayWnd", null); + } + + + + + public enum ScreenEdge + { + Undefined = -1, + Left = ABE_LEFT, + Top = ABE_TOP, + Right = ABE_RIGHT, + Bottom = ABE_BOTTOM + } + + + [StructLayout(LayoutKind.Sequential)] + private struct APPBARDATA + { + public UInt32 cbSize; + public IntPtr hWnd; + public UInt32 uCallbackMessage; + public UInt32 uEdge; + public RECT rc; + public Int32 lParam; + } + + [StructLayout(LayoutKind.Sequential)] + private struct RECT + { + public Int32 left; + public Int32 top; + public Int32 right; + public Int32 bottom; + } + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 9aa2a2f..710fa06 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -1,4 +1,29 @@ -using System; +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + + +using System; using System.ComponentModel; using System.Diagnostics; diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj index 821a357..914b6b0 100644 --- a/Source/NotifyIconWpf/NotifyIconWpf.csproj +++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -40,14 +40,18 @@ 3.5 + + - + + Code + diff --git a/Source/NotifyIconWpf/PopupActivationMode.cs b/Source/NotifyIconWpf/PopupActivationMode.cs index 81248b8..2020929 100644 --- a/Source/NotifyIconWpf/PopupActivationMode.cs +++ b/Source/NotifyIconWpf/PopupActivationMode.cs @@ -1,4 +1,28 @@ -namespace Hardcodet.Wpf.TaskbarNotification +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + +namespace Hardcodet.Wpf.TaskbarNotification { /// /// Defines flags that define when a popup diff --git a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs index d869e15..df1277c 100644 --- a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs +++ b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs @@ -1,6 +1,4 @@ using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Markup; @@ -8,16 +6,16 @@ using System.Windows.Markup; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("NotifyIconWpf")] -[assembly: AssemblyDescription("NotifyIcon Implementation for WPF.")] +[assembly: AssemblyTitle("NotifyIcon for WPF")] +[assembly: AssemblyDescription("NotifyIcon Implementation for the WPF platform.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("hardcodet.net")] -[assembly: AssemblyProduct("NotifyIconWpf")] +[assembly: AssemblyProduct("NotifyIcon WPF")] [assembly: AssemblyCopyright("Copyright © Philipp Sumi 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - +//provides simplified declaration [assembly: XmlnsDefinition("http://www.hardcodet.net/taskbar", "Hardcodet.Wpf.TaskbarNotification")] // Setting ComVisible to false makes the types in this assembly not visible diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 2870a7c..22fe1d5 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -1,4 +1,29 @@ -using System; +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + + +using System; using System.ComponentModel; using System.Drawing; using System.Windows; @@ -33,6 +58,11 @@ namespace Hardcodet.Wpf.TaskbarNotification = DependencyProperty.RegisterReadOnly("TrayPopupResolved", typeof(Popup), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null)); + + /// + /// A read-only dependency property that returns the + /// that is being displayed in the taskbar area based on a user action. + /// public static readonly DependencyProperty TrayPopupResolvedProperty = TrayPopupResolvedPropertyKey.DependencyProperty; @@ -70,6 +100,11 @@ namespace Hardcodet.Wpf.TaskbarNotification = DependencyProperty.RegisterReadOnly("TrayToolTipResolved", typeof(ToolTip), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null )); + + /// + /// A read-only dependency property that returns the + /// that is being displayed. + /// public static readonly DependencyProperty TrayToolTipResolvedProperty = TrayToolTipResolvedPropertyKey.DependencyProperty; @@ -336,7 +371,7 @@ namespace Hardcodet.Wpf.TaskbarNotification if (e.OldValue != null) { //remove the taskbar icon reference from the previously used element - SetParentTaskbarIcon((DependencyObject) e.OldValue, this); + SetParentTaskbarIcon((DependencyObject) e.OldValue, null); } @@ -407,7 +442,7 @@ namespace Hardcodet.Wpf.TaskbarNotification if (e.OldValue != null) { //remove the taskbar icon reference from the previously used element - SetParentTaskbarIcon((DependencyObject)e.OldValue, this); + SetParentTaskbarIcon((DependencyObject)e.OldValue, null); } @@ -434,7 +469,7 @@ namespace Hardcodet.Wpf.TaskbarNotification DependencyProperty.Register("MenuActivation", typeof (PopupActivationMode), typeof (TaskbarIcon), - new FrameworkPropertyMetadata(PopupActivationMode.RightClick, MenuActivationPropertyChanged)); + new FrameworkPropertyMetadata(PopupActivationMode.RightClick)); /// /// A property wrapper for the @@ -450,34 +485,6 @@ namespace Hardcodet.Wpf.TaskbarNotification set { SetValue(MenuActivationProperty, value); } } - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void MenuActivationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnMenuActivationPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnMenuActivationPropertyChanged(DependencyPropertyChangedEventArgs e) - { - //currently not needed - } - #endregion #region PopupActivation dependency property @@ -490,7 +497,7 @@ namespace Hardcodet.Wpf.TaskbarNotification DependencyProperty.Register("PopupActivation", typeof (PopupActivationMode), typeof (TaskbarIcon), - new FrameworkPropertyMetadata(PopupActivationMode.LeftClick, PopupActivationPropertyChanged)); + new FrameworkPropertyMetadata(PopupActivationMode.LeftClick)); /// /// A property wrapper for the @@ -506,34 +513,6 @@ namespace Hardcodet.Wpf.TaskbarNotification set { SetValue(PopupActivationProperty, value); } } - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void PopupActivationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnPopupActivationPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnPopupActivationPropertyChanged(DependencyPropertyChangedEventArgs e) - { - //currently not needed - } - #endregion @@ -726,21 +705,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - /// - /// Executes a given command. - /// - /// The command to be executed. - /// An optional parameter that was associated with - /// the command. - private static void RunCommand(ICommand command, object commandParameter) - { - if (command == null) return; - if (command.CanExecute(commandParameter)) - { - command.Execute(commandParameter); - } - } - //EVENTS @@ -769,7 +733,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { //first raise event, then command RoutedEventArgs args = RaiseTrayLeftMouseDownEvent(this); - RunCommand(LeftClickCommand, LeftClickCommandParameter); + LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter); return args; } @@ -1019,7 +983,7 @@ namespace Hardcodet.Wpf.TaskbarNotification protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent() { RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this); - RunCommand(DoubleClickCommand, DoubleClickCommandParameter); + DoubleClickCommand.ExecuteIfEnabled(DoubleClickCommandParameter); return args; } @@ -1685,21 +1649,66 @@ namespace Hardcodet.Wpf.TaskbarNotification /// A static helper method to raise the BalloonShowing event on a target element. /// /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseBalloonShowingEvent(DependencyObject target) + /// The instance that manages the balloon. + internal static RoutedEventArgs RaiseBalloonShowingEvent(DependencyObject target, TaskbarIcon source) { if (target == null) return null; - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = BalloonShowingEvent; + RoutedEventArgs args = new RoutedEventArgs(BalloonShowingEvent, source); + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region BalloonClosing + + /// + /// BalloonClosing Attached Routed Event + /// + public static readonly RoutedEvent BalloonClosingEvent = EventManager.RegisterRoutedEvent("BalloonClosing", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Adds a handler for the BalloonClosing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, BalloonClosingEvent, handler); + } + + /// + /// Removes a handler for the BalloonClosing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, BalloonClosingEvent, handler); + } + + /// + /// A static helper method to raise the BalloonClosing event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + /// The instance that manages the balloon. + internal static RoutedEventArgs RaiseBalloonClosingEvent(DependencyObject target, TaskbarIcon source) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(BalloonClosingEvent, source); RoutedEventHelper.RaiseEvent(target, args); return args; } #endregion + + //ATTACHED PROPERTIES - //TODO put into use #region ParentTaskbarIcon /// @@ -1729,9 +1738,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - - - //BASE CLASS PROPERTY OVERRIDES /// diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 4021df0..dd8405a 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -1,4 +1,28 @@ -using System; +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + +using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing; @@ -6,6 +30,7 @@ using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; +using System.Windows.Threading; using Hardcodet.Wpf.TaskbarNotification.Interop; using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point; @@ -122,6 +147,8 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + #region Custom Balloons + /// /// Shows a custom control as a tooltip in the tray location. /// @@ -133,6 +160,13 @@ namespace Hardcodet.Wpf.TaskbarNotification /// is a null reference. public void ShowCustomBalloon(UIElement balloon, PopupAnimation animation, int? timeout) { + if (!Application.Current.Dispatcher.CheckAccess()) + { + var action = new Action(() => ShowCustomBalloon(balloon, animation, timeout)); + Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, action); + return; + } + if (balloon == null) throw new ArgumentNullException("balloon"); if (timeout.HasValue && timeout < 500) { @@ -184,7 +218,7 @@ namespace Hardcodet.Wpf.TaskbarNotification SetParentTaskbarIcon(balloon, this); //fire attached event - RaiseBalloonShowingEvent(balloon); + RaiseBalloonShowingEvent(balloon, this); //display item popup.IsOpen = true; @@ -200,12 +234,39 @@ namespace Hardcodet.Wpf.TaskbarNotification /// - /// Closes the current , if it's set. + /// Resets the closing timeout, which effectively + /// keeps a displayed balloon message open until + /// it is either closed programmatically through + /// or due to a new + /// message being displayed. + /// + public void ResetBalloonCloseTimer() + { + if (IsDisposed) return; + + lock (this) + { + //reset timer in any case + balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + } + + + /// + /// Closes the current , if the + /// property is set. /// public void CloseBalloon() { if (IsDisposed) return; + if (!Application.Current.Dispatcher.CheckAccess()) + { + Action action = CloseBalloon; + Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, action); + return; + } + lock (this) { //reset timer in any case @@ -215,13 +276,23 @@ namespace Hardcodet.Wpf.TaskbarNotification Popup popup = CustomBalloon; if (popup != null) { - //if a balloon message is already displayed, close it immediately - popup.IsOpen = false; - - //reset attached property UIElement element = popup.Child; - if (element != null) SetParentTaskbarIcon(element, null); + //announce closing + RoutedEventArgs eventArgs = RaiseBalloonClosingEvent(element, this); + if (!eventArgs.Handled) + { + //if the event was handled, clear the reference to the popup, + //but don't close it - the handling code has to manage this stuff now + + //close the popup + popup.IsOpen = false; + + //reset attached property + if (element != null) SetParentTaskbarIcon(element, null); + } + + //remove custom balloon anyway SetCustomBalloon(null); } } @@ -241,6 +312,9 @@ namespace Hardcodet.Wpf.TaskbarNotification Application.Current.Dispatcher.Invoke(action); } + #endregion + + #region Process Incoming Mouse Events @@ -405,7 +479,8 @@ namespace Hardcodet.Wpf.TaskbarNotification tt.Placement = PlacementMode.Mouse; //do *not* set the placement target, as it causes the popup to become hidden if the - //TaskbarIcon's parent is hidden, too. + //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through + //the ParentTaskbarIcon attached dependency property: //tt.PlacementTarget = this; //the tooltip (and implicitly its context) explicitly gets @@ -478,13 +553,10 @@ namespace Hardcodet.Wpf.TaskbarNotification /// property which prevents this issue. private void CreatePopup() { - //no popup is available - if (TrayPopup == null) return; - //check if the item itself is a popup Popup popup = TrayPopup as Popup; - if (popup == null) + if (popup == null && TrayPopup != null) { //create an invisible popup that hosts the UIElement popup = new Popup(); @@ -501,8 +573,9 @@ namespace Hardcodet.Wpf.TaskbarNotification Popup.CreateRootPopup(popup, TrayPopup); - //TODO we don't really need this and it causes the popup to become hidden if the - //TaskbarIcon's parent is hidden, too. + //do *not* set the placement target, as it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through + //the ParentTaskbarIcon attached dependency property: //popup.PlacementTarget = this; popup.Placement = PlacementMode.AbsolutePoint; diff --git a/Source/NotifyIconWpf/Util.cs b/Source/NotifyIconWpf/Util.cs index 4b2acc4..8691996 100644 --- a/Source/NotifyIconWpf/Util.cs +++ b/Source/NotifyIconWpf/Util.cs @@ -1,7 +1,33 @@ -using System; +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + + +using System; using System.ComponentModel; using System.Drawing; using System.Windows; +using System.Windows.Input; using System.Windows.Media; using System.Windows.Resources; using Hardcodet.Wpf.TaskbarNotification.Interop; @@ -222,5 +248,27 @@ namespace Hardcodet.Wpf.TaskbarNotification } #endregion + + + #region execute command + + /// + /// Executes a given command if its method + /// indicates it can run. + /// + /// The command to be executed, or a null reference. + /// An optional parameter that is associated with + /// the command. + public static void ExecuteIfEnabled(this ICommand command, object commandParameter) + { + if (command == null) return; + if (command.CanExecute(commandParameter)) + { + command.Execute(commandParameter); + } + } + + #endregion + } } diff --git a/Source/Sample Project/FancyBalloon.xaml b/Source/Sample Project/FancyBalloon.xaml index da723bb..b7339d5 100644 --- a/Source/Sample Project/FancyBalloon.xaml +++ b/Source/Sample Project/FancyBalloon.xaml @@ -12,7 +12,7 @@ - + @@ -27,10 +27,22 @@ + + + + + + + + + + + + - + @@ -38,8 +50,15 @@ + + + + + + + - + - + diff --git a/Source/Sample Project/FancyBalloon.xaml.cs b/Source/Sample Project/FancyBalloon.xaml.cs index ccda58e..23c97cb 100644 --- a/Source/Sample Project/FancyBalloon.xaml.cs +++ b/Source/Sample Project/FancyBalloon.xaml.cs @@ -4,10 +4,12 @@ using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; +using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; @@ -20,6 +22,8 @@ namespace Sample_Project /// public partial class FancyBalloon : UserControl { + private bool isClosing = false; + #region BalloonText dependency property /// @@ -48,6 +52,19 @@ namespace Sample_Project public FancyBalloon() { InitializeComponent(); + TaskbarIcon.AddBalloonClosingHandler(this, OnBalloonClosing); + } + + + /// + /// By subscribing to the + /// and setting the "Handled" property to true, we suppress the popup + /// from being closed in order to display the fade-out animation. + /// + private void OnBalloonClosing(object sender, RoutedEventArgs e) + { + e.Handled = true; + isClosing = true; } @@ -61,5 +78,31 @@ namespace Sample_Project TaskbarIcon taskbarIcon = TaskbarIcon.GetParentTaskbarIcon(this); taskbarIcon.CloseBalloon(); } + + /// + /// If the users hovers over the balloon, we don't close it. + /// + private void grid_MouseEnter(object sender, MouseEventArgs e) + { + //if we're already running the fade-out animation, do not interrupt anymore + //(makes things too complicated for the sample) + if (isClosing) return; + + //the tray icon assigned this attached property to simplify access + TaskbarIcon taskbarIcon = TaskbarIcon.GetParentTaskbarIcon(this); + taskbarIcon.ResetBalloonCloseTimer(); + } + + + /// + /// Closes the popup once the fade-out animation completed. + /// The animation was triggered in XAML through the attached + /// BalloonClosing event. + /// + private void OnFadeOutCompleted(object sender, EventArgs e) + { + Popup pp = (Popup)Parent; + pp.IsOpen = false; + } } } diff --git a/Source/Sample Project/Images/Close.png b/Source/Sample Project/Images/Close.png new file mode 100644 index 0000000000000000000000000000000000000000..7b03ffc736bdaaab31364ea9cab034ecf7992fbc GIT binary patch literal 667 zcmV;M0%ZM(P)PpNH`{m&eCC@Yw)3-Q7*TnV2AKwGcw|fqjC1UZoUzGRe=qy(EAE@OXc( z9LqvE4jN!iPtz_I(OkESOr_9G6Sq`C0mAcmyt`8X8h{UUtSX*u6Uk(lTwUe$$_h@i ziS&IYb2&1(93mdawQby54X>xl0Pq0Ms-k-V?P8Iz(;+oG%hdWh1L-ueu`y)1j9V@f z)a%fZ_&tKI0s+2dp==w@&iJ*tiQ8&1JU7SS_&83f#P!Ao`t>!M;~?_|yk0VW1(hG) z85v9xi^XU+8Z^pf5{3al{o#S&{2WoOV%2KY0}oFro@Jm(2dz>;`aZ9=w;`P-e|gDc zK2LOJhUC^3o|KqDKvWaYEqH*2Ko^48;v$i$DH>N-*vrd2WV6Uh1#@A6$oxDJKo?!x zeG5Ji3Pqqm+ux@ihUh0JEEEc;LV?@0HN?mW1E;67fS`x@n}L9~QnV06fuVx~5=!A{ z8UVu=7dS#t7lJ0;-DlqzPtb6T5YYi81Z}`X5a})X2qcQ%D4I&)L_?L1(ZK2ve0a;Z z<3ga9>>%|Nj0WQAl + xmlns:Commands="clr-namespace:Sample_Project.Commands" MinWidth="750" MinHeight="800" ResizeMode="NoResize"> + x:Name="ToolTips" Height="233" VerticalAlignment="Top" d:LayoutOverrides="VerticalAlignment"> public static class TrayInfo { - - [DllImport("user32.dll")] - private static extern Int32 GetWindowLong(IntPtr hWnd, Int32 Offset); - - + /// + /// Gets the position of the system tray. + /// + /// Tray coordinates. public static Point GetTrayLocation() { var info = new AppBarInfo(); diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj index 914b6b0..e7b3757 100644 --- a/Source/NotifyIconWpf/NotifyIconWpf.csproj +++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -85,6 +85,7 @@ ResXFileCodeGenerator Resources.Designer.cs + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs index df1277c..e49731a 100644 --- a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs +++ b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs @@ -53,5 +53,5 @@ using System.Windows.Markup; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.0.1.0")] diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 22fe1d5..0166c6a 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -557,7 +557,24 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - #region DataContext dependency property override + #region DataContext dependency property override / target update + + /// + /// Updates the of a given + /// . This method only updates target elements + /// that do not already have a data context of their own, and either assigns + /// the of the NotifyIcon, or the + /// NotifyIcon itself, if no data context was assigned at all. + /// + private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue) + { + if (target != null && !target.IsDataContextDataBound() && Equals(oldDataContextValue, target.DataContext)) + { + //assign own data context, if available. If there is no data + //context at all, assign NotifyIcon itself. + target.DataContext = newDataContextValue ?? this; + } + } /// /// A static callback listener which is being invoked if the @@ -586,24 +603,58 @@ namespace Hardcodet.Wpf.TaskbarNotification object newValue = e.NewValue; object oldValue = e.OldValue; - //replace custom data context for popup and tooltip, if - //they are reflecting the data context's data context - var popup = TrayPopupResolved; - var toolTip = TrayToolTipResolved; - - if (popup != null && Equals(popup.DataContext, oldValue)) - { - popup.DataContext = newValue; - } - - if (toolTip != null && Equals(toolTip.DataContext, oldValue)) - { - toolTip.DataContext = newValue; - } + //replace custom data context for ToolTips, Popup, and + //ContextMenu + UpdateDataContext(TrayPopupResolved, oldValue, newValue); + UpdateDataContext(TrayToolTipResolved, oldValue, newValue); + UpdateDataContext(ContextMenu, oldValue, newValue); } #endregion + #region ContextMenu dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon)d; + owner.OnContextMenuPropertyChanged(e); + } + + + /// + /// Releases the old and updates the new property + /// in order to reflect both the NotifyIcon's + /// property and have the assigned. + /// + /// Provides information about the updated property. + private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + { + //remove the taskbar icon reference from the previously used element + SetParentTaskbarIcon((DependencyObject)e.OldValue, null); + } + + if (e.NewValue != null) + { + //set this taskbar icon as a reference to the new tooltip element + SetParentTaskbarIcon((DependencyObject)e.NewValue, this); + } + + UpdateDataContext((ContextMenu) e.NewValue, null, DataContext); + } + + #endregion + + #region DoubleClickCommand dependency property @@ -1752,7 +1803,12 @@ namespace Hardcodet.Wpf.TaskbarNotification //register change listener for the DataContext property md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged)); DataContextProperty.OverrideMetadata(typeof(TaskbarIcon), md); + + //register change listener for the ContextMenu property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); + ContextMenuProperty.OverrideMetadata(typeof(TaskbarIcon), md); } + } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index dd8405a..cd3afa4 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -30,6 +30,7 @@ using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; +using System.Windows.Data; using System.Windows.Threading; using Hardcodet.Wpf.TaskbarNotification.Interop; using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point; @@ -182,14 +183,13 @@ namespace Hardcodet.Wpf.TaskbarNotification { CloseBalloon(); } - //create an invisible popup that hosts the UIElement Popup popup = new Popup(); popup.AllowsTransparency = true; //provide the popup with the taskbar icon's data context - popup.DataContext = DataContext; + UpdateDataContext(popup, null, DataContext); //don't animate by default - devs can use attached //events or override @@ -314,8 +314,6 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion - - #region Process Incoming Mouse Events /// @@ -483,11 +481,6 @@ namespace Hardcodet.Wpf.TaskbarNotification //the ParentTaskbarIcon attached dependency property: //tt.PlacementTarget = this; - //the tooltip (and implicitly its context) explicitly gets - //the DataContext of this instance. If there is no DataContext, - //the TaskbarIcon sets itself - tt.DataContext = DataContext ?? this; - //make sure the tooltip is invisible tt.HasDropShadow = false; tt.BorderThickness = new Thickness(0); @@ -504,6 +497,13 @@ namespace Hardcodet.Wpf.TaskbarNotification tt.Content = ToolTipText; } + //the tooltip explicitly gets the DataContext of this instance. + //If there is no DataContext, the TaskbarIcon assigns itself + if (tt != null) + { + UpdateDataContext(tt, null, DataContext); + } + //store a reference to the used tooltip SetTrayToolTipResolved(tt); } @@ -566,11 +566,9 @@ namespace Hardcodet.Wpf.TaskbarNotification //events or override popup.PopupAnimation = PopupAnimation.None; - //the tooltip (and implicitly its context) explicitly gets - //the DataContext of this instance. If there is no DataContext, - //the TaskbarIcon assigns itself - popup.DataContext = DataContext ?? this; - + //the CreateRootPopup method outputs binding errors in the debug window because + //it tries to bind to "Popup-specific" properties in case they are provided by the child + //not a problem. Popup.CreateRootPopup(popup, TrayPopup); //do *not* set the placement target, as it causes the popup to become hidden if the @@ -582,6 +580,13 @@ namespace Hardcodet.Wpf.TaskbarNotification popup.StaysOpen = false; } + //the popup explicitly gets the DataContext of this instance. + //If there is no DataContext, the TaskbarIcon assigns itself + if (popup != null) + { + UpdateDataContext(popup, null, DataContext); + } + //store a reference to the used tooltip SetTrayPopupResolved(popup); } diff --git a/Source/NotifyIconWpf/Util.cs b/Source/NotifyIconWpf/Util.cs index 8691996..c7ef9f6 100644 --- a/Source/NotifyIconWpf/Util.cs +++ b/Source/NotifyIconWpf/Util.cs @@ -27,6 +27,7 @@ using System; using System.ComponentModel; using System.Drawing; using System.Windows; +using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Resources; @@ -99,9 +100,10 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Updates the taskbar icons with data provided by a given /// instance. /// - /// - /// - /// + /// Configuration settings for the NotifyIcon. + /// Operation on the icon (e.g. delete the icon). + /// True if the data was successfully written. + /// See Shell_NotifyIcon documentation on MSDN for details. public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command) { return WriteIconData(ref data, command, data.ValidMembers); @@ -112,10 +114,12 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Updates the taskbar icons with data provided by a given /// instance. /// - /// - /// - /// - /// + /// Configuration settings for the NotifyIcon. + /// Operation on the icon (e.g. delete the icon). + /// Defines which members of the + /// structure are set. + /// True if the data was successfully written. + /// See Shell_NotifyIcon documentation on MSDN for details. public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command, IconDataMembers flags) { //do nothing if in design mode @@ -270,5 +274,21 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + + /// + /// Checks whether the + /// is bound or not. + /// + /// The element to be checked. + /// True if the data context property is being managed by a + /// binding expression. + /// If + /// is a null reference. + public static bool IsDataContextDataBound(this FrameworkElement element) + { + if (element == null) throw new ArgumentNullException("element"); + return element.GetBindingExpression(FrameworkElement.DataContextProperty) != null; + } + } } From f349d3d3393b9d7596ff61c7186f5376b8599262 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Wed, 13 May 2009 09:32:55 +0000 Subject: [PATCH 12/73] WPF NotifyIcon -------------- CHG Generally improved sample project - added more bindings, welcome balloon, changed layout. CHG Changed namespace in sample project. Preparing tutorials. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@101 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Changelog.txt | 20 + Source/NotifyIconWpf.sln | 5 + Source/Sample Project/App.xaml | 2 +- Source/Sample Project/App.xaml.cs | 2 +- Source/Sample Project/Commands/CommandBase.cs | 2 +- .../Commands/HideMainWindowCommand.cs | 2 +- .../Commands/ShowMainWindowCommand.cs | 2 +- Source/Sample Project/FancyBalloon.xaml | 2 +- Source/Sample Project/FancyBalloon.xaml.cs | 2 +- Source/Sample Project/FancyPopup.xaml | 4 +- Source/Sample Project/FancyPopup.xaml.cs | 2 +- Source/Sample Project/FancyToolTip.xaml | 4 +- Source/Sample Project/FancyToolTip.xaml.cs | 2 +- .../Properties/Resources.Designer.cs | 4 +- .../Properties/Settings.Designer.cs | 32 +- Source/Sample Project/Sample Project.csproj | 26 +- .../Sample Project/TaskbarIconResources.xaml | 29 +- .../Tutorials/01 - Declaration/Window1.xaml | 17 + .../01 - Declaration/Window1.xaml.cs | 15 + .../02 - ToolTips/SimpleUserControl.xaml | 8 + .../02 - ToolTips/SimpleUserControl.xaml.cs | 27 + Source/Sample Project/WelcomeBalloon.xaml | 93 ++++ Source/Sample Project/WelcomeBalloon.xaml.cs | 27 + Source/Sample Project/Window1.xaml | 461 ++++++++++++------ Source/Sample Project/Window1.xaml.cs | 19 +- 25 files changed, 612 insertions(+), 197 deletions(-) create mode 100644 Source/Changelog.txt create mode 100644 Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml create mode 100644 Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml.cs create mode 100644 Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml create mode 100644 Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs create mode 100644 Source/Sample Project/WelcomeBalloon.xaml create mode 100644 Source/Sample Project/WelcomeBalloon.xaml.cs diff --git a/Source/Changelog.txt b/Source/Changelog.txt new file mode 100644 index 0000000..27fab31 --- /dev/null +++ b/Source/Changelog.txt @@ -0,0 +1,20 @@ +hardcodet.net NotifyIcon for WPF - Changelog +Copyright (c) 2009 Philipp Sumi +Contact and Information: http://www.hardcodet.net + + +---------------------------------------------------------------------------- + +1.0.1 +***** +CHG DataContext is also assigned to ContextMenu, and properly coerced for + ToolTips and Popups. Also checks whether target item has a binding + on the DataContext (does not just override if DataContext is null). + + + +---------------------------------------------------------------------------- + +1.0.0 +***** +ADD Initial release. \ No newline at end of file diff --git a/Source/NotifyIconWpf.sln b/Source/NotifyIconWpf.sln index b1e2296..84d90fa 100644 --- a/Source/NotifyIconWpf.sln +++ b/Source/NotifyIconWpf.sln @@ -5,6 +5,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotifyIconWpf", "NotifyIcon EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample Project", "Sample Project\Sample Project.csproj", "{71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C37AE34D-A8C4-4AEC-995C-3C763300934E}" + ProjectSection(SolutionItems) = preProject + Changelog.txt = Changelog.txt + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Source/Sample Project/App.xaml b/Source/Sample Project/App.xaml index 04fb858..e3eec8e 100644 --- a/Source/Sample Project/App.xaml +++ b/Source/Sample Project/App.xaml @@ -1,4 +1,4 @@ - diff --git a/Source/Sample Project/App.xaml.cs b/Source/Sample Project/App.xaml.cs index 92b661a..3ddc729 100644 --- a/Source/Sample Project/App.xaml.cs +++ b/Source/Sample Project/App.xaml.cs @@ -5,7 +5,7 @@ using System.Data; using System.Linq; using System.Windows; -namespace Sample_Project +namespace Samples { /// /// Interaction logic for App.xaml diff --git a/Source/Sample Project/Commands/CommandBase.cs b/Source/Sample Project/Commands/CommandBase.cs index b3411ae..c841986 100644 --- a/Source/Sample Project/Commands/CommandBase.cs +++ b/Source/Sample Project/Commands/CommandBase.cs @@ -2,7 +2,7 @@ using System.Windows.Input; using System.Windows.Markup; -namespace Sample_Project.Commands +namespace Samples.Commands { /// /// Basic implementation of the diff --git a/Source/Sample Project/Commands/HideMainWindowCommand.cs b/Source/Sample Project/Commands/HideMainWindowCommand.cs index ea40b97..eae7c0e 100644 --- a/Source/Sample Project/Commands/HideMainWindowCommand.cs +++ b/Source/Sample Project/Commands/HideMainWindowCommand.cs @@ -1,7 +1,7 @@ using System.Windows; using System.Windows.Input; -namespace Sample_Project.Commands +namespace Samples.Commands { /// /// Hides the main window. diff --git a/Source/Sample Project/Commands/ShowMainWindowCommand.cs b/Source/Sample Project/Commands/ShowMainWindowCommand.cs index d80e5ce..c499c85 100644 --- a/Source/Sample Project/Commands/ShowMainWindowCommand.cs +++ b/Source/Sample Project/Commands/ShowMainWindowCommand.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Windows; using System.Windows.Input; -namespace Sample_Project.Commands +namespace Samples.Commands { /// /// Shows the main window. diff --git a/Source/Sample Project/FancyBalloon.xaml b/Source/Sample Project/FancyBalloon.xaml index b7339d5..0dab931 100644 --- a/Source/Sample Project/FancyBalloon.xaml +++ b/Source/Sample Project/FancyBalloon.xaml @@ -1,5 +1,5 @@  /// Interaction logic for FancyBalloon.xaml diff --git a/Source/Sample Project/FancyPopup.xaml b/Source/Sample Project/FancyPopup.xaml index 432b97e..1cfb9cd 100644 --- a/Source/Sample Project/FancyPopup.xaml +++ b/Source/Sample Project/FancyPopup.xaml @@ -1,5 +1,5 @@  + diff --git a/Source/Sample Project/FancyPopup.xaml.cs b/Source/Sample Project/FancyPopup.xaml.cs index 7d5d028..c50f34f 100644 --- a/Source/Sample Project/FancyPopup.xaml.cs +++ b/Source/Sample Project/FancyPopup.xaml.cs @@ -1,7 +1,7 @@ using System.Windows; using System.Windows.Controls; -namespace Sample_Project +namespace Samples { /// /// Interaction logic for FancyPopup.xaml diff --git a/Source/Sample Project/FancyToolTip.xaml b/Source/Sample Project/FancyToolTip.xaml index 7db12ff..59be48b 100644 --- a/Source/Sample Project/FancyToolTip.xaml +++ b/Source/Sample Project/FancyToolTip.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:tb="http://www.hardcodet.net/taskbar" mc:Ignorable="d" - x:Class="Sample_Project.FancyToolTip" + x:Class="Samples.FancyToolTip" x:Name="me" Width="285" Height="136"> @@ -109,6 +109,6 @@ Foreground="#FF141414" TextWrapping="Wrap" Margin="82,42,20,44.96" - x:Name="txtToolTipDetail_Copy" > + x:Name="txtToolTipDetail_Copy" > \ No newline at end of file diff --git a/Source/Sample Project/FancyToolTip.xaml.cs b/Source/Sample Project/FancyToolTip.xaml.cs index d15a337..946d277 100644 --- a/Source/Sample Project/FancyToolTip.xaml.cs +++ b/Source/Sample Project/FancyToolTip.xaml.cs @@ -12,7 +12,7 @@ using System.Windows.Navigation; using System.Windows.Shapes; using Hardcodet.Wpf.TaskbarNotification; -namespace Sample_Project +namespace Samples { /// /// Interaction logic for FancyToolTip.xaml diff --git a/Source/Sample Project/Properties/Resources.Designer.cs b/Source/Sample Project/Properties/Resources.Designer.cs index 1646b08..c0666f1 100644 --- a/Source/Sample Project/Properties/Resources.Designer.cs +++ b/Source/Sample Project/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace Sample_Project.Properties { +namespace Samples.Properties { using System; @@ -39,7 +39,7 @@ namespace Sample_Project.Properties { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sample_Project.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Samples.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/Source/Sample Project/Properties/Settings.Designer.cs b/Source/Sample Project/Properties/Settings.Designer.cs index 4a1169a..acb4052 100644 --- a/Source/Sample Project/Properties/Settings.Designer.cs +++ b/Source/Sample Project/Properties/Settings.Designer.cs @@ -8,23 +8,19 @@ // //------------------------------------------------------------------------------ -namespace Sample_Project.Properties -{ - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { - return defaultInstance; - } +namespace Samples.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } } - } } diff --git a/Source/Sample Project/Sample Project.csproj b/Source/Sample Project/Sample Project.csproj index 7d102c5..ffeabeb 100644 --- a/Source/Sample Project/Sample Project.csproj +++ b/Source/Sample Project/Sample Project.csproj @@ -8,7 +8,7 @@ {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC} WinExe Properties - Sample_Project + Samples Sample Project v3.5 512 @@ -88,6 +88,18 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + MSBuild:Compile Designer @@ -124,6 +136,15 @@ True Settings.settings + + Window1.xaml + + + SimpleUserControl.xaml + + + WelcomeBalloon.xaml + ResXFileCodeGenerator Resources.Designer.cs @@ -156,9 +177,6 @@ - - - + + + + + + + diff --git a/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml b/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml new file mode 100644 index 0000000..59619ec --- /dev/null +++ b/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml.cs b/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml.cs new file mode 100644 index 0000000..caf3ef1 --- /dev/null +++ b/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows; + +namespace Samples.Tutorials +{ + /// + /// Interaction logic for SimpleDirectDeclaration.xaml + /// + public partial class SimpleDirectDeclaration : Window + { + public SimpleDirectDeclaration() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml b/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml new file mode 100644 index 0000000..606ca05 --- /dev/null +++ b/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs b/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs new file mode 100644 index 0000000..441276e --- /dev/null +++ b/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Samples.Tutorials +{ + /// + /// Interaction logic for SimpleUserControl.xaml + /// + public partial class SimpleUserControl : UserControl + { + public SimpleUserControl() + { + InitializeComponent(); + } + } +} diff --git a/Source/Sample Project/WelcomeBalloon.xaml b/Source/Sample Project/WelcomeBalloon.xaml new file mode 100644 index 0000000..d8231a9 --- /dev/null +++ b/Source/Sample Project/WelcomeBalloon.xaml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Sample Project/WelcomeBalloon.xaml.cs b/Source/Sample Project/WelcomeBalloon.xaml.cs new file mode 100644 index 0000000..0f29d2f --- /dev/null +++ b/Source/Sample Project/WelcomeBalloon.xaml.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Samples +{ + /// + /// Interaction logic for WelcomeBalloon.xaml + /// + public partial class WelcomeBalloon : UserControl + { + public WelcomeBalloon() + { + InitializeComponent(); + } + } +} diff --git a/Source/Sample Project/Window1.xaml b/Source/Sample Project/Window1.xaml index 66acba9..9290ccd 100644 --- a/Source/Sample Project/Window1.xaml +++ b/Source/Sample Project/Window1.xaml @@ -1,17 +1,20 @@  + xmlns:local="clr-namespace:Samples" + xmlns:Commands="clr-namespace:Samples.Commands" + MinWidth="750" + MinHeight="800" + ResizeMode="NoResize"> + SourceName="tb" /> - + + + - - - + + DoubleClickCommand="{Commands:ShowMainWindowCommand}"> @@ -85,57 +88,19 @@ - - - + + + - - - - - - - + Height="248" + x:Name="Balloons" + Width="372" + HorizontalAlignment="Left"> WPF NotifyIcon + x:Name="txtBalloonText" + AcceptsReturn="True" + Height="47" + VerticalAlignment="Bottom" + d:LayoutOverrides="VerticalAlignment" + TextWrapping="Wrap" + Text="You should see a LED icon in your system tray. This is your NotifyIcon." /> + Text="Balloon Title" /> + Width="85" + Height="23" + VerticalAlignment="Bottom" + d:LayoutOverrides="VerticalAlignment"> + Text="Displays default balloon tips as supported by the OS. " /> public partial class App : Application { + } } diff --git a/Source/Sample Project/Commands/CommandBase.cs b/Source/Sample Project/Commands/CommandBase.cs index c841986..9b47695 100644 --- a/Source/Sample Project/Commands/CommandBase.cs +++ b/Source/Sample Project/Commands/CommandBase.cs @@ -1,4 +1,6 @@ using System; +using System.ComponentModel; +using System.Windows; using System.Windows.Input; using System.Windows.Markup; @@ -58,7 +60,18 @@ namespace Samples.Commands /// public virtual bool CanExecute(object parameter) { - return true; + return IsDesignMode ? false : true; + } + + + public static bool IsDesignMode + { + get + { + return (bool) + DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement)) + .Metadata.DefaultValue; + } } } } diff --git a/Source/Sample Project/Commands/HideMainWindowCommand.cs b/Source/Sample Project/Commands/HideMainWindowCommand.cs index eae7c0e..694fb1f 100644 --- a/Source/Sample Project/Commands/HideMainWindowCommand.cs +++ b/Source/Sample Project/Commands/HideMainWindowCommand.cs @@ -18,7 +18,7 @@ namespace Samples.Commands public override bool CanExecute(object parameter) { - return Application.Current.MainWindow.IsVisible; + return !IsDesignMode && Application.Current.MainWindow.IsVisible; } diff --git a/Source/Sample Project/Commands/ShowMainWindowCommand.cs b/Source/Sample Project/Commands/ShowMainWindowCommand.cs index c499c85..f3bccc9 100644 --- a/Source/Sample Project/Commands/ShowMainWindowCommand.cs +++ b/Source/Sample Project/Commands/ShowMainWindowCommand.cs @@ -20,7 +20,7 @@ namespace Samples.Commands public override bool CanExecute(object parameter) { - return Application.Current.MainWindow.IsVisible == false; + return !IsDesignMode && Application.Current.MainWindow.IsVisible == false; } } diff --git a/Source/Sample Project/Images/Preferences.png b/Source/Sample Project/Images/Preferences.png new file mode 100644 index 0000000000000000000000000000000000000000..cd420d73e900e3e34e41fe4af245ef70dfcd38b5 GIT binary patch literal 7825 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 e_Z%*j3ugJkm?&CG8KkMMtA + + + + + + + + + + - public partial class Window1 : Window + public partial class ShowcaseWindow : Window { - public Window1() + public ShowcaseWindow() { InitializeComponent(); @@ -82,5 +81,13 @@ namespace Samples Process.Start(e.Uri.ToString()); e.Handled = true; } + + + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) + { + //clean up notifyicon (would otherwise stay open until application finishes) + tb.Dispose(); + base.OnClosing(e); + } } } \ No newline at end of file diff --git a/Source/Sample Project/WelcomeBalloon.xaml b/Source/Sample Project/Showcase/WelcomeBalloon.xaml similarity index 100% rename from Source/Sample Project/WelcomeBalloon.xaml rename to Source/Sample Project/Showcase/WelcomeBalloon.xaml diff --git a/Source/Sample Project/WelcomeBalloon.xaml.cs b/Source/Sample Project/Showcase/WelcomeBalloon.xaml.cs similarity index 100% rename from Source/Sample Project/WelcomeBalloon.xaml.cs rename to Source/Sample Project/Showcase/WelcomeBalloon.xaml.cs diff --git a/Source/Sample Project/Tutorials/01 - Declaration/NotifyIconResourceDictionary.xaml b/Source/Sample Project/Tutorials/01 - Declaration/NotifyIconResourceDictionary.xaml new file mode 100644 index 0000000..021457e --- /dev/null +++ b/Source/Sample Project/Tutorials/01 - Declaration/NotifyIconResourceDictionary.xaml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml b/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml similarity index 62% rename from Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml rename to Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml index 59619ec..000598d 100644 --- a/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml +++ b/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml @@ -1,5 +1,5 @@  + diff --git a/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml.cs b/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml.cs new file mode 100644 index 0000000..ab7ae3e --- /dev/null +++ b/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml.cs @@ -0,0 +1,23 @@ +using System.Windows; + +namespace Samples.Tutorials +{ + /// + /// Interaction logic for SimpleWindowWithNotifyIcon.xaml + /// + public partial class SimpleWindowWithNotifyIcon : Window + { + public SimpleWindowWithNotifyIcon() + { + InitializeComponent(); + } + + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) + { + //clean up notifyicon (would otherwise stay open until application finishes) + MyNotifyIcon.Dispose(); + + base.OnClosing(e); + } + } +} \ No newline at end of file diff --git a/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml.cs b/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml.cs deleted file mode 100644 index caf3ef1..0000000 --- a/Source/Sample Project/Tutorials/01 - Declaration/Window1.xaml.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Windows; - -namespace Samples.Tutorials -{ - /// - /// Interaction logic for SimpleDirectDeclaration.xaml - /// - public partial class SimpleDirectDeclaration : Window - { - public SimpleDirectDeclaration() - { - InitializeComponent(); - } - } -} \ No newline at end of file diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml b/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml new file mode 100644 index 0000000..48f8a35 --- /dev/null +++ b/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml.cs b/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml.cs new file mode 100644 index 0000000..4477529 --- /dev/null +++ b/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace Samples.Tutorials.ToolTips +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class InlineToolTipWindow : Window + { + public InlineToolTipWindow() + { + InitializeComponent(); + } + + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) + { + //clean up notifyicon (would otherwise stay open until application finishes) + MyNotifyIcon.Dispose(); + + base.OnClosing(e); + } + } +} diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml b/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml index 606ca05..d8ad5d8 100644 --- a/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml +++ b/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml @@ -1,8 +1,22 @@ - - - - + + + + + + + diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs b/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs index 441276e..ee7d684 100644 --- a/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs +++ b/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs @@ -12,7 +12,7 @@ using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; -namespace Samples.Tutorials +namespace Samples.Tutorials.ToolTips { /// /// Interaction logic for SimpleUserControl.xaml diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml b/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml new file mode 100644 index 0000000..35a1f0c --- /dev/null +++ b/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml.cs b/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml.cs new file mode 100644 index 0000000..8910dc6 --- /dev/null +++ b/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace Samples.Tutorials.ToolTips +{ + /// + /// Interaction logic for UserControlToolTipWindow.xaml + /// + public partial class UserControlToolTipWindow : Window + { + public UserControlToolTipWindow() + { + InitializeComponent(); + } + + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) + { + //clean up notifyicon (would otherwise stay open until application finishes) + MyNotifyIcon.Dispose(); + + base.OnClosing(e); + } + } +} diff --git a/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml b/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml new file mode 100644 index 0000000..476889b --- /dev/null +++ b/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml @@ -0,0 +1,39 @@ + + + + + + + + + - - - - \ No newline at end of file diff --git a/Source/Sample Project/Showcase/ShowcaseWindow.xaml b/Source/Sample Project/Showcase/ShowcaseWindow.xaml index bcaa51a..6d0e48e 100644 --- a/Source/Sample Project/Showcase/ShowcaseWindow.xaml +++ b/Source/Sample Project/Showcase/ShowcaseWindow.xaml @@ -70,7 +70,9 @@ Visibility="{Binding Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}, ElementName=iconVisibility, Mode=Default}" MenuActivation="{Binding Path=SelectedItem, ElementName=lstMenuTrigger, Mode=Default}" PopupActivation="{Binding Path=SelectedItem, ElementName=lstPopupTrigger, Mode=Default}" - DoubleClickCommand="{Commands:ShowMainWindowCommand}"> + DoubleClickCommand="{Commands:ShowSampleWindowCommand}" + DoubleClickCommandParameter="{Binding RelativeSource={RelativeSource Self}}" + > diff --git a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml b/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml index 1dd568b..00789fe 100644 --- a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml +++ b/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml @@ -253,9 +253,7 @@ VerticalAlignment="Top" Height="31" TextWrapping="Wrap" - FontWeight="Bold"> + FontWeight="Bold"> \ No newline at end of file diff --git a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs b/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs index febb6e1..7562128 100644 --- a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs +++ b/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; +using System.Windows; namespace Samples.Tutorials.Events { diff --git a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml index 1fb880d..1fec7a4 100644 --- a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml +++ b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml @@ -4,12 +4,12 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:tb="http://www.hardcodet.net/taskbar" Height="300" - Width="300"> + Width="500"> @@ -36,16 +36,19 @@ - + - + + + + + + diff --git a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs index a383e18..e21e133 100644 --- a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs +++ b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; +using System.Windows; namespace Samples.Tutorials.DataBinding { @@ -27,9 +16,10 @@ namespace Samples.Tutorials.DataBinding protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { //clean up notifyicon (would otherwise stay open until application finishes) - MyNotifyIcon.Dispose(); + MyNotifyIcon1.Dispose(); + MyNotifyIcon2.Dispose(); base.OnClosing(e); } } -} +} \ No newline at end of file From aa4e7d00b3fb5c68af8d63f4abb36c665cc1c8e0 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 May 2009 20:33:45 +0000 Subject: [PATCH 17/73] WPF NotifyIcon -------------- CHG Changes in sample project. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@107 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Changelog.txt | 12 ++-- Source/Sample Project/Main.xaml | 62 +++++++++++-------- .../Showcase/ShowcaseWindow.xaml | 2 +- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/Source/Changelog.txt b/Source/Changelog.txt index 81bf8aa..086df01 100644 --- a/Source/Changelog.txt +++ b/Source/Changelog.txt @@ -7,14 +7,14 @@ Contact and Information: http://www.hardcodet.net 1.0.1 ***** -CHG DataContext is also assigned to ContextMenu, and properly coerced for - ToolTips and Popups. Also checks whether target item has a binding - on the DataContext (does not just override if DataContext is null). - Thanks Nic Pilllinger for pointing this one out. +CHG DataContext is also assigned to ContextMenu (thanks Nic Pilllinger), + and properly coerced for ToolTips and Popups. Also checks whether + target item has a binding on the DataContext + (does not just override if DataContext is null). CHG Popup creation no longer calls Popup.CreateRootPopup which tries to bind to dependency properties that do not exist, thus causing debug - warnings. Thanks to Loic Berthollet for the hint. -CHG The LeftClickCommand now executes with a delay in order to mak sure + warnings (thanks to Loic Berthollet). +CHG The LeftClickCommand now executes with a delay in order to make sure it's not a double-click. FIX Removed debug output in WindowMessageSink. diff --git a/Source/Sample Project/Main.xaml b/Source/Sample Project/Main.xaml index a972bc9..410cb08 100644 --- a/Source/Sample Project/Main.xaml +++ b/Source/Sample Project/Main.xaml @@ -2,7 +2,7 @@ x:Class="Samples.Main" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - Title="Main" + Title="NotifyIcon Samples" Height="563" Width="703" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" @@ -68,7 +68,7 @@ Click="btnInlineToolTip_Click" /> private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue) { - if (target != null && !target.IsDataContextDataBound() && Equals(oldDataContextValue, target.DataContext)) + //if there is no target or it's data context is determined through a binding + //of its own, keep it + if (target == null || target.IsDataContextDataBound()) return; + + //if the target's data context is the NotifyIcon's old DataContext or the NotifyIcon itself, + //update it + if (ReferenceEquals(this, target.DataContext) || Equals(oldDataContextValue, target.DataContext)) { //assign own data context, if available. If there is no data //context at all, assign NotifyIcon itself. diff --git a/Source/Sample Project/Main.xaml b/Source/Sample Project/Main.xaml index 410cb08..1a3ca52 100644 --- a/Source/Sample Project/Main.xaml +++ b/Source/Sample Project/Main.xaml @@ -31,7 +31,7 @@ FontStyle="Italic" FontWeight="Bold" TextWrapping="Wrap"> + Text="WPF NotifyIcon 1.0.2 - Samples" /> + + + + + + + + diff --git a/Source/WindowsFormsSample/FancyPopup.xaml.cs b/Source/WindowsFormsSample/FancyPopup.xaml.cs new file mode 100644 index 0000000..c50f34f --- /dev/null +++ b/Source/WindowsFormsSample/FancyPopup.xaml.cs @@ -0,0 +1,46 @@ +using System.Windows; +using System.Windows.Controls; + +namespace Samples +{ + /// + /// Interaction logic for FancyPopup.xaml + /// + public partial class FancyPopup : UserControl + { + #region ClickCount dependency property + + /// + /// The number of clicks on the popup button. + /// + public static readonly DependencyProperty ClickCountProperty = + DependencyProperty.Register("ClickCount", + typeof (int), + typeof (FancyPopup), + new FrameworkPropertyMetadata(0)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The number of clicks on the popup button. + ///
+ public int ClickCount + { + get { return (int) GetValue(ClickCountProperty); } + set { SetValue(ClickCountProperty, value); } + } + + #endregion + + public FancyPopup() + { + InitializeComponent(); + } + + private void OnButtonClick(object sender, RoutedEventArgs e) + { + //just increment a counter - will be displayed on screen + ClickCount++; + } + } +} \ No newline at end of file diff --git a/Source/WindowsFormsSample/Form1.Designer.cs b/Source/WindowsFormsSample/Form1.Designer.cs new file mode 100644 index 0000000..eaab61d --- /dev/null +++ b/Source/WindowsFormsSample/Form1.Designer.cs @@ -0,0 +1,62 @@ +namespace WindowsFormsSample +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(32, 25); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(408, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Click on the red LED icon in the taskbar to display an interactive WPF Popup cont" + + "rol."; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(488, 264); + this.Controls.Add(this.label1); + this.Name = "Form1"; + this.Text = "Form1"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + } +} + diff --git a/Source/WindowsFormsSample/Form1.cs b/Source/WindowsFormsSample/Form1.cs new file mode 100644 index 0000000..0689ff2 --- /dev/null +++ b/Source/WindowsFormsSample/Form1.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Forms; +using Hardcodet.Wpf.TaskbarNotification; +using Samples; +using WindowsFormsSample.Properties; + +namespace WindowsFormsSample +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + TaskbarIcon tb = new TaskbarIcon(); + tb.Icon = Resources.Led; + tb.Visibility = Visibility.Visible; + + tb.TrayPopup = new FancyPopup(); + } + } +} diff --git a/Source/WindowsFormsSample/Form1.resx b/Source/WindowsFormsSample/Form1.resx new file mode 100644 index 0000000..ff31a6d --- /dev/null +++ b/Source/WindowsFormsSample/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/WindowsFormsSample/Icon/Led.ico b/Source/WindowsFormsSample/Icon/Led.ico new file mode 100644 index 0000000000000000000000000000000000000000..8a8bbafa87909fb28ea0375bf2347fa3d3768d26 GIT binary patch literal 1150 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 e_Z%*j3ugJkm?&CG8KkMMtA + /// The main entry point for the application. + ///
+ [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/Source/WindowsFormsSample/Properties/AssemblyInfo.cs b/Source/WindowsFormsSample/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b32abd5 --- /dev/null +++ b/Source/WindowsFormsSample/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WindowsFormsSample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("WindowsFormsSample")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("072bbfa0-9b8b-48df-bf88-3e4806b3e3e8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/WindowsFormsSample/Properties/Resources.Designer.cs b/Source/WindowsFormsSample/Properties/Resources.Designer.cs new file mode 100644 index 0000000..47cb61f --- /dev/null +++ b/Source/WindowsFormsSample/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3074 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsFormsSample.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowsFormsSample.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Icon Led { + get { + object obj = ResourceManager.GetObject("Led", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/Source/WindowsFormsSample/Properties/Resources.resx b/Source/WindowsFormsSample/Properties/Resources.resx new file mode 100644 index 0000000..4c8eec3 --- /dev/null +++ b/Source/WindowsFormsSample/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\icon\led.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Source/WindowsFormsSample/Properties/Settings.Designer.cs b/Source/WindowsFormsSample/Properties/Settings.Designer.cs new file mode 100644 index 0000000..12508d3 --- /dev/null +++ b/Source/WindowsFormsSample/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3074 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsFormsSample.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Source/WindowsFormsSample/Properties/Settings.settings b/Source/WindowsFormsSample/Properties/Settings.settings new file mode 100644 index 0000000..abf36c5 --- /dev/null +++ b/Source/WindowsFormsSample/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/WindowsFormsSample/WindowsFormsSample.csproj b/Source/WindowsFormsSample/WindowsFormsSample.csproj new file mode 100644 index 0000000..6e5677f --- /dev/null +++ b/Source/WindowsFormsSample/WindowsFormsSample.csproj @@ -0,0 +1,124 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8} + WinExe + Properties + WindowsFormsSample + WindowsFormsSample + v3.5 + 512 + WindowsFormsSample.Program + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + 3.0 + + + 3.0 + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + 3.0 + + + 3.0 + + + + + FancyPopup.xaml + + + Form + + + Form1.cs + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + MSBuild:Compile + Designer + + + + + + + + {7AC63864-7638-41C4-969C-D3197EF2BED9} + NotifyIconWpf + + + + + + + + \ No newline at end of file From ac2eed0a250af7aca77584490c08e1590afccf8a Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Tue, 22 Sep 2009 06:57:07 +0000 Subject: [PATCH 22/73] WPF NotifyIcon -------------- FIX Fixed typo (balloon with one "o") in comments and an even in WindowMessageSink.cs. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@120 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Changelog.txt | 2 ++ Source/NotifyIconWpf/BalloonIcon.cs | 2 +- Source/NotifyIconWpf/Interop/IconDataMembers.cs | 2 +- Source/NotifyIconWpf/Interop/WindowMessageSink.cs | 6 +++--- Source/NotifyIconWpf/TaskbarIcon.cs | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/Changelog.txt b/Source/Changelog.txt index e6c2c8e..5230200 100644 --- a/Source/Changelog.txt +++ b/Source/Changelog.txt @@ -12,6 +12,8 @@ FIX If a popup is opened, its window handle is now being set as the foreground This fixes an issue with certain controls being disabled on popups. (thanks Andrew Smith for pointing me in the right direction!). FIX Changed dispatcher access in order to work in WinForms scenarios, too. +FIX Corrected typo in WindowMessageSink.BalloonToolTipChanged event. Used internally + (although event is public), so users should be fine. ---------------------------------------------------------------------------- diff --git a/Source/NotifyIconWpf/BalloonIcon.cs b/Source/NotifyIconWpf/BalloonIcon.cs index 5c182d7..610ff57 100644 --- a/Source/NotifyIconWpf/BalloonIcon.cs +++ b/Source/NotifyIconWpf/BalloonIcon.cs @@ -25,7 +25,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { /// - /// Supported icons for the tray's ballon messages. + /// Supported icons for the tray's balloon messages. /// public enum BalloonIcon { diff --git a/Source/NotifyIconWpf/Interop/IconDataMembers.cs b/Source/NotifyIconWpf/Interop/IconDataMembers.cs index d3dd8db..be284cb 100644 --- a/Source/NotifyIconWpf/Interop/IconDataMembers.cs +++ b/Source/NotifyIconWpf/Interop/IconDataMembers.cs @@ -29,7 +29,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop ///
State = 0x08, /// - /// The ballon ToolTip is set. Accordingly, the following + /// The balloon ToolTip is set. Accordingly, the following /// members are set: , /// , , /// and . diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 1653525..3cf4ee2 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -101,7 +101,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// Fired if a balloon ToolTip was either displayed /// or closed (indicated by the boolean flag). /// - public event Action BallonToolTipChanged; + public event Action BalloonToolTipChanged; /// /// Fired if the taskbar was created or restarted. Requires the taskbar @@ -278,12 +278,12 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop break; case 0x402: - BallonToolTipChanged(true); + BalloonToolTipChanged(true); break; case 0x403: case 0x404: - BallonToolTipChanged(false); + BalloonToolTipChanged(false); break; case 0x405: diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 866dbfb..4d9169a 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -135,7 +135,7 @@ namespace Hardcodet.Wpf.TaskbarNotification messageSink.MouseEventReceived += OnMouseEvent; messageSink.TaskbarCreated += OnTaskbarCreated; messageSink.ChangeToolTipStateRequest += OnToolTipChange; - messageSink.BallonToolTipChanged += OnBalloonToolTipChanged; + messageSink.BalloonToolTipChanged += OnBalloonToolTipChanged; //init single click / balloon timers singleClickTimer = new Timer(DoSingleClickAction); From 2a4cf8de7ed6130533de082a87f93c874f20819e Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Tue, 22 Sep 2009 07:48:22 +0000 Subject: [PATCH 23/73] WPF NotifyIcon -------------- FIX Dispose only deregisters OnExit event listenter if there is actually an application (not the case in WinForms environments). CHG Added dispose to WinForms sample which closes the NotifyIcon. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@121 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Changelog.txt | 6 ++++-- Source/NotifyIconWpf/TaskbarIcon.cs | 5 ++++- Source/WindowsFormsSample/Form1.cs | 19 +++++++++++++++---- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Source/Changelog.txt b/Source/Changelog.txt index 5230200..e63696e 100644 --- a/Source/Changelog.txt +++ b/Source/Changelog.txt @@ -12,8 +12,10 @@ FIX If a popup is opened, its window handle is now being set as the foreground This fixes an issue with certain controls being disabled on popups. (thanks Andrew Smith for pointing me in the right direction!). FIX Changed dispatcher access in order to work in WinForms scenarios, too. -FIX Corrected typo in WindowMessageSink.BalloonToolTipChanged event. Used internally - (although event is public), so users should be fine. +FIX Corrected typo in WindowMessageSink.BalloonToolTipChanged event (thanks Mertsch). + Used internally (although event is public), so this shouldn't be a breaking change. +FIX Dispose only deregisters OnExit event listenter if there is actually an + application (not the case in WinForms environments). ---------------------------------------------------------------------------- diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 4d9169a..787bb1e 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -994,7 +994,10 @@ namespace Hardcodet.Wpf.TaskbarNotification IsDisposed = true; //deregister application event listener - Application.Current.Exit -= OnExit; + if (Application.Current != null) + { + Application.Current.Exit -= OnExit; + } //stop timers singleClickTimer.Dispose(); diff --git a/Source/WindowsFormsSample/Form1.cs b/Source/WindowsFormsSample/Form1.cs index 0689ff2..93a7e2d 100644 --- a/Source/WindowsFormsSample/Form1.cs +++ b/Source/WindowsFormsSample/Form1.cs @@ -15,6 +15,8 @@ namespace WindowsFormsSample { public partial class Form1 : Form { + private TaskbarIcon notifyIcon; + public Form1() { InitializeComponent(); @@ -23,11 +25,20 @@ namespace WindowsFormsSample protected override void OnLoad(EventArgs e) { base.OnLoad(e); - TaskbarIcon tb = new TaskbarIcon(); - tb.Icon = Resources.Led; - tb.Visibility = Visibility.Visible; + notifyIcon = new TaskbarIcon(); + notifyIcon.Icon = Resources.Led; + notifyIcon.ToolTipText = "Left-click to open popup"; + notifyIcon.Visibility = Visibility.Visible; - tb.TrayPopup = new FancyPopup(); + notifyIcon.TrayPopup = new FancyPopup(); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + + //close the notify icon + notifyIcon.Dispose(); } } } From b9dc9c4a1b12bb1e4271bb3748224e6932558938 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Tue, 6 Oct 2009 12:37:33 +0000 Subject: [PATCH 24/73] WPF NotifyIcon -------------- ADD Added cleanup file for deployment. CHG Improved comments to context menu placement - could not remember why I did this in the first place. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@124 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Cleanup_Solution_For_Deployment.bat | 20 ++++++++++++++++++++ Source/NotifyIconWpf/TaskbarIcon.cs | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 Source/Cleanup_Solution_For_Deployment.bat diff --git a/Source/Cleanup_Solution_For_Deployment.bat b/Source/Cleanup_Solution_For_Deployment.bat new file mode 100644 index 0000000..1f49792 --- /dev/null +++ b/Source/Cleanup_Solution_For_Deployment.bat @@ -0,0 +1,20 @@ +del /s /ah /f *.suo +del /s /f *.user +del /s /f *.cache +del /s /f *.scc +del /s /f *.vssscc +del /s /f *.vspscc +del /s /f *.keep +del /s /ah /f vssver2.scc + +rd /s /q bin obj ClientBin _Resharper.* _Upgrade* + +del dirs.txt +dir /s /b /ad bin > dirs.txt +dir /s /b /ad obj >> dirs.txt +dir /s /b /ad ClientBin >> dirs.txt +dir /s /b /ad _Resharper.* >> dirs.txt +dir /s /b /ad _Upgrade* >> dirs.txt + +for /f "delims=;" %%i in (dirs.txt) DO rd /s /q "%%i" +del dirs.txt diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 787bb1e..78b5b8b 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -681,7 +681,9 @@ namespace Hardcodet.Wpf.TaskbarNotification if (ContextMenu != null) { - //use absolute position + //use absolute positioning. We need to set the coordinates, or a delayed opening + //(e.g. when left-clicked) opens the context menu at the wrong place if the mouse + //is moved! ContextMenu.Placement = PlacementMode.AbsolutePoint; ContextMenu.HorizontalOffset = cursorPosition.X; ContextMenu.VerticalOffset = cursorPosition.Y; From b6a45901145d4353922a919dba05cc89fcbacb15 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Tue, 19 Jan 2010 13:46:20 +0000 Subject: [PATCH 25/73] WPF NotifyIcon -------------- CHG Removed version number in label of showcase window (not needed, required update with every release). git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@141 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Sample Project/Showcase/ShowcaseWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Sample Project/Showcase/ShowcaseWindow.xaml b/Source/Sample Project/Showcase/ShowcaseWindow.xaml index 279f917..c478954 100644 --- a/Source/Sample Project/Showcase/ShowcaseWindow.xaml +++ b/Source/Sample Project/Showcase/ShowcaseWindow.xaml @@ -396,7 +396,7 @@ FontWeight="Bold" FontSize="16" HorizontalAlignment="Left"> + Text="WPF NotifyIcon" /> Date: Sat, 16 Nov 2013 17:50:03 +0000 Subject: [PATCH 26/73] git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@170 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/Interop/NotifyIconData.cs | 3 +-- Source/NotifyIconWpf/Interop/WindowMessageSink.cs | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/NotifyIconWpf/Interop/NotifyIconData.cs b/Source/NotifyIconWpf/Interop/NotifyIconData.cs index 78cc5a6..81cf0a6 100644 --- a/Source/NotifyIconWpf/Interop/NotifyIconData.cs +++ b/Source/NotifyIconWpf/Interop/NotifyIconData.cs @@ -1,5 +1,4 @@ using System; -using System.Drawing; using System.Runtime.InteropServices; namespace Hardcodet.Wpf.TaskbarNotification.Interop @@ -48,7 +47,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// /// A handle to the icon that should be displayed. Just - /// . + /// Icon.Handle. /// public IntPtr IconHandle; diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 3cf4ee2..3c696f9 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -26,6 +26,7 @@ using System; using System.ComponentModel; using System.Diagnostics; +using System.Runtime.InteropServices; namespace Hardcodet.Wpf.TaskbarNotification.Interop { @@ -190,7 +191,11 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop if (MessageWindowHandle == IntPtr.Zero) { +#if SILVERLIGHT + throw new Exception("Message window handle was not a valid pointer."); +#else throw new Win32Exception(); +#endif } } From cad08add0c23e2bd81d15888d32b096d0ed4789e Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 19:31:26 +0000 Subject: [PATCH 27/73] FIX Supporting x64 for .NET and above (NTFY-1) git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@171 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/Interop/WinApi.cs | 6 +++--- Source/NotifyIconWpf/Interop/WindowClass.cs | 2 +- Source/NotifyIconWpf/Interop/WindowMessageSink.cs | 13 ++++++------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Source/NotifyIconWpf/Interop/WinApi.cs b/Source/NotifyIconWpf/Interop/WinApi.cs index e0d61ba..2cb96ea 100644 --- a/Source/NotifyIconWpf/Interop/WinApi.cs +++ b/Source/NotifyIconWpf/Interop/WinApi.cs @@ -21,15 +21,15 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop [DllImport("USER32.DLL", EntryPoint = "CreateWindowExW", SetLastError = true)] public static extern IntPtr CreateWindowEx(int dwExStyle, [MarshalAs(UnmanagedType.LPWStr)] string lpClassName, [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, int dwStyle, int x, int y, - int nWidth, int nHeight, uint hWndParent, int hMenu, int hInstance, - int lpParam); + int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, + IntPtr lpParam); /// /// Processes a default windows procedure. /// [DllImport("USER32.DLL")] - public static extern long DefWindowProc(IntPtr hWnd, uint msg, uint wparam, uint lparam); + public static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wparam, IntPtr lparam); /// /// Registers the helper window class. diff --git a/Source/NotifyIconWpf/Interop/WindowClass.cs b/Source/NotifyIconWpf/Interop/WindowClass.cs index e4f625a..bfc42f7 100644 --- a/Source/NotifyIconWpf/Interop/WindowClass.cs +++ b/Source/NotifyIconWpf/Interop/WindowClass.cs @@ -7,7 +7,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// Callback delegate which is used by the Windows API to /// submit window messages. /// - public delegate long WindowProcedureHandler(IntPtr hwnd, uint uMsg, uint wparam, uint lparam); + public delegate IntPtr WindowProcedureHandler(IntPtr hwnd, uint uMsg, IntPtr wparam, IntPtr lparam); /// diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 3c696f9..42fd3a9 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -187,14 +187,14 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop taskbarRestartMessageId = WinApi.RegisterWindowMessage("TaskbarCreated"); // Create the message window - MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, 0, 0, 0, 0); + MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (MessageWindowHandle == IntPtr.Zero) { #if SILVERLIGHT throw new Exception("Message window handle was not a valid pointer."); #else - throw new Win32Exception(); + throw new Win32Exception("Message window handle was not a valid pointer"); #endif } } @@ -207,7 +207,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// /// Callback method that receives messages from the taskbar area. /// - private long OnWindowMessageReceived(IntPtr hwnd, uint messageId, uint wparam, uint lparam) + private IntPtr OnWindowMessageReceived(IntPtr hwnd, uint messageId, IntPtr wparam, IntPtr lparam) { if (messageId == taskbarRestartMessageId) { @@ -231,15 +231,14 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// or higher, this parameter can be used to resolve mouse coordinates. /// Currently not in use. /// Provides information about the event. - private void ProcessWindowMessage(uint msg, uint wParam, uint lParam) + private void ProcessWindowMessage(uint msg, IntPtr wParam, IntPtr lParam) { if (msg != CallbackMessageId) return; - switch (lParam) + switch (lParam.ToInt32()) { case 0x200: - MouseEventReceived(MouseEvent.MouseMove); - break; + MouseEventReceived(MouseEvent.MouseMove); break; case 0x201: MouseEventReceived(MouseEvent.IconLeftMouseDown); From b4ae746d1c4af3c6a147a86717fb6d6f6101bfd4 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 19:42:54 +0000 Subject: [PATCH 28/73] CHG If setting the taskbar doesn't work, the control just retries again (and again) rather than throwing an exception. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@172 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 78b5b8b..5b9df1a 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -26,7 +26,9 @@ using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing; +using System.Runtime.Remoting.Channels; using System.Threading; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -878,7 +880,15 @@ namespace Hardcodet.Wpf.TaskbarNotification var status = Util.WriteIconData(ref iconData, NotifyCommand.Add, members); if (!status) { - throw new Win32Exception("Could not create icon data"); + //couldn't create the icon - we can assume this is because explorer is not running (yet!) + //-> try a bit later again rather than throwing an exception. Typically, if the windows + // shell is being loaded later, this method is being reinvoked from OnTaskbarCreated + Task.Factory.StartNew(() => + { + Thread.Sleep(1000); + CreateTaskbarIcon(); + }); + return; } //set to most recent version From 2076f8fa0b97011412b1d917f9e513c3d8ff29d7 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 19:46:49 +0000 Subject: [PATCH 29/73] CHG If setting the taskbar doesn't work, the control just retries again (and again) rather than throwing an exception. NTFY-6 git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@173 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 5b9df1a..b635119 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -883,11 +883,7 @@ namespace Hardcodet.Wpf.TaskbarNotification //couldn't create the icon - we can assume this is because explorer is not running (yet!) //-> try a bit later again rather than throwing an exception. Typically, if the windows // shell is being loaded later, this method is being reinvoked from OnTaskbarCreated - Task.Factory.StartNew(() => - { - Thread.Sleep(1000); - CreateTaskbarIcon(); - }); + // (we could also retry after a delay, but that's currently YAGNI) return; } @@ -900,7 +896,6 @@ namespace Hardcodet.Wpf.TaskbarNotification } } - /// /// Closes the taskbar icon if required. /// @@ -908,6 +903,8 @@ namespace Hardcodet.Wpf.TaskbarNotification { lock (this) { + //make sure we didn't schedule a creation + if (IsTaskbarIconCreated) { Util.WriteIconData(ref iconData, NotifyCommand.Delete, IconDataMembers.Message); From f534bbc773e8faf6c152515b8084fe023f408706 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 19:55:51 +0000 Subject: [PATCH 30/73] CHG NotifyIcon is not only removed on user-initiated disposal, but also garbage collection (NTFY-5). git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@174 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/Interop/WindowMessageSink.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 42fd3a9..4aabdef 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -361,9 +361,10 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop private void Dispose(bool disposing) { //don't do anything if the component is already disposed - if (IsDisposed || !disposing) return; + if (IsDisposed) return; IsDisposed = true; + //always destroy the unmanaged handle (even if called from the GC) WinApi.DestroyWindow(MessageWindowHandle); messageHandler = null; } From 24bbec3a45d4368bdc1c5c172ea62f3f54be82c3 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 20:55:36 +0000 Subject: [PATCH 31/73] CHG The attached TaskBarIcon DP is derived now, so binding doesn't have to go through the parent element anymore (NTFY-18). git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@175 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.Declarations.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index a5f4128..8d6e3e0 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -1818,10 +1818,14 @@ namespace Hardcodet.Wpf.TaskbarNotification #region ParentTaskbarIcon /// - /// An attached property that is assigned to + /// An attached property that is assigned to displayed UI elements (balloos, tooltips, context menus), and + /// that can be used to bind to this control. The attached property is being derived, so binding is + /// quite straightforward: + /// /// public static readonly DependencyProperty ParentTaskbarIconProperty = - DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof (TaskbarIcon), typeof (TaskbarIcon)); + DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof (TaskbarIcon), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); /// /// Gets the ParentTaskbarIcon property. This dependency property From e7904ade5290158ec2b7ab40acf52215205758d3 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 20:56:12 +0000 Subject: [PATCH 32/73] CHG The attached TaskBarIcon DP is derived now, so binding doesn't have to go through the parent element anymore (NTFY-18). git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@176 9f600761-6f11-4665-b6dc-0185e9171623 --- .../08 - DataBinding/DataBoundToolTipWindow.xaml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml index 1fec7a4..b412102 100644 --- a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml +++ b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml @@ -36,17 +36,17 @@ - + - + From 62dc5772958c99daf87456063b0fd34463b7b771 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 20:58:58 +0000 Subject: [PATCH 33/73] Added binding sample to code comments (NTFY-18) git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@177 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.Declarations.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 8d6e3e0..6d3a23d 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -1821,7 +1821,9 @@ namespace Hardcodet.Wpf.TaskbarNotification /// An attached property that is assigned to displayed UI elements (balloos, tooltips, context menus), and /// that can be used to bind to this control. The attached property is being derived, so binding is /// quite straightforward: - /// + /// + /// + /// /// public static readonly DependencyProperty ParentTaskbarIconProperty = DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof (TaskbarIcon), typeof (TaskbarIcon), From d2abe5238b4666ecc1e29d10432d21e68f612f11 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 21:05:20 +0000 Subject: [PATCH 34/73] Improved inline documentation. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@178 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Sample Project/Showcase/FancyBalloon.xaml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Sample Project/Showcase/FancyBalloon.xaml.cs b/Source/Sample Project/Showcase/FancyBalloon.xaml.cs index 78a6291..460a82a 100644 --- a/Source/Sample Project/Showcase/FancyBalloon.xaml.cs +++ b/Source/Sample Project/Showcase/FancyBalloon.xaml.cs @@ -59,11 +59,11 @@ namespace Samples /// /// By subscribing to the /// and setting the "Handled" property to true, we suppress the popup - /// from being closed in order to display the fade-out animation. + /// from being closed in order to display the custom fade-out animation. /// private void OnBalloonClosing(object sender, RoutedEventArgs e) { - e.Handled = true; + e.Handled = true; //suppresses the popup from being closed immediately isClosing = true; } From 008ea6ab2c95e29bf9049c9d412a16a174e5ad9d Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 16 Nov 2013 21:37:36 +0000 Subject: [PATCH 35/73] CHG If a popup is being reused, but still has a parent, throw custom exception with more descriptive error message. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@179 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.cs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index b635119..1fde567 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -23,12 +23,9 @@ using System; -using System.ComponentModel; using System.Diagnostics; using System.Drawing; -using System.Runtime.Remoting.Channels; using System.Threading; -using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -199,8 +196,23 @@ namespace Hardcodet.Wpf.TaskbarNotification //events or override popup.PopupAnimation = animation; - popup.Child = balloon; + //in case the balloon is cleaned up through routed events, the + //control didn't removed the balloon from its parent popup when + //if was closed the last time - just make sure it doesn't have + //a parent that is a popup + var parent = LogicalTreeHelper.GetParent(balloon) as Popup; + if (parent != null) parent.Child = null; + if (parent != null) + { + string msg = + "Cannot display control [{0}] in a new balloon popup - that control already has a parent. You may consider creating new balloons every time you want to show one."; + msg = String.Format(msg, balloon); + throw new InvalidOperationException(msg); + } + + popup.Child = balloon; + //don't set the PlacementTarget as it causes the popup to become hidden if the //TaskbarIcon's parent is hidden, too... //popup.PlacementTarget = this; @@ -291,6 +303,10 @@ namespace Hardcodet.Wpf.TaskbarNotification //close the popup popup.IsOpen = false; + //remove the reference of the popup to the balloon in case we want to reuse + //the balloon (then added to a new popup) + popup.Child = null; + //reset attached property if (element != null) SetParentTaskbarIcon(element, null); } From c261d99378118fc741e7f4ebc3e9c9af47ca4c90 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 17 Nov 2013 13:07:50 +0000 Subject: [PATCH 36/73] Reformatted XAML. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@180 9f600761-6f11-4665-b6dc-0185e9171623 --- .../Sample Project/Showcase/FancyBalloon.xaml | 272 ++++++++++-------- 1 file changed, 156 insertions(+), 116 deletions(-) diff --git a/Source/Sample Project/Showcase/FancyBalloon.xaml b/Source/Sample Project/Showcase/FancyBalloon.xaml index c0d58ba..5d2e60d 100644 --- a/Source/Sample Project/Showcase/FancyBalloon.xaml +++ b/Source/Sample Project/Showcase/FancyBalloon.xaml @@ -1,118 +1,158 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + From 6d505b158086c590c7611daae3a38faefd2d7a54 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 17 Nov 2013 14:17:40 +0000 Subject: [PATCH 37/73] CHG Added missing designer attributes to some properties. Reformatted code. (NTFY-21) git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@181 9f600761-6f11-4665-b6dc-0185e9171623 --- .../NotifyIconWpf/TaskbarIcon.Declarations.cs | 3677 +++++++++-------- 1 file changed, 1841 insertions(+), 1836 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 6d3a23d..2956ce4 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -22,7 +22,6 @@ // THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE - using System; using System.ComponentModel; using System.Drawing; @@ -35,1841 +34,1847 @@ using Hardcodet.Wpf.TaskbarNotification.Interop; namespace Hardcodet.Wpf.TaskbarNotification { - /// - /// Contains declarations of WPF dependency properties - /// and events. - /// - partial class TaskbarIcon - { /// - /// Category name that is set on designer properties. - /// - public const string CategoryName = "NotifyIcon"; - - - //POPUP CONTROLS - - #region TrayPopupResolved - - /// - /// TrayPopupResolved Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey TrayPopupResolvedPropertyKey - = DependencyProperty.RegisterReadOnly("TrayPopupResolved", typeof(Popup), typeof(TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - - /// - /// A read-only dependency property that returns the - /// that is being displayed in the taskbar area based on a user action. - /// - public static readonly DependencyProperty TrayPopupResolvedProperty - = TrayPopupResolvedPropertyKey.DependencyProperty; - - /// - /// Gets the TrayPopupResolved property. Returns - /// a which is either the - /// control itself or a - /// control that contains the - /// . - /// - [Category(CategoryName)] - public Popup TrayPopupResolved - { - get { return (Popup)GetValue(TrayPopupResolvedProperty); } - } - - /// - /// Provides a secure method for setting the TrayPopupResolved property. - /// This dependency property indicates .... - /// - /// The new value for the property. - protected void SetTrayPopupResolved(Popup value) - { - SetValue(TrayPopupResolvedPropertyKey, value); - } - - #endregion - - #region TrayToolTipResolved - - /// - /// TrayToolTipResolved Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey TrayToolTipResolvedPropertyKey - = DependencyProperty.RegisterReadOnly("TrayToolTipResolved", typeof(ToolTip), typeof(TaskbarIcon), - new FrameworkPropertyMetadata(null )); - - - /// - /// A read-only dependency property that returns the - /// that is being displayed. - /// - public static readonly DependencyProperty TrayToolTipResolvedProperty - = TrayToolTipResolvedPropertyKey.DependencyProperty; - - /// - /// Gets the TrayToolTipResolved property. Returns - /// a control that was created - /// in order to display either - /// or . - /// - [Category(CategoryName)] - [Browsable(true)] - [Bindable(true)] - public ToolTip TrayToolTipResolved - { - get { return (ToolTip)GetValue(TrayToolTipResolvedProperty); } - } - - /// - /// Provides a secure method for setting the - /// property. - /// - /// The new value for the property. - protected void SetTrayToolTipResolved(ToolTip value) - { - SetValue(TrayToolTipResolvedPropertyKey, value); - } - - #endregion - - #region CustomBalloon - - /// - /// CustomBalloon Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey CustomBalloonPropertyKey - = DependencyProperty.RegisterReadOnly("CustomBalloon", typeof(Popup), typeof(TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - public static readonly DependencyProperty CustomBalloonProperty - = CustomBalloonPropertyKey.DependencyProperty; - - /// - /// A custom popup that is being displayed in the tray area in order - /// to display messages to the user. - /// - public Popup CustomBalloon - { - get { return (Popup)GetValue(CustomBalloonProperty); } - } - - /// - /// Provides a secure method for setting the property. - /// - /// The new value for the property. - protected void SetCustomBalloon(Popup value) - { - SetValue(CustomBalloonPropertyKey, value); - } - - #endregion - - - - //DEPENDENCY PROPERTIES - - #region Icon property / IconSource dependency property - - private Icon icon; - - /// - /// Gets or sets the icon to be displayed. This is not a - /// dependency property - if you want to assign the property - /// through XAML, please use the - /// dependency property. - /// - [Browsable(false)] - public Icon Icon - { - get { return icon; } - set - { - icon = value; - iconData.IconHandle = value == null ? IntPtr.Zero : icon.Handle; - - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Icon); - } - } - - - /// - /// Resolves an image source and updates the property accordingly. - /// - public static readonly DependencyProperty IconSourceProperty = - DependencyProperty.Register("IconSource", - typeof(ImageSource), - typeof(TaskbarIcon), - new FrameworkPropertyMetadata(null, IconSourcePropertyChanged)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Resolves an image source and updates the property accordingly. - ///
- [Category(CategoryName)] - [Description("Sets the displayed taskbar icon.")] - public ImageSource IconSource - { - get { return (ImageSource)GetValue(IconSourceProperty); } - set { SetValue(IconSourceProperty, value); } - } - - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon)d; - owner.OnIconSourcePropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e) - { - ImageSource newValue = (ImageSource)e.NewValue; - - //resolving the ImageSource at design time is unlikely to work - if (!Util.IsDesignMode) Icon = newValue.ToIcon(); - } - - #endregion - - #region ToolTipText dependency property - - /// - /// A tooltip text that is being displayed if no custom - /// was set or if custom tooltips are not supported. - /// - public static readonly DependencyProperty ToolTipTextProperty = - DependencyProperty.Register("ToolTipText", - typeof (string), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(String.Empty, ToolTipTextPropertyChanged)); - - - /// - /// A property wrapper for the - /// dependency property:
- /// A tooltip text that is being displayed if no custom - /// was set or if custom tooltips are not supported. - ///
- [Category(CategoryName)] - [Description("Alternative to a fully blown ToolTip, which is only displayed on Vista and above.")] - public string ToolTipText - { - get { return (string) GetValue(ToolTipTextProperty); } - set { SetValue(ToolTipTextProperty, value); } - } - - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnToolTipTextPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e) - { - //only recreate tooltip if we're not using a custom control - if (TrayToolTipResolved == null || TrayToolTipResolved.Content is string) - { - CreateCustomToolTip(); - } - - WriteToolTipSettings(); - } - - #endregion - - #region TrayToolTip dependency property - - /// - /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. - /// Works only with Vista and above. Accordingly, you should make sure that - /// the property is set as well. - /// - public static readonly DependencyProperty TrayToolTipProperty = - DependencyProperty.Register("TrayToolTip", - typeof (UIElement), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null, TrayToolTipPropertyChanged)); - - /// - /// A property wrapper for the - /// dependency property:
- /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. - /// Works only with Vista and above. Accordingly, you should make sure that - /// the property is set as well. - ///
- [Category(CategoryName)] - [Description("Custom UI element that is displayed as a tooltip. Only on Vista and above")] - public UIElement TrayToolTip - { - get { return (UIElement) GetValue(TrayToolTipProperty); } - set { SetValue(TrayToolTipProperty, value); } - } - - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void TrayToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnTrayToolTipPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnTrayToolTipPropertyChanged(DependencyPropertyChangedEventArgs e) - { - //recreate tooltip control - CreateCustomToolTip(); - - if (e.OldValue != null) - { - //remove the taskbar icon reference from the previously used element - SetParentTaskbarIcon((DependencyObject) e.OldValue, null); - } - - - if (e.NewValue != null) - { - //set this taskbar icon as a reference to the new tooltip element - SetParentTaskbarIcon((DependencyObject) e.NewValue, this); - } - - - //update tooltip settings - needed to make sure a string is set, even - //if the ToolTipText property is not set. Otherwise, the event that - //triggers tooltip display is never fired. - WriteToolTipSettings(); - } - - #endregion - - #region TrayPopup dependency property - - /// - /// A control that is displayed as a popup when the taskbar icon is clicked. - /// - public static readonly DependencyProperty TrayPopupProperty = - DependencyProperty.Register("TrayPopup", - typeof(UIElement), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null, TrayPopupPropertyChanged)); - - /// - /// A property wrapper for the - /// dependency property:
- /// A control that is displayed as a popup when the taskbar icon is clicked. - ///
- [Category(CategoryName)] - [Description("Displayed as a Popup if the user clicks on the taskbar icon.")] - public UIElement TrayPopup - { - get { return (UIElement)GetValue(TrayPopupProperty); } - set { SetValue(TrayPopupProperty, value); } - } - - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void TrayPopupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnTrayPopupPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnTrayPopupPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - { - //remove the taskbar icon reference from the previously used element - SetParentTaskbarIcon((DependencyObject)e.OldValue, null); - } - - - if (e.NewValue != null) - { - //set this taskbar icon as a reference to the new tooltip element - SetParentTaskbarIcon((DependencyObject)e.NewValue, this); - } - - //create a pop - CreatePopup(); - } - - #endregion - - - #region MenuActivation dependency property - - /// - /// Defines what mouse events display the context menu. - /// Defaults to . - /// - public static readonly DependencyProperty MenuActivationProperty = - DependencyProperty.Register("MenuActivation", - typeof (PopupActivationMode), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(PopupActivationMode.RightClick)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Defines what mouse events display the context menu. - /// Defaults to . - ///
- [Category(CategoryName)] - [Description("Defines what mouse events display the context menu.")] - public PopupActivationMode MenuActivation - { - get { return (PopupActivationMode) GetValue(MenuActivationProperty); } - set { SetValue(MenuActivationProperty, value); } - } - - #endregion - - #region PopupActivation dependency property - - /// - /// Defines what mouse events trigger the . - /// Default is . - /// - public static readonly DependencyProperty PopupActivationProperty = - DependencyProperty.Register("PopupActivation", - typeof (PopupActivationMode), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(PopupActivationMode.LeftClick)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Defines what mouse events trigger the . - /// Default is . - ///
- [Category(CategoryName)] - [Description("Defines what mouse events display the TaskbarIconPopup.")] - public PopupActivationMode PopupActivation - { - get { return (PopupActivationMode) GetValue(PopupActivationProperty); } - set { SetValue(PopupActivationProperty, value); } - } - - #endregion - - - #region Visibility dependency property override - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnVisibilityPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnVisibilityPropertyChanged(DependencyPropertyChangedEventArgs e) - { - Visibility newValue = (Visibility) e.NewValue; - - //update - if (newValue == Visibility.Visible) - { - CreateTaskbarIcon(); - } - else - { - RemoveTaskbarIcon(); - } - } - - #endregion - - #region DataContext dependency property override / target update - - /// - /// Updates the of a given - /// . This method only updates target elements - /// that do not already have a data context of their own, and either assigns - /// the of the NotifyIcon, or the - /// NotifyIcon itself, if no data context was assigned at all. - /// - private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue) - { - //if there is no target or it's data context is determined through a binding - //of its own, keep it - if (target == null || target.IsDataContextDataBound()) return; - - //if the target's data context is the NotifyIcon's old DataContext or the NotifyIcon itself, - //update it - if (ReferenceEquals(this, target.DataContext) || Equals(oldDataContextValue, target.DataContext)) - { - //assign own data context, if available. If there is no data - //context at all, assign NotifyIcon itself. - target.DataContext = newDataContextValue ?? this; - } - } - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnDataContextPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// Provides information about the updated property. - private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e) - { - object newValue = e.NewValue; - object oldValue = e.OldValue; - - //replace custom data context for ToolTips, Popup, and - //ContextMenu - UpdateDataContext(TrayPopupResolved, oldValue, newValue); - UpdateDataContext(TrayToolTipResolved, oldValue, newValue); - UpdateDataContext(ContextMenu, oldValue, newValue); - } - - #endregion - - #region ContextMenu dependency property override - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon)d; - owner.OnContextMenuPropertyChanged(e); - } - - - /// - /// Releases the old and updates the new property - /// in order to reflect both the NotifyIcon's - /// property and have the assigned. - /// - /// Provides information about the updated property. - private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - { - //remove the taskbar icon reference from the previously used element - SetParentTaskbarIcon((DependencyObject)e.OldValue, null); - } - - if (e.NewValue != null) - { - //set this taskbar icon as a reference to the new tooltip element - SetParentTaskbarIcon((DependencyObject)e.NewValue, this); - } - - UpdateDataContext((ContextMenu) e.NewValue, null, DataContext); - } - - #endregion - - - - #region DoubleClickCommand dependency property - - /// - /// Associates a command that is being executed if the tray icon is being - /// double clicked. - /// - public static readonly DependencyProperty DoubleClickCommandProperty = - DependencyProperty.Register("DoubleClickCommand", - typeof (ICommand), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Associates a command that is being executed if the tray icon is being - /// double clicked. - ///
- public ICommand DoubleClickCommand - { - get { return (ICommand) GetValue(DoubleClickCommandProperty); } - set { SetValue(DoubleClickCommandProperty, value); } - } - - #endregion - - #region DoubleClickCommandParameter dependency property - - /// - /// Command parameter for the . - /// - public static readonly DependencyProperty DoubleClickCommandParameterProperty = - DependencyProperty.Register("DoubleClickCommandParameter", - typeof (object), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Command parameter for the . - ///
- public object DoubleClickCommandParameter - { - get { return GetValue(DoubleClickCommandParameterProperty); } - set { SetValue(DoubleClickCommandParameterProperty, value); } - } - - #endregion - - #region DoubleClickCommandTarget dependency property - - /// - /// The target of the command that is fired if the notify icon is double clicked. - /// - public static readonly DependencyProperty DoubleClickCommandTargetProperty = - DependencyProperty.Register("DoubleClickCommandTarget", - typeof (IInputElement), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// The target of the command that is fired if the notify icon is double clicked. - ///
- public IInputElement DoubleClickCommandTarget - { - get { return (IInputElement) GetValue(DoubleClickCommandTargetProperty); } - set { SetValue(DoubleClickCommandTargetProperty, value); } - } - - #endregion - - - - #region LeftClickCommand dependency property - - /// - /// Associates a command that is being executed if the tray icon is being - /// double clicked. - /// - public static readonly DependencyProperty LeftClickCommandProperty = - DependencyProperty.Register("LeftClickCommand", - typeof (ICommand), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Associates a command that is being executed if the tray icon is being - /// double clicked. - ///
- public ICommand LeftClickCommand - { - get { return (ICommand) GetValue(LeftClickCommandProperty); } - set { SetValue(LeftClickCommandProperty, value); } - } - - #endregion - - #region LeftClickCommandParameter dependency property - - /// - /// Command parameter for the . - /// - public static readonly DependencyProperty LeftClickCommandParameterProperty = - DependencyProperty.Register("LeftClickCommandParameter", - typeof (object), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Command parameter for the . - ///
- public object LeftClickCommandParameter - { - get { return GetValue(LeftClickCommandParameterProperty); } - set { SetValue(LeftClickCommandParameterProperty, value); } - } - - #endregion - - #region LeftClickCommandTarget dependency property - - /// - /// The target of the command that is fired if the notify icon is clicked. - /// - public static readonly DependencyProperty LeftClickCommandTargetProperty = - DependencyProperty.Register("LeftClickCommandTarget", - typeof (IInputElement), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// The target of the command that is fired if the notify icon is clicked. - ///
- public IInputElement LeftClickCommandTarget - { - get { return (IInputElement) GetValue(LeftClickCommandTargetProperty); } - set { SetValue(LeftClickCommandTargetProperty, value); } - } - - #endregion - - - - //EVENTS - - #region TrayLeftMouseDown - - /// - /// TrayLeftMouseDown Routed Event - /// - public static readonly RoutedEvent TrayLeftMouseDownEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseDown", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the user presses the left mouse button. - /// - [Category(CategoryName)] - public event RoutedEventHandler TrayLeftMouseDown - { - add { AddHandler(TrayLeftMouseDownEvent, value); } - remove { RemoveHandler(TrayLeftMouseDownEvent, value); } - } - - /// - /// A helper method to raise the TrayLeftMouseDown event. - /// - protected RoutedEventArgs RaiseTrayLeftMouseDownEvent() - { - RoutedEventArgs args = RaiseTrayLeftMouseDownEvent(this); - return args; - } - - /// - /// A static helper method to raise the TrayLeftMouseDown event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayLeftMouseDownEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayLeftMouseDownEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayRightMouseDown - - /// - /// TrayRightMouseDown Routed Event - /// - public static readonly RoutedEvent TrayRightMouseDownEvent = EventManager.RegisterRoutedEvent("TrayRightMouseDown", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the presses the right mouse button. - /// - public event RoutedEventHandler TrayRightMouseDown - { - add { AddHandler(TrayRightMouseDownEvent, value); } - remove { RemoveHandler(TrayRightMouseDownEvent, value); } - } - - /// - /// A helper method to raise the TrayRightMouseDown event. - /// - protected RoutedEventArgs RaiseTrayRightMouseDownEvent() - { - return RaiseTrayRightMouseDownEvent(this); - } - - /// - /// A static helper method to raise the TrayRightMouseDown event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayRightMouseDownEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayRightMouseDownEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayMiddleMouseDown - - /// - /// TrayMiddleMouseDown Routed Event - /// - public static readonly RoutedEvent TrayMiddleMouseDownEvent = EventManager.RegisterRoutedEvent("TrayMiddleMouseDown", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the user presses the middle mouse button. - /// - public event RoutedEventHandler TrayMiddleMouseDown - { - add { AddHandler(TrayMiddleMouseDownEvent, value); } - remove { RemoveHandler(TrayMiddleMouseDownEvent, value); } - } - - /// - /// A helper method to raise the TrayMiddleMouseDown event. - /// - protected RoutedEventArgs RaiseTrayMiddleMouseDownEvent() - { - return RaiseTrayMiddleMouseDownEvent(this); - } - - /// - /// A static helper method to raise the TrayMiddleMouseDown event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayMiddleMouseDownEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayMiddleMouseDownEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - - #region TrayLeftMouseUp - - /// - /// TrayLeftMouseUp Routed Event - /// - public static readonly RoutedEvent TrayLeftMouseUpEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseUp", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the user releases the left mouse button. - /// - public event RoutedEventHandler TrayLeftMouseUp - { - add { AddHandler(TrayLeftMouseUpEvent, value); } - remove { RemoveHandler(TrayLeftMouseUpEvent, value); } - } - - /// - /// A helper method to raise the TrayLeftMouseUp event. - /// - protected RoutedEventArgs RaiseTrayLeftMouseUpEvent() - { - return RaiseTrayLeftMouseUpEvent(this); - } - - /// - /// A static helper method to raise the TrayLeftMouseUp event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayLeftMouseUpEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayLeftMouseUpEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayRightMouseUp - - /// - /// TrayRightMouseUp Routed Event - /// - public static readonly RoutedEvent TrayRightMouseUpEvent = EventManager.RegisterRoutedEvent("TrayRightMouseUp", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the user releases the right mouse button. - /// - public event RoutedEventHandler TrayRightMouseUp - { - add { AddHandler(TrayRightMouseUpEvent, value); } - remove { RemoveHandler(TrayRightMouseUpEvent, value); } - } - - /// - /// A helper method to raise the TrayRightMouseUp event. - /// - protected RoutedEventArgs RaiseTrayRightMouseUpEvent() - { - return RaiseTrayRightMouseUpEvent(this); - } - - /// - /// A static helper method to raise the TrayRightMouseUp event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayRightMouseUpEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayRightMouseUpEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayMiddleMouseUp - - /// - /// TrayMiddleMouseUp Routed Event - /// - public static readonly RoutedEvent TrayMiddleMouseUpEvent = EventManager.RegisterRoutedEvent("TrayMiddleMouseUp", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the user releases the middle mouse button. - /// - public event RoutedEventHandler TrayMiddleMouseUp - { - add { AddHandler(TrayMiddleMouseUpEvent, value); } - remove { RemoveHandler(TrayMiddleMouseUpEvent, value); } - } - - /// - /// A helper method to raise the TrayMiddleMouseUp event. - /// - protected RoutedEventArgs RaiseTrayMiddleMouseUpEvent() - { - return RaiseTrayMiddleMouseUpEvent(this); - } - - /// - /// A static helper method to raise the TrayMiddleMouseUp event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayMiddleMouseUpEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayMiddleMouseUpEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - - #region TrayMouseDoubleClick - - /// - /// TrayMouseDoubleClick Routed Event - /// - public static readonly RoutedEvent TrayMouseDoubleClickEvent = EventManager.RegisterRoutedEvent("TrayMouseDoubleClick", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the user double-clicks the taskbar icon. - /// - public event RoutedEventHandler TrayMouseDoubleClick - { - add { AddHandler(TrayMouseDoubleClickEvent, value); } - remove { RemoveHandler(TrayMouseDoubleClickEvent, value); } - } - - /// - /// A helper method to raise the TrayMouseDoubleClick event. - /// - protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent() - { - RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this); - DoubleClickCommand.ExecuteIfEnabled(DoubleClickCommandParameter, DoubleClickCommandTarget ?? this); - return args; - } - - /// - /// A static helper method to raise the TrayMouseDoubleClick event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayMouseDoubleClickEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayMouseDoubleClickEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayMouseMove - - /// - /// TrayMouseMove Routed Event - /// - public static readonly RoutedEvent TrayMouseMoveEvent = EventManager.RegisterRoutedEvent("TrayMouseMove", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the user moves the mouse over the taskbar icon. - /// - public event RoutedEventHandler TrayMouseMove - { - add { AddHandler(TrayMouseMoveEvent, value); } - remove { RemoveHandler(TrayMouseMoveEvent, value); } - } - - /// - /// A helper method to raise the TrayMouseMove event. - /// - protected RoutedEventArgs RaiseTrayMouseMoveEvent() - { - return RaiseTrayMouseMoveEvent(this); - } - - /// - /// A static helper method to raise the TrayMouseMove event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayMouseMoveEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayMouseMoveEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - - #region TrayBalloonTipShown - - /// - /// TrayBalloonTipShown Routed Event - /// - public static readonly RoutedEvent TrayBalloonTipShownEvent = EventManager.RegisterRoutedEvent("TrayBalloonTipShown", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when a balloon ToolTip is displayed. - /// - public event RoutedEventHandler TrayBalloonTipShown - { - add { AddHandler(TrayBalloonTipShownEvent, value); } - remove { RemoveHandler(TrayBalloonTipShownEvent, value); } - } - - /// - /// A helper method to raise the TrayBalloonTipShown event. - /// - protected RoutedEventArgs RaiseTrayBalloonTipShownEvent() - { - return RaiseTrayBalloonTipShownEvent(this); - } - - /// - /// A static helper method to raise the TrayBalloonTipShown event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayBalloonTipShownEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayBalloonTipShownEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayBalloonTipClosed - - /// - /// TrayBalloonTipClosed Routed Event - /// - public static readonly RoutedEvent TrayBalloonTipClosedEvent = EventManager.RegisterRoutedEvent("TrayBalloonTipClosed", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when a balloon ToolTip was closed. - /// - public event RoutedEventHandler TrayBalloonTipClosed - { - add { AddHandler(TrayBalloonTipClosedEvent, value); } - remove { RemoveHandler(TrayBalloonTipClosedEvent, value); } - } - - /// - /// A helper method to raise the TrayBalloonTipClosed event. - /// - protected RoutedEventArgs RaiseTrayBalloonTipClosedEvent() - { - return RaiseTrayBalloonTipClosedEvent(this); - } - - /// - /// A static helper method to raise the TrayBalloonTipClosed event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayBalloonTipClosedEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayBalloonTipClosedEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayBalloonTipClicked - - /// - /// TrayBalloonTipClicked Routed Event - /// - public static readonly RoutedEvent TrayBalloonTipClickedEvent = EventManager.RegisterRoutedEvent("TrayBalloonTipClicked", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Occurs when the user clicks on a balloon ToolTip. - /// - public event RoutedEventHandler TrayBalloonTipClicked - { - add { AddHandler(TrayBalloonTipClickedEvent, value); } - remove { RemoveHandler(TrayBalloonTipClickedEvent, value); } - } - - /// - /// A helper method to raise the TrayBalloonTipClicked event. - /// - protected RoutedEventArgs RaiseTrayBalloonTipClickedEvent() - { - return RaiseTrayBalloonTipClickedEvent(this); - } - - /// - /// A static helper method to raise the TrayBalloonTipClicked event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayBalloonTipClickedEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayBalloonTipClickedEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - - #region TrayContextMenuOpen (and PreviewTrayContextMenuOpen) - - /// - /// TrayContextMenuOpen Routed Event - /// - public static readonly RoutedEvent TrayContextMenuOpenEvent = EventManager.RegisterRoutedEvent("TrayContextMenuOpen", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Bubbled event that occurs when the context menu of the taskbar icon is being displayed. - /// - public event RoutedEventHandler TrayContextMenuOpen - { - add { AddHandler(TrayContextMenuOpenEvent, value); } - remove { RemoveHandler(TrayContextMenuOpenEvent, value); } - } - - /// - /// A helper method to raise the TrayContextMenuOpen event. - /// - protected RoutedEventArgs RaiseTrayContextMenuOpenEvent() - { - return RaiseTrayContextMenuOpenEvent(this); - } - - /// - /// A static helper method to raise the TrayContextMenuOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayContextMenuOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayContextMenuOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - /// - /// PreviewTrayContextMenuOpen Routed Event - /// - public static readonly RoutedEvent PreviewTrayContextMenuOpenEvent = EventManager.RegisterRoutedEvent("PreviewTrayContextMenuOpen", - RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Tunneled event that occurs when the context menu of the taskbar icon is being displayed. - /// - public event RoutedEventHandler PreviewTrayContextMenuOpen - { - add { AddHandler(PreviewTrayContextMenuOpenEvent, value); } - remove { RemoveHandler(PreviewTrayContextMenuOpenEvent, value); } - } - - /// - /// A helper method to raise the PreviewTrayContextMenuOpen event. - /// - protected RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent() - { - return RaisePreviewTrayContextMenuOpenEvent(this); - } - - /// - /// A static helper method to raise the PreviewTrayContextMenuOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTrayContextMenuOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayPopupOpen (and PreviewTrayPopupOpen) - - /// - /// TrayPopupOpen Routed Event - /// - public static readonly RoutedEvent TrayPopupOpenEvent = EventManager.RegisterRoutedEvent("TrayPopupOpen", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Bubbled event that occurs when the custom popup is being opened. - /// - public event RoutedEventHandler TrayPopupOpen - { - add { AddHandler(TrayPopupOpenEvent, value); } - remove { RemoveHandler(TrayPopupOpenEvent, value); } - } - - /// - /// A helper method to raise the TrayPopupOpen event. - /// - protected RoutedEventArgs RaiseTrayPopupOpenEvent() - { - return RaiseTrayPopupOpenEvent(this); - } - - /// - /// A static helper method to raise the TrayPopupOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayPopupOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayPopupOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - /// - /// PreviewTrayPopupOpen Routed Event - /// - public static readonly RoutedEvent PreviewTrayPopupOpenEvent = EventManager.RegisterRoutedEvent("PreviewTrayPopupOpen", - RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Tunneled event that occurs when the custom popup is being opened. - /// - public event RoutedEventHandler PreviewTrayPopupOpen - { - add { AddHandler(PreviewTrayPopupOpenEvent, value); } - remove { RemoveHandler(PreviewTrayPopupOpenEvent, value); } - } - - /// - /// A helper method to raise the PreviewTrayPopupOpen event. - /// - protected RoutedEventArgs RaisePreviewTrayPopupOpenEvent() - { - return RaisePreviewTrayPopupOpenEvent(this); - } - - /// - /// A static helper method to raise the PreviewTrayPopupOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTrayPopupOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTrayPopupOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - - #region TrayToolTipOpen (and PreviewTrayToolTipOpen) - - /// - /// TrayToolTipOpen Routed Event - /// - public static readonly RoutedEvent TrayToolTipOpenEvent = EventManager.RegisterRoutedEvent("TrayToolTipOpen", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Bubbled event that occurs when the custom ToolTip is being displayed. - /// - public event RoutedEventHandler TrayToolTipOpen - { - add { AddHandler(TrayToolTipOpenEvent, value); } - remove { RemoveHandler(TrayToolTipOpenEvent, value); } - } - - /// - /// A helper method to raise the TrayToolTipOpen event. - /// - protected RoutedEventArgs RaiseTrayToolTipOpenEvent() - { - return RaiseTrayToolTipOpenEvent(this); - } - - /// - /// A static helper method to raise the TrayToolTipOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayToolTipOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayToolTipOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - /// - /// PreviewTrayToolTipOpen Routed Event - /// - public static readonly RoutedEvent PreviewTrayToolTipOpenEvent = EventManager.RegisterRoutedEvent("PreviewTrayToolTipOpen", - RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Tunneled event that occurs when the custom ToolTip is being displayed. - /// - public event RoutedEventHandler PreviewTrayToolTipOpen - { - add { AddHandler(PreviewTrayToolTipOpenEvent, value); } - remove { RemoveHandler(PreviewTrayToolTipOpenEvent, value); } - } - - /// - /// A helper method to raise the PreviewTrayToolTipOpen event. - /// - protected RoutedEventArgs RaisePreviewTrayToolTipOpenEvent() - { - return RaisePreviewTrayToolTipOpenEvent(this); - } - - /// - /// A static helper method to raise the PreviewTrayToolTipOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTrayToolTipOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTrayToolTipOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayToolTipClose (and PreviewTrayToolTipClose) - - /// - /// TrayToolTipClose Routed Event - /// - public static readonly RoutedEvent TrayToolTipCloseEvent = EventManager.RegisterRoutedEvent("TrayToolTipClose", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Bubbled event that occurs when a custom tooltip is being closed. - /// - public event RoutedEventHandler TrayToolTipClose - { - add { AddHandler(TrayToolTipCloseEvent, value); } - remove { RemoveHandler(TrayToolTipCloseEvent, value); } - } - - /// - /// A helper method to raise the TrayToolTipClose event. - /// - protected RoutedEventArgs RaiseTrayToolTipCloseEvent() - { - return RaiseTrayToolTipCloseEvent(this); - } - - /// - /// A static helper method to raise the TrayToolTipClose event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayToolTipCloseEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayToolTipCloseEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - /// - /// PreviewTrayToolTipClose Routed Event - /// - public static readonly RoutedEvent PreviewTrayToolTipCloseEvent = EventManager.RegisterRoutedEvent("PreviewTrayToolTipClose", - RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Tunneled event that occurs when a custom tooltip is being closed. - /// - public event RoutedEventHandler PreviewTrayToolTipClose - { - add { AddHandler(PreviewTrayToolTipCloseEvent, value); } - remove { RemoveHandler(PreviewTrayToolTipCloseEvent, value); } - } - - /// - /// A helper method to raise the PreviewTrayToolTipClose event. - /// - protected RoutedEventArgs RaisePreviewTrayToolTipCloseEvent() - { - return RaisePreviewTrayToolTipCloseEvent(this); - } - - /// - /// A static helper method to raise the PreviewTrayToolTipClose event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTrayToolTipCloseEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTrayToolTipCloseEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - - //ATTACHED EVENTS - - #region PopupOpened - - /// - /// PopupOpened Attached Routed Event - /// - public static readonly RoutedEvent PopupOpenedEvent = EventManager.RegisterRoutedEvent("PopupOpened", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Adds a handler for the PopupOpened attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddPopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, PopupOpenedEvent, handler); - } - - /// - /// Removes a handler for the PopupOpened attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemovePopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, PopupOpenedEvent, handler); - } - - /// - /// A static helper method to raise the PopupOpened event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePopupOpenedEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PopupOpenedEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region ToolTipOpened - - /// - /// ToolTipOpened Attached Routed Event - /// - public static readonly RoutedEvent ToolTipOpenedEvent = EventManager.RegisterRoutedEvent("ToolTipOpened", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Adds a handler for the ToolTipOpened attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, ToolTipOpenedEvent, handler); - } - - /// - /// Removes a handler for the ToolTipOpened attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemoveToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, ToolTipOpenedEvent, handler); - } - - /// - /// A static helper method to raise the ToolTipOpened event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseToolTipOpenedEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = ToolTipOpenedEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region ToolTipClose - - /// - /// ToolTipClose Attached Routed Event - /// - public static readonly RoutedEvent ToolTipCloseEvent = EventManager.RegisterRoutedEvent("ToolTipClose", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Adds a handler for the ToolTipClose attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, ToolTipCloseEvent, handler); - } - - /// - /// Removes a handler for the ToolTipClose attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemoveToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, ToolTipCloseEvent, handler); - } - - /// - /// A static helper method to raise the ToolTipClose event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseToolTipCloseEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = ToolTipCloseEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region BalloonShowing - - /// - /// BalloonShowing Attached Routed Event - /// - public static readonly RoutedEvent BalloonShowingEvent = EventManager.RegisterRoutedEvent("BalloonShowing", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Adds a handler for the BalloonShowing attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, BalloonShowingEvent, handler); - } - - /// - /// Removes a handler for the BalloonShowing attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemoveBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, BalloonShowingEvent, handler); - } - - /// - /// A static helper method to raise the BalloonShowing event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - /// The instance that manages the balloon. - internal static RoutedEventArgs RaiseBalloonShowingEvent(DependencyObject target, TaskbarIcon source) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(BalloonShowingEvent, source); - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region BalloonClosing - - /// - /// BalloonClosing Attached Routed Event - /// - public static readonly RoutedEvent BalloonClosingEvent = EventManager.RegisterRoutedEvent("BalloonClosing", - RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); - - /// - /// Adds a handler for the BalloonClosing attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, BalloonClosingEvent, handler); - } - - /// - /// Removes a handler for the BalloonClosing attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemoveBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, BalloonClosingEvent, handler); - } - - /// - /// A static helper method to raise the BalloonClosing event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - /// The instance that manages the balloon. - internal static RoutedEventArgs RaiseBalloonClosingEvent(DependencyObject target, TaskbarIcon source) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(BalloonClosingEvent, source); - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - - - //ATTACHED PROPERTIES - - #region ParentTaskbarIcon - - /// - /// An attached property that is assigned to displayed UI elements (balloos, tooltips, context menus), and - /// that can be used to bind to this control. The attached property is being derived, so binding is - /// quite straightforward: - /// - /// - /// - /// - public static readonly DependencyProperty ParentTaskbarIconProperty = - DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof (TaskbarIcon), typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); - - /// - /// Gets the ParentTaskbarIcon property. This dependency property - /// indicates .... - /// - public static TaskbarIcon GetParentTaskbarIcon(DependencyObject d) - { - return (TaskbarIcon)d.GetValue(ParentTaskbarIconProperty); - } - - /// - /// Sets the ParentTaskbarIcon property. This dependency property - /// indicates .... - /// - public static void SetParentTaskbarIcon(DependencyObject d, TaskbarIcon value) - { - d.SetValue(ParentTaskbarIconProperty, value); - } - - #endregion - - - //BASE CLASS PROPERTY OVERRIDES - - /// - /// Registers properties. - /// - static TaskbarIcon() - { - //register change listener for the Visibility property - PropertyMetadata md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); - VisibilityProperty.OverrideMetadata(typeof(TaskbarIcon), md); - - //register change listener for the DataContext property - md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged)); - DataContextProperty.OverrideMetadata(typeof(TaskbarIcon), md); - - //register change listener for the ContextMenu property - md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); - ContextMenuProperty.OverrideMetadata(typeof(TaskbarIcon), md); + /// Contains declarations of WPF dependency properties + /// and events. + ///
+ partial class TaskbarIcon + { + /// + /// Category name that is set on designer properties. + /// + public const string CategoryName = "NotifyIcon"; + + + //POPUP CONTROLS + + #region TrayPopupResolved + + /// + /// TrayPopupResolved Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey TrayPopupResolvedPropertyKey + = DependencyProperty.RegisterReadOnly("TrayPopupResolved", typeof (Popup), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + + /// + /// A read-only dependency property that returns the + /// that is being displayed in the taskbar area based on a user action. + /// + public static readonly DependencyProperty TrayPopupResolvedProperty + = TrayPopupResolvedPropertyKey.DependencyProperty; + + /// + /// Gets the TrayPopupResolved property. Returns + /// a which is either the + /// control itself or a + /// control that contains the + /// . + /// + [Category(CategoryName)] + public Popup TrayPopupResolved + { + get { return (Popup) GetValue(TrayPopupResolvedProperty); } + } + + /// + /// Provides a secure method for setting the TrayPopupResolved property. + /// This dependency property indicates .... + /// + /// The new value for the property. + protected void SetTrayPopupResolved(Popup value) + { + SetValue(TrayPopupResolvedPropertyKey, value); + } + + #endregion + + #region TrayToolTipResolved + + /// + /// TrayToolTipResolved Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey TrayToolTipResolvedPropertyKey + = DependencyProperty.RegisterReadOnly("TrayToolTipResolved", typeof (ToolTip), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + + /// + /// A read-only dependency property that returns the + /// that is being displayed. + /// + public static readonly DependencyProperty TrayToolTipResolvedProperty + = TrayToolTipResolvedPropertyKey.DependencyProperty; + + /// + /// Gets the TrayToolTipResolved property. Returns + /// a control that was created + /// in order to display either + /// or . + /// + [Category(CategoryName)] + [Browsable(true)] + [Bindable(true)] + public ToolTip TrayToolTipResolved + { + get { return (ToolTip) GetValue(TrayToolTipResolvedProperty); } + } + + /// + /// Provides a secure method for setting the + /// property. + /// + /// The new value for the property. + protected void SetTrayToolTipResolved(ToolTip value) + { + SetValue(TrayToolTipResolvedPropertyKey, value); + } + + #endregion + + #region CustomBalloon + + /// + /// CustomBalloon Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey CustomBalloonPropertyKey + = DependencyProperty.RegisterReadOnly("CustomBalloon", typeof (Popup), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + public static readonly DependencyProperty CustomBalloonProperty + = CustomBalloonPropertyKey.DependencyProperty; + + /// + /// A custom popup that is being displayed in the tray area in order + /// to display messages to the user. + /// + public Popup CustomBalloon + { + get { return (Popup) GetValue(CustomBalloonProperty); } + } + + /// + /// Provides a secure method for setting the property. + /// + /// The new value for the property. + protected void SetCustomBalloon(Popup value) + { + SetValue(CustomBalloonPropertyKey, value); + } + + #endregion + + //DEPENDENCY PROPERTIES + + #region Icon property / IconSource dependency property + + private Icon icon; + + /// + /// Gets or sets the icon to be displayed. This is not a + /// dependency property - if you want to assign the property + /// through XAML, please use the + /// dependency property. + /// + [Browsable(false)] + public Icon Icon + { + get { return icon; } + set + { + icon = value; + iconData.IconHandle = value == null ? IntPtr.Zero : icon.Handle; + + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Icon); + } + } + + + /// + /// Resolves an image source and updates the property accordingly. + /// + public static readonly DependencyProperty IconSourceProperty = + DependencyProperty.Register("IconSource", + typeof (ImageSource), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, IconSourcePropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Resolves an image source and updates the property accordingly. + ///
+ [Category(CategoryName)] + [Description("Sets the displayed taskbar icon.")] + public ImageSource IconSource + { + get { return (ImageSource) GetValue(IconSourceProperty); } + set { SetValue(IconSourceProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnIconSourcePropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e) + { + ImageSource newValue = (ImageSource) e.NewValue; + + //resolving the ImageSource at design time is unlikely to work + if (!Util.IsDesignMode) Icon = newValue.ToIcon(); + } + + #endregion + + #region ToolTipText dependency property + + /// + /// A tooltip text that is being displayed if no custom + /// was set or if custom tooltips are not supported. + /// + public static readonly DependencyProperty ToolTipTextProperty = + DependencyProperty.Register("ToolTipText", + typeof (string), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(String.Empty, ToolTipTextPropertyChanged)); + + + /// + /// A property wrapper for the + /// dependency property:
+ /// A tooltip text that is being displayed if no custom + /// was set or if custom tooltips are not supported. + ///
+ [Category(CategoryName)] + [Description("Alternative to a fully blown ToolTip, which is only displayed on Vista and above.")] + public string ToolTipText + { + get { return (string) GetValue(ToolTipTextProperty); } + set { SetValue(ToolTipTextProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnToolTipTextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e) + { + //only recreate tooltip if we're not using a custom control + if (TrayToolTipResolved == null || TrayToolTipResolved.Content is string) + { + CreateCustomToolTip(); + } + + WriteToolTipSettings(); + } + + #endregion + + #region TrayToolTip dependency property + + /// + /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. + /// Works only with Vista and above. Accordingly, you should make sure that + /// the property is set as well. + /// + public static readonly DependencyProperty TrayToolTipProperty = + DependencyProperty.Register("TrayToolTip", + typeof (UIElement), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, TrayToolTipPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. + /// Works only with Vista and above. Accordingly, you should make sure that + /// the property is set as well. + ///
+ [Category(CategoryName)] + [Description("Custom UI element that is displayed as a tooltip. Only on Vista and above")] + public UIElement TrayToolTip + { + get { return (UIElement) GetValue(TrayToolTipProperty); } + set { SetValue(TrayToolTipProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void TrayToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnTrayToolTipPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnTrayToolTipPropertyChanged(DependencyPropertyChangedEventArgs e) + { + //recreate tooltip control + CreateCustomToolTip(); + + if (e.OldValue != null) + { + //remove the taskbar icon reference from the previously used element + SetParentTaskbarIcon((DependencyObject) e.OldValue, null); + } + + + if (e.NewValue != null) + { + //set this taskbar icon as a reference to the new tooltip element + SetParentTaskbarIcon((DependencyObject) e.NewValue, this); + } + + + //update tooltip settings - needed to make sure a string is set, even + //if the ToolTipText property is not set. Otherwise, the event that + //triggers tooltip display is never fired. + WriteToolTipSettings(); + } + + #endregion + + #region TrayPopup dependency property + + /// + /// A control that is displayed as a popup when the taskbar icon is clicked. + /// + public static readonly DependencyProperty TrayPopupProperty = + DependencyProperty.Register("TrayPopup", + typeof (UIElement), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, TrayPopupPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// A control that is displayed as a popup when the taskbar icon is clicked. + ///
+ [Category(CategoryName)] + [Description("Displayed as a Popup if the user clicks on the taskbar icon.")] + public UIElement TrayPopup + { + get { return (UIElement) GetValue(TrayPopupProperty); } + set { SetValue(TrayPopupProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void TrayPopupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnTrayPopupPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnTrayPopupPropertyChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + { + //remove the taskbar icon reference from the previously used element + SetParentTaskbarIcon((DependencyObject) e.OldValue, null); + } + + + if (e.NewValue != null) + { + //set this taskbar icon as a reference to the new tooltip element + SetParentTaskbarIcon((DependencyObject) e.NewValue, this); + } + + //create a pop + CreatePopup(); + } + + #endregion + + #region MenuActivation dependency property + + /// + /// Defines what mouse events display the context menu. + /// Defaults to . + /// + public static readonly DependencyProperty MenuActivationProperty = + DependencyProperty.Register("MenuActivation", + typeof (PopupActivationMode), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(PopupActivationMode.RightClick)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Defines what mouse events display the context menu. + /// Defaults to . + ///
+ [Category(CategoryName)] + [Description("Defines what mouse events display the context menu.")] + public PopupActivationMode MenuActivation + { + get { return (PopupActivationMode) GetValue(MenuActivationProperty); } + set { SetValue(MenuActivationProperty, value); } + } + + #endregion + + #region PopupActivation dependency property + + /// + /// Defines what mouse events trigger the . + /// Default is . + /// + public static readonly DependencyProperty PopupActivationProperty = + DependencyProperty.Register("PopupActivation", + typeof (PopupActivationMode), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(PopupActivationMode.LeftClick)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Defines what mouse events trigger the . + /// Default is . + ///
+ [Category(CategoryName)] + [Description("Defines what mouse events display the TaskbarIconPopup.")] + public PopupActivationMode PopupActivation + { + get { return (PopupActivationMode) GetValue(PopupActivationProperty); } + set { SetValue(PopupActivationProperty, value); } + } + + #endregion + + #region Visibility dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnVisibilityPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnVisibilityPropertyChanged(DependencyPropertyChangedEventArgs e) + { + Visibility newValue = (Visibility) e.NewValue; + + //update + if (newValue == Visibility.Visible) + { + CreateTaskbarIcon(); + } + else + { + RemoveTaskbarIcon(); + } + } + + #endregion + + #region DataContext dependency property override / target update + + /// + /// Updates the of a given + /// . This method only updates target elements + /// that do not already have a data context of their own, and either assigns + /// the of the NotifyIcon, or the + /// NotifyIcon itself, if no data context was assigned at all. + /// + private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue) + { + //if there is no target or it's data context is determined through a binding + //of its own, keep it + if (target == null || target.IsDataContextDataBound()) return; + + //if the target's data context is the NotifyIcon's old DataContext or the NotifyIcon itself, + //update it + if (ReferenceEquals(this, target.DataContext) || Equals(oldDataContextValue, target.DataContext)) + { + //assign own data context, if available. If there is no data + //context at all, assign NotifyIcon itself. + target.DataContext = newDataContextValue ?? this; + } + } + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnDataContextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e) + { + object newValue = e.NewValue; + object oldValue = e.OldValue; + + //replace custom data context for ToolTips, Popup, and + //ContextMenu + UpdateDataContext(TrayPopupResolved, oldValue, newValue); + UpdateDataContext(TrayToolTipResolved, oldValue, newValue); + UpdateDataContext(ContextMenu, oldValue, newValue); + } + + #endregion + + #region ContextMenu dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnContextMenuPropertyChanged(e); + } + + + /// + /// Releases the old and updates the new property + /// in order to reflect both the NotifyIcon's + /// property and have the assigned. + /// + /// Provides information about the updated property. + private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + { + //remove the taskbar icon reference from the previously used element + SetParentTaskbarIcon((DependencyObject) e.OldValue, null); + } + + if (e.NewValue != null) + { + //set this taskbar icon as a reference to the new tooltip element + SetParentTaskbarIcon((DependencyObject) e.NewValue, this); + } + + UpdateDataContext((ContextMenu) e.NewValue, null, DataContext); + } + + #endregion + + #region DoubleClickCommand dependency property + + /// + /// Associates a command that is being executed if the tray icon is being + /// double clicked. + /// + public static readonly DependencyProperty DoubleClickCommandProperty = + DependencyProperty.Register("DoubleClickCommand", + typeof (ICommand), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Associates a command that is being executed if the tray icon is being + /// double clicked. + ///
+ [Category(CategoryName)] + [Description("A command that is being executed if the tray icon is being double-clicked.")] + public ICommand DoubleClickCommand + { + get { return (ICommand) GetValue(DoubleClickCommandProperty); } + set { SetValue(DoubleClickCommandProperty, value); } + } + + #endregion + + #region DoubleClickCommandParameter dependency property + + /// + /// Command parameter for the . + /// + public static readonly DependencyProperty DoubleClickCommandParameterProperty = + DependencyProperty.Register("DoubleClickCommandParameter", + typeof (object), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Command parameter for the . + ///
+ [Category(CategoryName)] + [Description("Parameter to submit to the DoubleClickCommand when the user double clicks on the NotifyIcon.")] + public object DoubleClickCommandParameter + { + get { return GetValue(DoubleClickCommandParameterProperty); } + set { SetValue(DoubleClickCommandParameterProperty, value); } + } + + #endregion + + #region DoubleClickCommandTarget dependency property + + /// + /// The target of the command that is fired if the notify icon is double clicked. + /// + public static readonly DependencyProperty DoubleClickCommandTargetProperty = + DependencyProperty.Register("DoubleClickCommandTarget", + typeof (IInputElement), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The target of the command that is fired if the notify icon is double clicked. + ///
+ [Category(CategoryName)] + [Description("The target of the command that is fired if the notify icon is double clicked.")] + public IInputElement DoubleClickCommandTarget + { + get { return (IInputElement) GetValue(DoubleClickCommandTargetProperty); } + set { SetValue(DoubleClickCommandTargetProperty, value); } + } + + #endregion + + #region LeftClickCommand dependency property + + /// + /// Associates a command that is being executed if the tray icon is being + /// double clicked. + /// + public static readonly DependencyProperty LeftClickCommandProperty = + DependencyProperty.Register("LeftClickCommand", + typeof (ICommand), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Associates a command that is being executed if the tray icon is being + /// left-clicked. + ///
+ [Category(CategoryName)] + [Description("A command that is being executed if the tray icon is being left-clicked.")] + public ICommand LeftClickCommand + { + get { return (ICommand) GetValue(LeftClickCommandProperty); } + set { SetValue(LeftClickCommandProperty, value); } + } + + #endregion + + #region LeftClickCommandParameter dependency property + + /// + /// Command parameter for the . + /// + public static readonly DependencyProperty LeftClickCommandParameterProperty = + DependencyProperty.Register("LeftClickCommandParameter", + typeof (object), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Command parameter for the . + ///
+ [Category(CategoryName)] + [Description("The target of the command that is fired if the notify icon is clicked with the left mouse button." + )] + public object LeftClickCommandParameter + { + get { return GetValue(LeftClickCommandParameterProperty); } + set { SetValue(LeftClickCommandParameterProperty, value); } + } + + #endregion + + #region LeftClickCommandTarget dependency property + + /// + /// The target of the command that is fired if the notify icon is clicked. + /// + public static readonly DependencyProperty LeftClickCommandTargetProperty = + DependencyProperty.Register("LeftClickCommandTarget", + typeof (IInputElement), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The target of the command that is fired if the notify icon is clicked. + ///
+ [Category(CategoryName)] + [Description("The target of the command that is fired if the notify icon is clicked with the left mouse button." + )] + public IInputElement LeftClickCommandTarget + { + get { return (IInputElement) GetValue(LeftClickCommandTargetProperty); } + set { SetValue(LeftClickCommandTargetProperty, value); } + } + + #endregion + + //EVENTS + + #region TrayLeftMouseDown + + /// + /// TrayLeftMouseDown Routed Event + /// + public static readonly RoutedEvent TrayLeftMouseDownEvent = EventManager.RegisterRoutedEvent( + "TrayLeftMouseDown", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user presses the left mouse button. + /// + [Category(CategoryName)] + public event RoutedEventHandler TrayLeftMouseDown + { + add { AddHandler(TrayLeftMouseDownEvent, value); } + remove { RemoveHandler(TrayLeftMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TrayLeftMouseDown event. + /// + protected RoutedEventArgs RaiseTrayLeftMouseDownEvent() + { + RoutedEventArgs args = RaiseTrayLeftMouseDownEvent(this); + return args; + } + + /// + /// A static helper method to raise the TrayLeftMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayLeftMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayLeftMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayRightMouseDown + + /// + /// TrayRightMouseDown Routed Event + /// + public static readonly RoutedEvent TrayRightMouseDownEvent = + EventManager.RegisterRoutedEvent("TrayRightMouseDown", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the presses the right mouse button. + /// + public event RoutedEventHandler TrayRightMouseDown + { + add { AddHandler(TrayRightMouseDownEvent, value); } + remove { RemoveHandler(TrayRightMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TrayRightMouseDown event. + /// + protected RoutedEventArgs RaiseTrayRightMouseDownEvent() + { + return RaiseTrayRightMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TrayRightMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayRightMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayRightMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayMiddleMouseDown + + /// + /// TrayMiddleMouseDown Routed Event + /// + public static readonly RoutedEvent TrayMiddleMouseDownEvent = + EventManager.RegisterRoutedEvent("TrayMiddleMouseDown", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user presses the middle mouse button. + /// + public event RoutedEventHandler TrayMiddleMouseDown + { + add { AddHandler(TrayMiddleMouseDownEvent, value); } + remove { RemoveHandler(TrayMiddleMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TrayMiddleMouseDown event. + /// + protected RoutedEventArgs RaiseTrayMiddleMouseDownEvent() + { + return RaiseTrayMiddleMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TrayMiddleMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayMiddleMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayMiddleMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayLeftMouseUp + + /// + /// TrayLeftMouseUp Routed Event + /// + public static readonly RoutedEvent TrayLeftMouseUpEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseUp", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user releases the left mouse button. + /// + public event RoutedEventHandler TrayLeftMouseUp + { + add { AddHandler(TrayLeftMouseUpEvent, value); } + remove { RemoveHandler(TrayLeftMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TrayLeftMouseUp event. + /// + protected RoutedEventArgs RaiseTrayLeftMouseUpEvent() + { + return RaiseTrayLeftMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TrayLeftMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayLeftMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayLeftMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayRightMouseUp + + /// + /// TrayRightMouseUp Routed Event + /// + public static readonly RoutedEvent TrayRightMouseUpEvent = EventManager.RegisterRoutedEvent("TrayRightMouseUp", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user releases the right mouse button. + /// + public event RoutedEventHandler TrayRightMouseUp + { + add { AddHandler(TrayRightMouseUpEvent, value); } + remove { RemoveHandler(TrayRightMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TrayRightMouseUp event. + /// + protected RoutedEventArgs RaiseTrayRightMouseUpEvent() + { + return RaiseTrayRightMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TrayRightMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayRightMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayRightMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayMiddleMouseUp + + /// + /// TrayMiddleMouseUp Routed Event + /// + public static readonly RoutedEvent TrayMiddleMouseUpEvent = EventManager.RegisterRoutedEvent( + "TrayMiddleMouseUp", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user releases the middle mouse button. + /// + public event RoutedEventHandler TrayMiddleMouseUp + { + add { AddHandler(TrayMiddleMouseUpEvent, value); } + remove { RemoveHandler(TrayMiddleMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TrayMiddleMouseUp event. + /// + protected RoutedEventArgs RaiseTrayMiddleMouseUpEvent() + { + return RaiseTrayMiddleMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TrayMiddleMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayMiddleMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayMiddleMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayMouseDoubleClick + + /// + /// TrayMouseDoubleClick Routed Event + /// + public static readonly RoutedEvent TrayMouseDoubleClickEvent = + EventManager.RegisterRoutedEvent("TrayMouseDoubleClick", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user double-clicks the taskbar icon. + /// + public event RoutedEventHandler TrayMouseDoubleClick + { + add { AddHandler(TrayMouseDoubleClickEvent, value); } + remove { RemoveHandler(TrayMouseDoubleClickEvent, value); } + } + + /// + /// A helper method to raise the TrayMouseDoubleClick event. + /// + protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent() + { + RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this); + DoubleClickCommand.ExecuteIfEnabled(DoubleClickCommandParameter, DoubleClickCommandTarget ?? this); + return args; + } + + /// + /// A static helper method to raise the TrayMouseDoubleClick event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayMouseDoubleClickEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayMouseDoubleClickEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayMouseMove + + /// + /// TrayMouseMove Routed Event + /// + public static readonly RoutedEvent TrayMouseMoveEvent = EventManager.RegisterRoutedEvent("TrayMouseMove", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user moves the mouse over the taskbar icon. + /// + public event RoutedEventHandler TrayMouseMove + { + add { AddHandler(TrayMouseMoveEvent, value); } + remove { RemoveHandler(TrayMouseMoveEvent, value); } + } + + /// + /// A helper method to raise the TrayMouseMove event. + /// + protected RoutedEventArgs RaiseTrayMouseMoveEvent() + { + return RaiseTrayMouseMoveEvent(this); + } + + /// + /// A static helper method to raise the TrayMouseMove event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayMouseMoveEvent(DependencyObject target) + { + if (target == null) return null; + + var args = new RoutedEventArgs(); + args.RoutedEvent = TrayMouseMoveEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayBalloonTipShown + + /// + /// TrayBalloonTipShown Routed Event + /// + public static readonly RoutedEvent TrayBalloonTipShownEvent = + EventManager.RegisterRoutedEvent("TrayBalloonTipShown", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when a balloon ToolTip is displayed. + /// + public event RoutedEventHandler TrayBalloonTipShown + { + add { AddHandler(TrayBalloonTipShownEvent, value); } + remove { RemoveHandler(TrayBalloonTipShownEvent, value); } + } + + /// + /// A helper method to raise the TrayBalloonTipShown event. + /// + protected RoutedEventArgs RaiseTrayBalloonTipShownEvent() + { + return RaiseTrayBalloonTipShownEvent(this); + } + + /// + /// A static helper method to raise the TrayBalloonTipShown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayBalloonTipShownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayBalloonTipShownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayBalloonTipClosed + + /// + /// TrayBalloonTipClosed Routed Event + /// + public static readonly RoutedEvent TrayBalloonTipClosedEvent = + EventManager.RegisterRoutedEvent("TrayBalloonTipClosed", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when a balloon ToolTip was closed. + /// + public event RoutedEventHandler TrayBalloonTipClosed + { + add { AddHandler(TrayBalloonTipClosedEvent, value); } + remove { RemoveHandler(TrayBalloonTipClosedEvent, value); } + } + + /// + /// A helper method to raise the TrayBalloonTipClosed event. + /// + protected RoutedEventArgs RaiseTrayBalloonTipClosedEvent() + { + return RaiseTrayBalloonTipClosedEvent(this); + } + + /// + /// A static helper method to raise the TrayBalloonTipClosed event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayBalloonTipClosedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayBalloonTipClosedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayBalloonTipClicked + + /// + /// TrayBalloonTipClicked Routed Event + /// + public static readonly RoutedEvent TrayBalloonTipClickedEvent = + EventManager.RegisterRoutedEvent("TrayBalloonTipClicked", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user clicks on a balloon ToolTip. + /// + public event RoutedEventHandler TrayBalloonTipClicked + { + add { AddHandler(TrayBalloonTipClickedEvent, value); } + remove { RemoveHandler(TrayBalloonTipClickedEvent, value); } + } + + /// + /// A helper method to raise the TrayBalloonTipClicked event. + /// + protected RoutedEventArgs RaiseTrayBalloonTipClickedEvent() + { + return RaiseTrayBalloonTipClickedEvent(this); + } + + /// + /// A static helper method to raise the TrayBalloonTipClicked event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayBalloonTipClickedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayBalloonTipClickedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayContextMenuOpen (and PreviewTrayContextMenuOpen) + + /// + /// TrayContextMenuOpen Routed Event + /// + public static readonly RoutedEvent TrayContextMenuOpenEvent = + EventManager.RegisterRoutedEvent("TrayContextMenuOpen", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Bubbled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler TrayContextMenuOpen + { + add { AddHandler(TrayContextMenuOpenEvent, value); } + remove { RemoveHandler(TrayContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the TrayContextMenuOpen event. + /// + protected RoutedEventArgs RaiseTrayContextMenuOpenEvent() + { + return RaiseTrayContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the TrayContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTrayContextMenuOpen Routed Event + /// + public static readonly RoutedEvent PreviewTrayContextMenuOpenEvent = + EventManager.RegisterRoutedEvent("PreviewTrayContextMenuOpen", + RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Tunneled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler PreviewTrayContextMenuOpen + { + add { AddHandler(PreviewTrayContextMenuOpenEvent, value); } + remove { RemoveHandler(PreviewTrayContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTrayContextMenuOpen event. + /// + protected RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent() + { + return RaisePreviewTrayContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTrayContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTrayContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayPopupOpen (and PreviewTrayPopupOpen) + + /// + /// TrayPopupOpen Routed Event + /// + public static readonly RoutedEvent TrayPopupOpenEvent = EventManager.RegisterRoutedEvent("TrayPopupOpen", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Bubbled event that occurs when the custom popup is being opened. + /// + public event RoutedEventHandler TrayPopupOpen + { + add { AddHandler(TrayPopupOpenEvent, value); } + remove { RemoveHandler(TrayPopupOpenEvent, value); } + } + + /// + /// A helper method to raise the TrayPopupOpen event. + /// + protected RoutedEventArgs RaiseTrayPopupOpenEvent() + { + return RaiseTrayPopupOpenEvent(this); + } + + /// + /// A static helper method to raise the TrayPopupOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayPopupOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayPopupOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTrayPopupOpen Routed Event + /// + public static readonly RoutedEvent PreviewTrayPopupOpenEvent = + EventManager.RegisterRoutedEvent("PreviewTrayPopupOpen", + RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Tunneled event that occurs when the custom popup is being opened. + /// + public event RoutedEventHandler PreviewTrayPopupOpen + { + add { AddHandler(PreviewTrayPopupOpenEvent, value); } + remove { RemoveHandler(PreviewTrayPopupOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTrayPopupOpen event. + /// + protected RoutedEventArgs RaisePreviewTrayPopupOpenEvent() + { + return RaisePreviewTrayPopupOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTrayPopupOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTrayPopupOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTrayPopupOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayToolTipOpen (and PreviewTrayToolTipOpen) + + /// + /// TrayToolTipOpen Routed Event + /// + public static readonly RoutedEvent TrayToolTipOpenEvent = EventManager.RegisterRoutedEvent("TrayToolTipOpen", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Bubbled event that occurs when the custom ToolTip is being displayed. + /// + public event RoutedEventHandler TrayToolTipOpen + { + add { AddHandler(TrayToolTipOpenEvent, value); } + remove { RemoveHandler(TrayToolTipOpenEvent, value); } + } + + /// + /// A helper method to raise the TrayToolTipOpen event. + /// + protected RoutedEventArgs RaiseTrayToolTipOpenEvent() + { + return RaiseTrayToolTipOpenEvent(this); + } + + /// + /// A static helper method to raise the TrayToolTipOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayToolTipOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayToolTipOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTrayToolTipOpen Routed Event + /// + public static readonly RoutedEvent PreviewTrayToolTipOpenEvent = + EventManager.RegisterRoutedEvent("PreviewTrayToolTipOpen", + RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Tunneled event that occurs when the custom ToolTip is being displayed. + /// + public event RoutedEventHandler PreviewTrayToolTipOpen + { + add { AddHandler(PreviewTrayToolTipOpenEvent, value); } + remove { RemoveHandler(PreviewTrayToolTipOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTrayToolTipOpen event. + /// + protected RoutedEventArgs RaisePreviewTrayToolTipOpenEvent() + { + return RaisePreviewTrayToolTipOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTrayToolTipOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTrayToolTipOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTrayToolTipOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayToolTipClose (and PreviewTrayToolTipClose) + + /// + /// TrayToolTipClose Routed Event + /// + public static readonly RoutedEvent TrayToolTipCloseEvent = EventManager.RegisterRoutedEvent("TrayToolTipClose", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Bubbled event that occurs when a custom tooltip is being closed. + /// + public event RoutedEventHandler TrayToolTipClose + { + add { AddHandler(TrayToolTipCloseEvent, value); } + remove { RemoveHandler(TrayToolTipCloseEvent, value); } + } + + /// + /// A helper method to raise the TrayToolTipClose event. + /// + protected RoutedEventArgs RaiseTrayToolTipCloseEvent() + { + return RaiseTrayToolTipCloseEvent(this); + } + + /// + /// A static helper method to raise the TrayToolTipClose event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayToolTipCloseEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayToolTipCloseEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTrayToolTipClose Routed Event + /// + public static readonly RoutedEvent PreviewTrayToolTipCloseEvent = + EventManager.RegisterRoutedEvent("PreviewTrayToolTipClose", + RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Tunneled event that occurs when a custom tooltip is being closed. + /// + public event RoutedEventHandler PreviewTrayToolTipClose + { + add { AddHandler(PreviewTrayToolTipCloseEvent, value); } + remove { RemoveHandler(PreviewTrayToolTipCloseEvent, value); } + } + + /// + /// A helper method to raise the PreviewTrayToolTipClose event. + /// + protected RoutedEventArgs RaisePreviewTrayToolTipCloseEvent() + { + return RaisePreviewTrayToolTipCloseEvent(this); + } + + /// + /// A static helper method to raise the PreviewTrayToolTipClose event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTrayToolTipCloseEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTrayToolTipCloseEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + //ATTACHED EVENTS + + #region PopupOpened + + /// + /// PopupOpened Attached Routed Event + /// + public static readonly RoutedEvent PopupOpenedEvent = EventManager.RegisterRoutedEvent("PopupOpened", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the PopupOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddPopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, PopupOpenedEvent, handler); + } + + /// + /// Removes a handler for the PopupOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemovePopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, PopupOpenedEvent, handler); + } + + /// + /// A static helper method to raise the PopupOpened event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePopupOpenedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PopupOpenedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region ToolTipOpened + + /// + /// ToolTipOpened Attached Routed Event + /// + public static readonly RoutedEvent ToolTipOpenedEvent = EventManager.RegisterRoutedEvent("ToolTipOpened", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the ToolTipOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, ToolTipOpenedEvent, handler); + } + + /// + /// Removes a handler for the ToolTipOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, ToolTipOpenedEvent, handler); + } + + /// + /// A static helper method to raise the ToolTipOpened event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseToolTipOpenedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = ToolTipOpenedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region ToolTipClose + + /// + /// ToolTipClose Attached Routed Event + /// + public static readonly RoutedEvent ToolTipCloseEvent = EventManager.RegisterRoutedEvent("ToolTipClose", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the ToolTipClose attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, ToolTipCloseEvent, handler); + } + + /// + /// Removes a handler for the ToolTipClose attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, ToolTipCloseEvent, handler); + } + + /// + /// A static helper method to raise the ToolTipClose event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseToolTipCloseEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = ToolTipCloseEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region BalloonShowing + + /// + /// BalloonShowing Attached Routed Event + /// + public static readonly RoutedEvent BalloonShowingEvent = EventManager.RegisterRoutedEvent("BalloonShowing", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the BalloonShowing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, BalloonShowingEvent, handler); + } + + /// + /// Removes a handler for the BalloonShowing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, BalloonShowingEvent, handler); + } + + /// + /// A static helper method to raise the BalloonShowing event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + /// The instance that manages the balloon. + internal static RoutedEventArgs RaiseBalloonShowingEvent(DependencyObject target, TaskbarIcon source) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(BalloonShowingEvent, source); + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region BalloonClosing + + /// + /// BalloonClosing Attached Routed Event + /// + public static readonly RoutedEvent BalloonClosingEvent = EventManager.RegisterRoutedEvent("BalloonClosing", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the BalloonClosing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, BalloonClosingEvent, handler); + } + + /// + /// Removes a handler for the BalloonClosing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, BalloonClosingEvent, handler); + } + + /// + /// A static helper method to raise the BalloonClosing event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + /// The instance that manages the balloon. + internal static RoutedEventArgs RaiseBalloonClosingEvent(DependencyObject target, TaskbarIcon source) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(BalloonClosingEvent, source); + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + //ATTACHED PROPERTIES + + #region ParentTaskbarIcon + + /// + /// An attached property that is assigned to displayed UI elements (balloos, tooltips, context menus), and + /// that can be used to bind to this control. The attached property is being derived, so binding is + /// quite straightforward: + /// + /// + /// + /// + public static readonly DependencyProperty ParentTaskbarIconProperty = + DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof (TaskbarIcon), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); + + /// + /// Gets the ParentTaskbarIcon property. This dependency property + /// indicates .... + /// + public static TaskbarIcon GetParentTaskbarIcon(DependencyObject d) + { + return (TaskbarIcon) d.GetValue(ParentTaskbarIconProperty); + } + + /// + /// Sets the ParentTaskbarIcon property. This dependency property + /// indicates .... + /// + public static void SetParentTaskbarIcon(DependencyObject d, TaskbarIcon value) + { + d.SetValue(ParentTaskbarIconProperty, value); + } + + #endregion + + //BASE CLASS PROPERTY OVERRIDES + + /// + /// Registers properties. + /// + static TaskbarIcon() + { + //register change listener for the Visibility property + var md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); + VisibilityProperty.OverrideMetadata(typeof (TaskbarIcon), md); + + //register change listener for the DataContext property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged)); + DataContextProperty.OverrideMetadata(typeof (TaskbarIcon), md); + + //register change listener for the ContextMenu property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); + ContextMenuProperty.OverrideMetadata(typeof (TaskbarIcon), md); + } } - - - } } \ No newline at end of file From 4179f9f4ece319cb87a57a27fb869b84f041f835 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 17 Nov 2013 14:54:06 +0000 Subject: [PATCH 38/73] FIX Interop using Unicode in order to support for long strings / asian languages. (NTFY-11) git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@182 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/Interop/NotifyIconData.cs | 4 ++-- Source/NotifyIconWpf/Interop/WinApi.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/NotifyIconWpf/Interop/NotifyIconData.cs b/Source/NotifyIconWpf/Interop/NotifyIconData.cs index 81cf0a6..b169b8e 100644 --- a/Source/NotifyIconWpf/Interop/NotifyIconData.cs +++ b/Source/NotifyIconWpf/Interop/NotifyIconData.cs @@ -10,7 +10,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// values of the /// that were defined. ///
- [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct NotifyIconData { /// @@ -134,7 +134,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop { //we need to set another size on xp/2003- otherwise certain //features (e.g. balloon tooltips) don't work. - data.cbSize = 504; + data.cbSize = 952; // NOTIFYICONDATAW_V3_SIZE //set to fixed timeout data.VersionOrTimeout = 10; diff --git a/Source/NotifyIconWpf/Interop/WinApi.cs b/Source/NotifyIconWpf/Interop/WinApi.cs index 2cb96ea..38e7d6a 100644 --- a/Source/NotifyIconWpf/Interop/WinApi.cs +++ b/Source/NotifyIconWpf/Interop/WinApi.cs @@ -11,7 +11,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// /// Creates, updates or deletes the taskbar icon. /// - [DllImport("shell32.Dll")] + [DllImport("shell32.Dll", CharSet = CharSet.Unicode)] public static extern bool Shell_NotifyIcon(NotifyCommand cmd, [In]ref NotifyIconData data); From b10992dc25381787f52003564e55d9933b28c2a5 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 17 Nov 2013 23:03:38 +0000 Subject: [PATCH 39/73] Reformatting code (NTFY-20) git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@183 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.cs | 1938 +++++++++++++-------------- 1 file changed, 967 insertions(+), 971 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 1fde567..ec7eee2 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -32,1010 +32,1006 @@ using System.Windows.Controls.Primitives; using System.Windows.Interop; using System.Windows.Threading; using Hardcodet.Wpf.TaskbarNotification.Interop; -using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point; - +using Point = Hardcodet.Wpf.TaskbarNotification.Interop.Point; namespace Hardcodet.Wpf.TaskbarNotification { - /// - /// A WPF proxy to for a taskbar icon (NotifyIcon) that sits in the system's - /// taskbar notification area ("system tray"). - /// - public partial class TaskbarIcon : FrameworkElement, IDisposable - { - #region Members - /// - /// Represents the current icon data. + /// A WPF proxy to for a taskbar icon (NotifyIcon) that sits in the system's + /// taskbar notification area ("system tray"). /// - private NotifyIconData iconData; - - /// - /// Receives messages from the taskbar icon. - /// - private readonly WindowMessageSink messageSink; - - /// - /// An action that is being invoked if the - /// fires. - /// - private Action delayedTimerAction; - - /// - /// A timer that is used to differentiate between single - /// and double clicks. - /// - private readonly Timer singleClickTimer; - - /// - /// A timer that is used to close open balloon tooltips. - /// - private readonly Timer balloonCloseTimer; - - /// - /// Indicates whether the taskbar icon has been created or not. - /// - public bool IsTaskbarIconCreated { get; private set; } - - /// - /// Indicates whether custom tooltips are supported, which depends - /// on the OS. Windows Vista or higher is required in order to - /// support this feature. - /// - public bool SupportsCustomToolTips + public partial class TaskbarIcon : FrameworkElement, IDisposable { - get { return messageSink.Version == NotifyIconVersion.Vista; } - } + #region Members + /// + /// Represents the current icon data. + /// + private NotifyIconData iconData; + /// + /// Receives messages from the taskbar icon. + /// + private readonly WindowMessageSink messageSink; - /// - /// Checks whether a non-tooltip popup is currently opened. - /// - private bool IsPopupOpen - { - get - { - var popup = TrayPopupResolved; - var menu = ContextMenu; - var balloon = CustomBalloon; + /// + /// An action that is being invoked if the + /// fires. + /// + private Action delayedTimerAction; - return popup != null && popup.IsOpen || - menu != null && menu.IsOpen || - balloon != null && balloon.IsOpen; + /// + /// A timer that is used to differentiate between single + /// and double clicks. + /// + private readonly Timer singleClickTimer; - } - } + /// + /// A timer that is used to close open balloon tooltips. + /// + private readonly Timer balloonCloseTimer; - #endregion + /// + /// Indicates whether the taskbar icon has been created or not. + /// + public bool IsTaskbarIconCreated { get; private set; } - - #region Construction - - /// - /// Inits the taskbar icon and registers a message listener - /// in order to receive events from the taskbar area. - /// - public TaskbarIcon() - { - //using dummy sink in design mode - messageSink = Util.IsDesignMode - ? WindowMessageSink.CreateEmpty() - : new WindowMessageSink(NotifyIconVersion.Win95); - - //init icon data structure - iconData = NotifyIconData.CreateDefault(messageSink.MessageWindowHandle); - - //create the taskbar icon - CreateTaskbarIcon(); - - //register event listeners - messageSink.MouseEventReceived += OnMouseEvent; - messageSink.TaskbarCreated += OnTaskbarCreated; - messageSink.ChangeToolTipStateRequest += OnToolTipChange; - messageSink.BalloonToolTipChanged += OnBalloonToolTipChanged; - - //init single click / balloon timers - singleClickTimer = new Timer(DoSingleClickAction); - balloonCloseTimer = new Timer(CloseBalloonCallback); - - //register listener in order to get notified when the application closes - if (Application.Current != null) Application.Current.Exit += OnExit; - } - - #endregion - - - #region Custom Balloons - - /// - /// Shows a custom control as a tooltip in the tray location. - /// - /// - /// An optional animation for the popup. - /// The time after which the popup is being closed. - /// Submit null in order to keep the balloon open inde - /// - /// If - /// is a null reference. - public void ShowCustomBalloon(UIElement balloon, PopupAnimation animation, int? timeout) - { - Dispatcher dispatcher = this.GetDispatcher(); - if (!dispatcher.CheckAccess()) - { - var action = new Action(() => ShowCustomBalloon(balloon, animation, timeout)); - dispatcher.Invoke(DispatcherPriority.Normal, action); - return; - } - - if (balloon == null) throw new ArgumentNullException("balloon"); - if (timeout.HasValue && timeout < 500) - { - string msg = "Invalid timeout of {0} milliseconds. Timeout must be at least 500 ms"; - msg = String.Format(msg, timeout); - throw new ArgumentOutOfRangeException("timeout", msg); - } - - EnsureNotDisposed(); - - //make sure we don't have an open balloon - lock (this) - { - CloseBalloon(); - } - - //create an invisible popup that hosts the UIElement - Popup popup = new Popup(); - popup.AllowsTransparency = true; - - //provide the popup with the taskbar icon's data context - UpdateDataContext(popup, null, DataContext); - - //don't animate by default - devs can use attached - //events or override - popup.PopupAnimation = animation; - - //in case the balloon is cleaned up through routed events, the - //control didn't removed the balloon from its parent popup when - //if was closed the last time - just make sure it doesn't have - //a parent that is a popup - var parent = LogicalTreeHelper.GetParent(balloon) as Popup; - if (parent != null) parent.Child = null; - - if (parent != null) - { - string msg = - "Cannot display control [{0}] in a new balloon popup - that control already has a parent. You may consider creating new balloons every time you want to show one."; - msg = String.Format(msg, balloon); - throw new InvalidOperationException(msg); - } - - popup.Child = balloon; - - //don't set the PlacementTarget as it causes the popup to become hidden if the - //TaskbarIcon's parent is hidden, too... - //popup.PlacementTarget = this; - - popup.Placement = PlacementMode.AbsolutePoint; - popup.StaysOpen = true; - - Point position = TrayInfo.GetTrayLocation(); - popup.HorizontalOffset = position.X -1; - popup.VerticalOffset = position.Y -1; - - //store reference - lock (this) - { - SetCustomBalloon(popup); - } - - //assign this instance as an attached property - SetParentTaskbarIcon(balloon, this); - - //fire attached event - RaiseBalloonShowingEvent(balloon, this); - - //display item - popup.IsOpen = true; - - if (timeout.HasValue) - { - //register timer to close the popup - balloonCloseTimer.Change(timeout.Value, Timeout.Infinite); - } - } - - - /// - /// Resets the closing timeout, which effectively - /// keeps a displayed balloon message open until - /// it is either closed programmatically through - /// or due to a new - /// message being displayed. - /// - public void ResetBalloonCloseTimer() - { - if (IsDisposed) return; - - lock (this) - { - //reset timer in any case - balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); - } - } - - - /// - /// Closes the current , if the - /// property is set. - /// - public void CloseBalloon() - { - if (IsDisposed) return; - - Dispatcher dispatcher = this.GetDispatcher(); - if (!dispatcher.CheckAccess()) - { - Action action = CloseBalloon; - dispatcher.Invoke(DispatcherPriority.Normal, action); - return; - } - - lock (this) - { - //reset timer in any case - balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); - - //reset old popup, if we still have one - Popup popup = CustomBalloon; - if (popup != null) + /// + /// Indicates whether custom tooltips are supported, which depends + /// on the OS. Windows Vista or higher is required in order to + /// support this feature. + /// + public bool SupportsCustomToolTips { - UIElement element = popup.Child; - - //announce closing - RoutedEventArgs eventArgs = RaiseBalloonClosingEvent(element, this); - if (!eventArgs.Handled) - { - //if the event was handled, clear the reference to the popup, - //but don't close it - the handling code has to manage this stuff now - - //close the popup - popup.IsOpen = false; - - //remove the reference of the popup to the balloon in case we want to reuse - //the balloon (then added to a new popup) - popup.Child = null; - - //reset attached property - if (element != null) SetParentTaskbarIcon(element, null); - } - - //remove custom balloon anyway - SetCustomBalloon(null); - } - } - } - - - /// - /// Timer-invoke event which closes the currently open balloon and - /// resets the dependency property. - /// - private void CloseBalloonCallback(object state) - { - if (IsDisposed) return; - - //switch to UI thread - Action action = CloseBalloon; - this.GetDispatcher().Invoke(action); - } - - #endregion - - #region Process Incoming Mouse Events - - /// - /// Processes mouse events, which are bubbled - /// through the class' routed events, trigger - /// certain actions (e.g. show a popup), or - /// both. - /// - /// Event flag. - private void OnMouseEvent(MouseEvent me) - { - if (IsDisposed) return; - - switch (me) - { - case MouseEvent.MouseMove: - RaiseTrayMouseMoveEvent(); - //immediately return - there's nothing left to evaluate - return; - case MouseEvent.IconRightMouseDown: - RaiseTrayRightMouseDownEvent(); - break; - case MouseEvent.IconLeftMouseDown: - RaiseTrayLeftMouseDownEvent(); - break; - case MouseEvent.IconRightMouseUp: - RaiseTrayRightMouseUpEvent(); - break; - case MouseEvent.IconLeftMouseUp: - RaiseTrayLeftMouseUpEvent(); - break; - case MouseEvent.IconMiddleMouseDown: - RaiseTrayMiddleMouseDownEvent(); - break; - case MouseEvent.IconMiddleMouseUp: - RaiseTrayMiddleMouseUpEvent(); - break; - case MouseEvent.IconDoubleClick: - //cancel single click timer - singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); - //bubble event - RaiseTrayMouseDoubleClickEvent(); - break; - case MouseEvent.BalloonToolTipClicked: - RaiseTrayBalloonTipClickedEvent(); - break; - default: - throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); - } - - - //get mouse coordinates - Point cursorPosition = new Point(); - WinApi.GetCursorPos(ref cursorPosition); - - bool isLeftClickCommandInvoked = false; - - //show popup, if requested - if (me.IsMatch(PopupActivation)) - { - if (me == MouseEvent.IconLeftMouseUp) - { - //show popup once we are sure it's not a double click - delayedTimerAction = () => - { - LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); - ShowTrayPopup(cursorPosition); - }; - singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); - isLeftClickCommandInvoked = true; - } - else - { - //show popup immediately - ShowTrayPopup(cursorPosition); - } - } - - - //show context menu, if requested - if (me.IsMatch(MenuActivation)) - { - if (me == MouseEvent.IconLeftMouseUp) - { - //show context menu once we are sure it's not a double click - delayedTimerAction = () => - { - LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); - ShowContextMenu(cursorPosition); - }; - singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); - isLeftClickCommandInvoked = true; - } - else - { - //show context menu immediately - ShowContextMenu(cursorPosition); - } - } - - //make sure the left click command is invoked on mouse clicks - if (me == MouseEvent.IconLeftMouseUp && !isLeftClickCommandInvoked) - { - //show context menu once we are sure it's not a double click - delayedTimerAction = () => LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); - singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); - } - - } - - #endregion - - #region ToolTips - - /// - /// Displays a custom tooltip, if available. This method is only - /// invoked for Windows Vista and above. - /// - /// Whether to show or hide the tooltip. - private void OnToolTipChange(bool visible) - { - //if we don't have a tooltip, there's nothing to do here... - if (TrayToolTipResolved == null) return; - - if (visible) - { - if (IsPopupOpen) - { - //ignore if we are already displaying something down there - return; + get { return messageSink.Version == NotifyIconVersion.Vista; } } - var args = RaisePreviewTrayToolTipOpenEvent(); - if (args.Handled) return; - TrayToolTipResolved.IsOpen = true; - - //raise attached event first - if (TrayToolTip != null) RaiseToolTipOpenedEvent(TrayToolTip); - - //bubble routed event - RaiseTrayToolTipOpenEvent(); - } - else - { - var args = RaisePreviewTrayToolTipCloseEvent(); - if (args.Handled) return; - - //raise attached event first - if (TrayToolTip != null) RaiseToolTipCloseEvent(TrayToolTip); - - TrayToolTipResolved.IsOpen = false; - - //bubble event - RaiseTrayToolTipCloseEvent(); - } - } - - - /// - /// Creates a control that either - /// wraps the currently set - /// control or the string.
- /// If itself is already - /// a instance, it will be used directly. - ///
- /// We use a rather than - /// because there was no way to prevent a - /// popup from causing cyclic open/close commands if it was - /// placed under the mouse. ToolTip internally uses a Popup of - /// its own, but takes advance of Popup's internal - /// property which prevents this issue. - private void CreateCustomToolTip() - { - //check if the item itself is a tooltip - ToolTip tt = TrayToolTip as ToolTip; - - if (tt == null && TrayToolTip != null) - { - //create an invisible tooltip that hosts the UIElement - tt = new ToolTip(); - tt.Placement = PlacementMode.Mouse; - - //do *not* set the placement target, as it causes the popup to become hidden if the - //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through - //the ParentTaskbarIcon attached dependency property: - //tt.PlacementTarget = this; - - //make sure the tooltip is invisible - tt.HasDropShadow = false; - tt.BorderThickness = new Thickness(0); - tt.Background = System.Windows.Media.Brushes.Transparent; - - //setting the - tt.StaysOpen = true; - tt.Content = TrayToolTip; - } - else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) - { - //create a simple tooltip for the string - tt = new ToolTip(); - tt.Content = ToolTipText; - } - - //the tooltip explicitly gets the DataContext of this instance. - //If there is no DataContext, the TaskbarIcon assigns itself - if (tt != null) - { - UpdateDataContext(tt, null, DataContext); - } - - //store a reference to the used tooltip - SetTrayToolTipResolved(tt); - } - - - /// - /// Sets tooltip settings for the class depending on defined - /// dependency properties and OS support. - /// - private void WriteToolTipSettings() - { - const IconDataMembers flags = IconDataMembers.Tip; - iconData.ToolTipText = ToolTipText; - - if (messageSink.Version == NotifyIconVersion.Vista) - { - //we need to set a tooltip text to get tooltip events from the - //taskbar icon - if (String.IsNullOrEmpty(iconData.ToolTipText) && TrayToolTipResolved != null) + /// + /// Checks whether a non-tooltip popup is currently opened. + /// + private bool IsPopupOpen { - //if we have not tooltip text but a custom tooltip, we - //need to set a dummy value (we're displaying the ToolTip control, not the string) - iconData.ToolTipText = "ToolTip"; - } - } + get + { + var popup = TrayPopupResolved; + var menu = ContextMenu; + var balloon = CustomBalloon; - //update the tooltip text - Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); - } - - #endregion - - #region Custom Popup - - /// - /// Creates a control that either - /// wraps the currently set - /// control or the string.
- /// If itself is already - /// a instance, it will be used directly. - ///
- /// We use a rather than - /// because there was no way to prevent a - /// popup from causing cyclic open/close commands if it was - /// placed under the mouse. ToolTip internally uses a Popup of - /// its own, but takes advance of Popup's internal - /// property which prevents this issue. - private void CreatePopup() - { - //check if the item itself is a popup - Popup popup = TrayPopup as Popup; - - if (popup == null && TrayPopup != null) - { - //create an invisible popup that hosts the UIElement - popup = new Popup(); - popup.AllowsTransparency = true; - - //don't animate by default - devs can use attached - //events or override - popup.PopupAnimation = PopupAnimation.None; - - //the CreateRootPopup method outputs binding errors in the debug window because - //it tries to bind to "Popup-specific" properties in case they are provided by the child. - //We don't need that so just assign the control as the child. - popup.Child = TrayPopup; - - //do *not* set the placement target, as it causes the popup to become hidden if the - //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through - //the ParentTaskbarIcon attached dependency property: - //popup.PlacementTarget = this; - - popup.Placement = PlacementMode.AbsolutePoint; - popup.StaysOpen = false; - } - - //the popup explicitly gets the DataContext of this instance. - //If there is no DataContext, the TaskbarIcon assigns itself - if (popup != null) - { - UpdateDataContext(popup, null, DataContext); - } - - //store a reference to the used tooltip - SetTrayPopupResolved(popup); - } - - - /// - /// Displays the control if - /// it was set. - /// - private void ShowTrayPopup(Point cursorPosition) - { - if (IsDisposed) return; - - //raise preview event no matter whether popup is currently set - //or not (enables client to set it on demand) - var args = RaisePreviewTrayPopupOpenEvent(); - if (args.Handled) return; - - if (TrayPopup != null) - { - //use absolute position, but place the popup centered above the icon - TrayPopupResolved.Placement = PlacementMode.AbsolutePoint; - TrayPopupResolved.HorizontalOffset = cursorPosition.X; - TrayPopupResolved.VerticalOffset = cursorPosition.Y; - - //open popup - TrayPopupResolved.IsOpen = true; - - - IntPtr handle = IntPtr.Zero; - if (TrayPopupResolved.Child != null) - { - //try to get a handle on the popup itself (via its child) - HwndSource source = (HwndSource)PresentationSource.FromVisual(TrayPopupResolved.Child); - if (source != null) handle = source.Handle; + return popup != null && popup.IsOpen || + menu != null && menu.IsOpen || + balloon != null && balloon.IsOpen; + } } - //if we don't have a handle for the popup, fall back to the message sink - if (handle == IntPtr.Zero) handle = messageSink.MessageWindowHandle; + #endregion - //activate either popup or message sink to track deactivation. - //otherwise, the popup does not close if the user clicks somewhere else - WinApi.SetForegroundWindow(handle); + #region Construction - //raise attached event - item should never be null unless developers - //changed the CustomPopup directly... - if (TrayPopup != null) RaisePopupOpenedEvent(TrayPopup); - - //bubble routed event - RaiseTrayPopupOpenEvent(); - } - } - - #endregion - - #region Context Menu - - /// - /// Displays the if - /// it was set. - /// - private void ShowContextMenu(Point cursorPosition) - { - if (IsDisposed) return; - - //raise preview event no matter whether context menu is currently set - //or not (enables client to set it on demand) - var args = RaisePreviewTrayContextMenuOpenEvent(); - if (args.Handled) return; - - if (ContextMenu != null) - { - //use absolute positioning. We need to set the coordinates, or a delayed opening - //(e.g. when left-clicked) opens the context menu at the wrong place if the mouse - //is moved! - ContextMenu.Placement = PlacementMode.AbsolutePoint; - ContextMenu.HorizontalOffset = cursorPosition.X; - ContextMenu.VerticalOffset = cursorPosition.Y; - ContextMenu.IsOpen = true; - - //activate the message window to track deactivation - otherwise, the context menu - //does not close if the user clicks somewhere else - WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); - - //bubble event - RaiseTrayContextMenuOpenEvent(); - } - } - - #endregion - - #region Balloon Tips - - /// - /// Bubbles events if a balloon ToolTip was displayed - /// or removed. - /// - /// Whether the ToolTip was just displayed - /// or removed. - private void OnBalloonToolTipChanged(bool visible) - { - if (visible) - { - RaiseTrayBalloonTipShownEvent(); - } - else - { - RaiseTrayBalloonTipClosedEvent(); - } - } - - /// - /// Displays a balloon tip with the specified title, - /// text, and icon in the taskbar for the specified time period. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// A symbol that indicates the severity. - public void ShowBalloonTip(string title, string message, BalloonIcon symbol) - { - lock (this) - { - ShowBalloonTip(title, message, symbol.GetBalloonFlag(), IntPtr.Zero); - } - } - - - /// - /// Displays a balloon tip with the specified title, - /// text, and a custom icon in the taskbar for the specified time period. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// A custom icon. - /// If - /// is a null reference. - public void ShowBalloonTip(string title, string message, Icon customIcon) - { - if (customIcon == null) throw new ArgumentNullException("customIcon"); - - lock (this) - { - ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); - } - } - - - /// - /// Invokes in order to display - /// a given balloon ToolTip. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// Indicates what icon to use. - /// A handle to a custom icon, if any, or - /// . - private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) - { - EnsureNotDisposed(); - - iconData.BalloonText = message ?? String.Empty; - iconData.BalloonTitle = title ?? String.Empty; - - iconData.BalloonFlags = flags; - iconData.CustomBalloonIconHandle = balloonIconHandle; - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info | IconDataMembers.Icon); - } - - - /// - /// Hides a balloon ToolTip, if any is displayed. - /// - public void HideBalloonTip() - { - EnsureNotDisposed(); - - //reset balloon by just setting the info to an empty string - iconData.BalloonText = iconData.BalloonTitle = String.Empty; - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); - } - - #endregion - - #region Single Click Timer event - - /// - /// Performs a delayed action if the user requested an action - /// based on a single click of the left mouse.
- /// This method is invoked by the . - ///
- private void DoSingleClickAction(object state) - { - if (IsDisposed) return; - - //run action - Action action = delayedTimerAction; - if (action != null) - { - //cleanup action - delayedTimerAction = null; - - //switch to UI thread - this.GetDispatcher().Invoke(action); - } - } - - #endregion - - #region Set Version (API) - - /// - /// Sets the version flag for the . - /// - private void SetVersion() - { - iconData.VersionOrTimeout = (uint) NotifyIconVersion.Vista; - bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); - - if (!status) - { - iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win2000; - status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); - } - - if (!status) - { - iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win95; - status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); - } - - if (!status) - { - Debug.Fail("Could not set version"); - } - } - - #endregion - - #region Create / Remove Taskbar Icon - - /// - /// Recreates the taskbar icon if the whole taskbar was - /// recreated (e.g. because Explorer was shut down). - /// - private void OnTaskbarCreated() - { - IsTaskbarIconCreated = false; - CreateTaskbarIcon(); - } - - - /// - /// Creates the taskbar icon. This message is invoked during initialization, - /// if the taskbar is restarted, and whenever the icon is displayed. - /// - private void CreateTaskbarIcon() - { - lock (this) - { - if (!IsTaskbarIconCreated) + /// + /// Inits the taskbar icon and registers a message listener + /// in order to receive events from the taskbar area. + /// + public TaskbarIcon() { - const IconDataMembers members = IconDataMembers.Message - | IconDataMembers.Icon - | IconDataMembers.Tip; + //using dummy sink in design mode + messageSink = Util.IsDesignMode + ? WindowMessageSink.CreateEmpty() + : new WindowMessageSink(NotifyIconVersion.Win95); - //write initial configuration - var status = Util.WriteIconData(ref iconData, NotifyCommand.Add, members); - if (!status) - { - //couldn't create the icon - we can assume this is because explorer is not running (yet!) - //-> try a bit later again rather than throwing an exception. Typically, if the windows - // shell is being loaded later, this method is being reinvoked from OnTaskbarCreated - // (we could also retry after a delay, but that's currently YAGNI) - return; - } + //init icon data structure + iconData = NotifyIconData.CreateDefault(messageSink.MessageWindowHandle); - //set to most recent version - SetVersion(); - messageSink.Version = (NotifyIconVersion) iconData.VersionOrTimeout; + //create the taskbar icon + CreateTaskbarIcon(); - IsTaskbarIconCreated = true; - } - } - } + //register event listeners + messageSink.MouseEventReceived += OnMouseEvent; + messageSink.TaskbarCreated += OnTaskbarCreated; + messageSink.ChangeToolTipStateRequest += OnToolTipChange; + messageSink.BalloonToolTipChanged += OnBalloonToolTipChanged; - /// - /// Closes the taskbar icon if required. - /// - private void RemoveTaskbarIcon() - { - lock (this) - { - //make sure we didn't schedule a creation + //init single click / balloon timers + singleClickTimer = new Timer(DoSingleClickAction); + balloonCloseTimer = new Timer(CloseBalloonCallback); - if (IsTaskbarIconCreated) - { - Util.WriteIconData(ref iconData, NotifyCommand.Delete, IconDataMembers.Message); - IsTaskbarIconCreated = false; - } - } - } - - #endregion - - #region Dispose / Exit - - /// - /// Set to true as soon as - /// has been invoked. - /// - public bool IsDisposed { get; private set; } - - - /// - /// Checks if the object has been disposed and - /// raises a in case - /// the flag is true. - /// - private void EnsureNotDisposed() - { - if (IsDisposed) throw new ObjectDisposedException(Name ?? GetType().FullName); - } - - - /// - /// Disposes the class if the application exits. - /// - private void OnExit(object sender, EventArgs e) - { - Dispose(); - } - - - /// - /// This destructor will run only if the - /// method does not get called. This gives this base class the - /// opportunity to finalize. - /// - /// Important: Do not provide destructors in types derived from - /// this class. - /// - /// - ~TaskbarIcon() - { - Dispose(false); - } - - - /// - /// Disposes the object. - /// - /// This method is not virtual by design. Derived classes - /// should override . - /// - public void Dispose() - { - Dispose(true); - - // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SupressFinalize to - // take this object off the finalization queue - // and prevent finalization code for this object - // from executing a second time. - GC.SuppressFinalize(this); - } - - - /// - /// Closes the tray and releases all resources. - /// - /// - /// Dispose(bool disposing) executes in two distinct scenarios. - /// If disposing equals true, the method has been called directly - /// or indirectly by a user's code. Managed and unmanaged resources - /// can be disposed. - /// - /// If disposing equals false, the method - /// has been called by the runtime from inside the finalizer and you - /// should not reference other objects. Only unmanaged resources can - /// be disposed. - /// Check the property to determine whether - /// the method has already been called. - private void Dispose(bool disposing) - { - //don't do anything if the component is already disposed - if (IsDisposed || !disposing) return; - - lock (this) - { - IsDisposed = true; - - //deregister application event listener - if (Application.Current != null) - { - Application.Current.Exit -= OnExit; + //register listener in order to get notified when the application closes + if (Application.Current != null) Application.Current.Exit += OnExit; } - //stop timers - singleClickTimer.Dispose(); - balloonCloseTimer.Dispose(); + #endregion - //dispose message sink - messageSink.Dispose(); + #region Custom Balloons - //remove icon - RemoveTaskbarIcon(); - } + /// + /// Shows a custom control as a tooltip in the tray location. + /// + /// + /// An optional animation for the popup. + /// The time after which the popup is being closed. + /// Submit null in order to keep the balloon open inde + /// + /// If + /// is a null reference. + public void ShowCustomBalloon(UIElement balloon, PopupAnimation animation, int? timeout) + { + Dispatcher dispatcher = this.GetDispatcher(); + if (!dispatcher.CheckAccess()) + { + var action = new Action(() => ShowCustomBalloon(balloon, animation, timeout)); + dispatcher.Invoke(DispatcherPriority.Normal, action); + return; + } + + if (balloon == null) throw new ArgumentNullException("balloon"); + if (timeout.HasValue && timeout < 500) + { + string msg = "Invalid timeout of {0} milliseconds. Timeout must be at least 500 ms"; + msg = String.Format(msg, timeout); + throw new ArgumentOutOfRangeException("timeout", msg); + } + + EnsureNotDisposed(); + + //make sure we don't have an open balloon + lock (this) + { + CloseBalloon(); + } + + //create an invisible popup that hosts the UIElement + Popup popup = new Popup(); + popup.AllowsTransparency = true; + + //provide the popup with the taskbar icon's data context + UpdateDataContext(popup, null, DataContext); + + //don't animate by default - devs can use attached + //events or override + popup.PopupAnimation = animation; + + //in case the balloon is cleaned up through routed events, the + //control didn't removed the balloon from its parent popup when + //if was closed the last time - just make sure it doesn't have + //a parent that is a popup + var parent = LogicalTreeHelper.GetParent(balloon) as Popup; + if (parent != null) parent.Child = null; + + if (parent != null) + { + string msg = + "Cannot display control [{0}] in a new balloon popup - that control already has a parent. You may consider creating new balloons every time you want to show one."; + msg = String.Format(msg, balloon); + throw new InvalidOperationException(msg); + } + + popup.Child = balloon; + + //don't set the PlacementTarget as it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too... + //popup.PlacementTarget = this; + + popup.Placement = PlacementMode.AbsolutePoint; + popup.StaysOpen = true; + + Point position = TrayInfo.GetTrayLocation(); + popup.HorizontalOffset = position.X - 1; + popup.VerticalOffset = position.Y - 1; + + //store reference + lock (this) + { + SetCustomBalloon(popup); + } + + //assign this instance as an attached property + SetParentTaskbarIcon(balloon, this); + + //fire attached event + RaiseBalloonShowingEvent(balloon, this); + + //display item + popup.IsOpen = true; + + if (timeout.HasValue) + { + //register timer to close the popup + balloonCloseTimer.Change(timeout.Value, Timeout.Infinite); + } + } + + + /// + /// Resets the closing timeout, which effectively + /// keeps a displayed balloon message open until + /// it is either closed programmatically through + /// or due to a new + /// message being displayed. + /// + public void ResetBalloonCloseTimer() + { + if (IsDisposed) return; + + lock (this) + { + //reset timer in any case + balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + } + + + /// + /// Closes the current , if the + /// property is set. + /// + public void CloseBalloon() + { + if (IsDisposed) return; + + Dispatcher dispatcher = this.GetDispatcher(); + if (!dispatcher.CheckAccess()) + { + Action action = CloseBalloon; + dispatcher.Invoke(DispatcherPriority.Normal, action); + return; + } + + lock (this) + { + //reset timer in any case + balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); + + //reset old popup, if we still have one + Popup popup = CustomBalloon; + if (popup != null) + { + UIElement element = popup.Child; + + //announce closing + RoutedEventArgs eventArgs = RaiseBalloonClosingEvent(element, this); + if (!eventArgs.Handled) + { + //if the event was handled, clear the reference to the popup, + //but don't close it - the handling code has to manage this stuff now + + //close the popup + popup.IsOpen = false; + + //remove the reference of the popup to the balloon in case we want to reuse + //the balloon (then added to a new popup) + popup.Child = null; + + //reset attached property + if (element != null) SetParentTaskbarIcon(element, null); + } + + //remove custom balloon anyway + SetCustomBalloon(null); + } + } + } + + + /// + /// Timer-invoke event which closes the currently open balloon and + /// resets the dependency property. + /// + private void CloseBalloonCallback(object state) + { + if (IsDisposed) return; + + //switch to UI thread + Action action = CloseBalloon; + this.GetDispatcher().Invoke(action); + } + + #endregion + + #region Process Incoming Mouse Events + + /// + /// Processes mouse events, which are bubbled + /// through the class' routed events, trigger + /// certain actions (e.g. show a popup), or + /// both. + /// + /// Event flag. + private void OnMouseEvent(MouseEvent me) + { + if (IsDisposed) return; + + switch (me) + { + case MouseEvent.MouseMove: + RaiseTrayMouseMoveEvent(); + //immediately return - there's nothing left to evaluate + return; + case MouseEvent.IconRightMouseDown: + RaiseTrayRightMouseDownEvent(); + break; + case MouseEvent.IconLeftMouseDown: + RaiseTrayLeftMouseDownEvent(); + break; + case MouseEvent.IconRightMouseUp: + RaiseTrayRightMouseUpEvent(); + break; + case MouseEvent.IconLeftMouseUp: + RaiseTrayLeftMouseUpEvent(); + break; + case MouseEvent.IconMiddleMouseDown: + RaiseTrayMiddleMouseDownEvent(); + break; + case MouseEvent.IconMiddleMouseUp: + RaiseTrayMiddleMouseUpEvent(); + break; + case MouseEvent.IconDoubleClick: + //cancel single click timer + singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); + //bubble event + RaiseTrayMouseDoubleClickEvent(); + break; + case MouseEvent.BalloonToolTipClicked: + RaiseTrayBalloonTipClickedEvent(); + break; + default: + throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); + } + + + //get mouse coordinates + Point cursorPosition = new Point(); + WinApi.GetCursorPos(ref cursorPosition); + + bool isLeftClickCommandInvoked = false; + + //show popup, if requested + if (me.IsMatch(PopupActivation)) + { + if (me == MouseEvent.IconLeftMouseUp) + { + //show popup once we are sure it's not a double click + delayedTimerAction = () => + { + LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); + ShowTrayPopup(cursorPosition); + }; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + isLeftClickCommandInvoked = true; + } + else + { + //show popup immediately + ShowTrayPopup(cursorPosition); + } + } + + + //show context menu, if requested + if (me.IsMatch(MenuActivation)) + { + if (me == MouseEvent.IconLeftMouseUp) + { + //show context menu once we are sure it's not a double click + delayedTimerAction = () => + { + LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); + ShowContextMenu(cursorPosition); + }; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + isLeftClickCommandInvoked = true; + } + else + { + //show context menu immediately + ShowContextMenu(cursorPosition); + } + } + + //make sure the left click command is invoked on mouse clicks + if (me == MouseEvent.IconLeftMouseUp && !isLeftClickCommandInvoked) + { + //show context menu once we are sure it's not a double click + delayedTimerAction = + () => LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + } + } + + #endregion + + #region ToolTips + + /// + /// Displays a custom tooltip, if available. This method is only + /// invoked for Windows Vista and above. + /// + /// Whether to show or hide the tooltip. + private void OnToolTipChange(bool visible) + { + //if we don't have a tooltip, there's nothing to do here... + if (TrayToolTipResolved == null) return; + + if (visible) + { + if (IsPopupOpen) + { + //ignore if we are already displaying something down there + return; + } + + var args = RaisePreviewTrayToolTipOpenEvent(); + if (args.Handled) return; + + TrayToolTipResolved.IsOpen = true; + + //raise attached event first + if (TrayToolTip != null) RaiseToolTipOpenedEvent(TrayToolTip); + + //bubble routed event + RaiseTrayToolTipOpenEvent(); + } + else + { + var args = RaisePreviewTrayToolTipCloseEvent(); + if (args.Handled) return; + + //raise attached event first + if (TrayToolTip != null) RaiseToolTipCloseEvent(TrayToolTip); + + TrayToolTipResolved.IsOpen = false; + + //bubble event + RaiseTrayToolTipCloseEvent(); + } + } + + + /// + /// Creates a control that either + /// wraps the currently set + /// control or the string.
+ /// If itself is already + /// a instance, it will be used directly. + ///
+ /// We use a rather than + /// because there was no way to prevent a + /// popup from causing cyclic open/close commands if it was + /// placed under the mouse. ToolTip internally uses a Popup of + /// its own, but takes advance of Popup's internal + /// property which prevents this issue. + private void CreateCustomToolTip() + { + //check if the item itself is a tooltip + ToolTip tt = TrayToolTip as ToolTip; + + if (tt == null && TrayToolTip != null) + { + //create an invisible tooltip that hosts the UIElement + tt = new ToolTip(); + tt.Placement = PlacementMode.Mouse; + + //do *not* set the placement target, as it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through + //the ParentTaskbarIcon attached dependency property: + //tt.PlacementTarget = this; + + //make sure the tooltip is invisible + tt.HasDropShadow = false; + tt.BorderThickness = new Thickness(0); + tt.Background = System.Windows.Media.Brushes.Transparent; + + //setting the + tt.StaysOpen = true; + tt.Content = TrayToolTip; + } + else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) + { + //create a simple tooltip for the string + tt = new ToolTip(); + tt.Content = ToolTipText; + } + + //the tooltip explicitly gets the DataContext of this instance. + //If there is no DataContext, the TaskbarIcon assigns itself + if (tt != null) + { + UpdateDataContext(tt, null, DataContext); + } + + //store a reference to the used tooltip + SetTrayToolTipResolved(tt); + } + + + /// + /// Sets tooltip settings for the class depending on defined + /// dependency properties and OS support. + /// + private void WriteToolTipSettings() + { + const IconDataMembers flags = IconDataMembers.Tip; + iconData.ToolTipText = ToolTipText; + + if (messageSink.Version == NotifyIconVersion.Vista) + { + //we need to set a tooltip text to get tooltip events from the + //taskbar icon + if (String.IsNullOrEmpty(iconData.ToolTipText) && TrayToolTipResolved != null) + { + //if we have not tooltip text but a custom tooltip, we + //need to set a dummy value (we're displaying the ToolTip control, not the string) + iconData.ToolTipText = "ToolTip"; + } + } + + //update the tooltip text + Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); + } + + #endregion + + #region Custom Popup + + /// + /// Creates a control that either + /// wraps the currently set + /// control or the string.
+ /// If itself is already + /// a instance, it will be used directly. + ///
+ /// We use a rather than + /// because there was no way to prevent a + /// popup from causing cyclic open/close commands if it was + /// placed under the mouse. ToolTip internally uses a Popup of + /// its own, but takes advance of Popup's internal + /// property which prevents this issue. + private void CreatePopup() + { + //check if the item itself is a popup + Popup popup = TrayPopup as Popup; + + if (popup == null && TrayPopup != null) + { + //create an invisible popup that hosts the UIElement + popup = new Popup(); + popup.AllowsTransparency = true; + + //don't animate by default - devs can use attached + //events or override + popup.PopupAnimation = PopupAnimation.None; + + //the CreateRootPopup method outputs binding errors in the debug window because + //it tries to bind to "Popup-specific" properties in case they are provided by the child. + //We don't need that so just assign the control as the child. + popup.Child = TrayPopup; + + //do *not* set the placement target, as it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through + //the ParentTaskbarIcon attached dependency property: + //popup.PlacementTarget = this; + + popup.Placement = PlacementMode.AbsolutePoint; + popup.StaysOpen = false; + } + + //the popup explicitly gets the DataContext of this instance. + //If there is no DataContext, the TaskbarIcon assigns itself + if (popup != null) + { + UpdateDataContext(popup, null, DataContext); + } + + //store a reference to the used tooltip + SetTrayPopupResolved(popup); + } + + + /// + /// Displays the control if + /// it was set. + /// + private void ShowTrayPopup(Point cursorPosition) + { + if (IsDisposed) return; + + //raise preview event no matter whether popup is currently set + //or not (enables client to set it on demand) + var args = RaisePreviewTrayPopupOpenEvent(); + if (args.Handled) return; + + if (TrayPopup != null) + { + //use absolute position, but place the popup centered above the icon + TrayPopupResolved.Placement = PlacementMode.AbsolutePoint; + TrayPopupResolved.HorizontalOffset = cursorPosition.X; + TrayPopupResolved.VerticalOffset = cursorPosition.Y; + + //open popup + TrayPopupResolved.IsOpen = true; + + + IntPtr handle = IntPtr.Zero; + if (TrayPopupResolved.Child != null) + { + //try to get a handle on the popup itself (via its child) + HwndSource source = (HwndSource) PresentationSource.FromVisual(TrayPopupResolved.Child); + if (source != null) handle = source.Handle; + } + + //if we don't have a handle for the popup, fall back to the message sink + if (handle == IntPtr.Zero) handle = messageSink.MessageWindowHandle; + + //activate either popup or message sink to track deactivation. + //otherwise, the popup does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(handle); + + //raise attached event - item should never be null unless developers + //changed the CustomPopup directly... + if (TrayPopup != null) RaisePopupOpenedEvent(TrayPopup); + + //bubble routed event + RaiseTrayPopupOpenEvent(); + } + } + + #endregion + + #region Context Menu + + /// + /// Displays the if + /// it was set. + /// + private void ShowContextMenu(Point cursorPosition) + { + if (IsDisposed) return; + + //raise preview event no matter whether context menu is currently set + //or not (enables client to set it on demand) + var args = RaisePreviewTrayContextMenuOpenEvent(); + if (args.Handled) return; + + if (ContextMenu != null) + { + //use absolute positioning. We need to set the coordinates, or a delayed opening + //(e.g. when left-clicked) opens the context menu at the wrong place if the mouse + //is moved! + ContextMenu.Placement = PlacementMode.AbsolutePoint; + ContextMenu.HorizontalOffset = cursorPosition.X; + ContextMenu.VerticalOffset = cursorPosition.Y; + + ContextMenu.IsOpen = true; + + //activate the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); + + //bubble event + RaiseTrayContextMenuOpenEvent(); + } + } + + #endregion + + #region Balloon Tips + + /// + /// Bubbles events if a balloon ToolTip was displayed + /// or removed. + /// + /// Whether the ToolTip was just displayed + /// or removed. + private void OnBalloonToolTipChanged(bool visible) + { + if (visible) + { + RaiseTrayBalloonTipShownEvent(); + } + else + { + RaiseTrayBalloonTipClosedEvent(); + } + } + + /// + /// Displays a balloon tip with the specified title, + /// text, and icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A symbol that indicates the severity. + public void ShowBalloonTip(string title, string message, BalloonIcon symbol) + { + lock (this) + { + ShowBalloonTip(title, message, symbol.GetBalloonFlag(), IntPtr.Zero); + } + } + + + /// + /// Displays a balloon tip with the specified title, + /// text, and a custom icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A custom icon. + /// If + /// is a null reference. + public void ShowBalloonTip(string title, string message, Icon customIcon) + { + if (customIcon == null) throw new ArgumentNullException("customIcon"); + + lock (this) + { + ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); + } + } + + + /// + /// Invokes in order to display + /// a given balloon ToolTip. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// Indicates what icon to use. + /// A handle to a custom icon, if any, or + /// . + private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) + { + EnsureNotDisposed(); + + iconData.BalloonText = message ?? String.Empty; + iconData.BalloonTitle = title ?? String.Empty; + + iconData.BalloonFlags = flags; + iconData.CustomBalloonIconHandle = balloonIconHandle; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info | IconDataMembers.Icon); + } + + + /// + /// Hides a balloon ToolTip, if any is displayed. + /// + public void HideBalloonTip() + { + EnsureNotDisposed(); + + //reset balloon by just setting the info to an empty string + iconData.BalloonText = iconData.BalloonTitle = String.Empty; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + } + + #endregion + + #region Single Click Timer event + + /// + /// Performs a delayed action if the user requested an action + /// based on a single click of the left mouse.
+ /// This method is invoked by the . + ///
+ private void DoSingleClickAction(object state) + { + if (IsDisposed) return; + + //run action + Action action = delayedTimerAction; + if (action != null) + { + //cleanup action + delayedTimerAction = null; + + //switch to UI thread + this.GetDispatcher().Invoke(action); + } + } + + #endregion + + #region Set Version (API) + + /// + /// Sets the version flag for the . + /// + private void SetVersion() + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Vista; + bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); + + if (!status) + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win2000; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win95; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + Debug.Fail("Could not set version"); + } + } + + #endregion + + #region Create / Remove Taskbar Icon + + /// + /// Recreates the taskbar icon if the whole taskbar was + /// recreated (e.g. because Explorer was shut down). + /// + private void OnTaskbarCreated() + { + IsTaskbarIconCreated = false; + CreateTaskbarIcon(); + } + + + /// + /// Creates the taskbar icon. This message is invoked during initialization, + /// if the taskbar is restarted, and whenever the icon is displayed. + /// + private void CreateTaskbarIcon() + { + lock (this) + { + if (!IsTaskbarIconCreated) + { + const IconDataMembers members = IconDataMembers.Message + | IconDataMembers.Icon + | IconDataMembers.Tip; + + //write initial configuration + var status = Util.WriteIconData(ref iconData, NotifyCommand.Add, members); + if (!status) + { + //couldn't create the icon - we can assume this is because explorer is not running (yet!) + //-> try a bit later again rather than throwing an exception. Typically, if the windows + // shell is being loaded later, this method is being reinvoked from OnTaskbarCreated + // (we could also retry after a delay, but that's currently YAGNI) + return; + } + + //set to most recent version + SetVersion(); + messageSink.Version = (NotifyIconVersion) iconData.VersionOrTimeout; + + IsTaskbarIconCreated = true; + } + } + } + + /// + /// Closes the taskbar icon if required. + /// + private void RemoveTaskbarIcon() + { + lock (this) + { + //make sure we didn't schedule a creation + + if (IsTaskbarIconCreated) + { + Util.WriteIconData(ref iconData, NotifyCommand.Delete, IconDataMembers.Message); + IsTaskbarIconCreated = false; + } + } + } + + #endregion + + #region Dispose / Exit + + /// + /// Set to true as soon as + /// has been invoked. + /// + public bool IsDisposed { get; private set; } + + + /// + /// Checks if the object has been disposed and + /// raises a in case + /// the flag is true. + /// + private void EnsureNotDisposed() + { + if (IsDisposed) throw new ObjectDisposedException(Name ?? GetType().FullName); + } + + + /// + /// Disposes the class if the application exits. + /// + private void OnExit(object sender, EventArgs e) + { + Dispose(); + } + + + /// + /// This destructor will run only if the + /// method does not get called. This gives this base class the + /// opportunity to finalize. + /// + /// Important: Do not provide destructors in types derived from + /// this class. + /// + /// + ~TaskbarIcon() + { + Dispose(false); + } + + + /// + /// Disposes the object. + /// + /// This method is not virtual by design. Derived classes + /// should override . + /// + public void Dispose() + { + Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + + /// + /// Closes the tray and releases all resources. + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// + /// If disposing equals false, the method + /// has been called by the runtime from inside the finalizer and you + /// should not reference other objects. Only unmanaged resources can + /// be disposed. + /// Check the property to determine whether + /// the method has already been called. + private void Dispose(bool disposing) + { + //don't do anything if the component is already disposed + if (IsDisposed || !disposing) return; + + lock (this) + { + IsDisposed = true; + + //deregister application event listener + if (Application.Current != null) + { + Application.Current.Exit -= OnExit; + } + + //stop timers + singleClickTimer.Dispose(); + balloonCloseTimer.Dispose(); + + //dispose message sink + messageSink.Dispose(); + + //remove icon + RemoveTaskbarIcon(); + } + } + + #endregion } - - #endregion - } } \ No newline at end of file From 16ef216a4c2bc64028b9fa64c0c8d23c2f79398d Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 17 Nov 2013 23:10:18 +0000 Subject: [PATCH 40/73] FIX Activating context menu itself rather than messagesink window, in order for the menu to receive keyboard input (NTFY-3). git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@184 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index ec7eee2..c227d62 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -703,9 +703,22 @@ namespace Hardcodet.Wpf.TaskbarNotification ContextMenu.IsOpen = true; - //activate the message window to track deactivation - otherwise, the context menu - //does not close if the user clicks somewhere else - WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); + IntPtr handle = IntPtr.Zero; + + //try to get a handle on the context itself + HwndSource source = (HwndSource)PresentationSource.FromVisual(ContextMenu); + if (source != null) + { + handle = source.Handle; + } + + //if we don't have a handle for the popup, fall back to the message sink + if (handle == IntPtr.Zero) handle = messageSink.MessageWindowHandle; + + //activate the context menu or the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else. With the message window + //fallback, the context menu can't receive keyboard events - should not happen though + WinApi.SetForegroundWindow(handle); //bubble event RaiseTrayContextMenuOpenEvent(); From f756fcc8a3b7a78806dc845955e39c3add1a1659 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 17 Nov 2013 23:40:37 +0000 Subject: [PATCH 41/73] FIX Referencing context menu as dynamic resource loses data context somehow. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@185 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Sample Project/Showcase/NotifyIconResources.xaml | 6 +++--- Source/Sample Project/Showcase/ShowcaseWindow.xaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Sample Project/Showcase/NotifyIconResources.xaml b/Source/Sample Project/Showcase/NotifyIconResources.xaml index ba1ea49..1ccfe31 100644 --- a/Source/Sample Project/Showcase/NotifyIconResources.xaml +++ b/Source/Sample Project/Showcase/NotifyIconResources.xaml @@ -28,10 +28,10 @@ - + Date: Sun, 17 Nov 2013 23:43:26 +0000 Subject: [PATCH 42/73] CHG Reformatting. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@186 9f600761-6f11-4665-b6dc-0185e9171623 --- .../Showcase/NotifyIconResources.xaml | 138 +++++++++--------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/Source/Sample Project/Showcase/NotifyIconResources.xaml b/Source/Sample Project/Showcase/NotifyIconResources.xaml index 1ccfe31..7154629 100644 --- a/Source/Sample Project/Showcase/NotifyIconResources.xaml +++ b/Source/Sample Project/Showcase/NotifyIconResources.xaml @@ -1,78 +1,80 @@ - - - - - - - - + + + + + - - + - - - - - - + + + + + + - - - - - - - + + + + + - - - - - - + + + + + + + + \ No newline at end of file From 19f4f8717ca2019eed35a35606af4a28f6048ea6 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 17 Nov 2013 23:47:44 +0000 Subject: [PATCH 43/73] CHG Better ContextMenu tutorial sample. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@187 9f600761-6f11-4665-b6dc-0185e9171623 --- .../InlineContextMenuWindow.xaml | 96 ++++++++++++++----- .../InlineContextMenuWindow.xaml.cs | 59 ++++++------ 2 files changed, 106 insertions(+), 49 deletions(-) diff --git a/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml b/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml index 7338e68..a5e8da1 100644 --- a/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml +++ b/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml @@ -1,27 +1,79 @@ - - + + - + - - - - - - - + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs b/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs index fea9324..6c156b5 100644 --- a/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs +++ b/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs @@ -1,35 +1,40 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Diagnostics; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; namespace Samples.Tutorials.ContextMenus { - /// - /// Interaction logic for InlineContextMenuWindow.xaml - /// - public partial class InlineContextMenuWindow : Window - { - public InlineContextMenuWindow() + /// + /// Interaction logic for InlineContextMenuWindow.xaml + /// + public partial class InlineContextMenuWindow : Window { - InitializeComponent(); + public InlineContextMenuWindow() + { + InitializeComponent(); + } + + + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) + { + //clean up notifyicon (would otherwise stay open until application finishes) + MyNotifyIcon.Dispose(); + + base.OnClosing(e); + } + + private void MyNotifyIcon_TrayContextMenuOpen(object sender, System.Windows.RoutedEventArgs e) + { + OpenEventCounter.Text = (int.Parse(OpenEventCounter.Text) + 1).ToString(); + } + + private void MyNotifyIcon_PreviewTrayContextMenuOpen(object sender, System.Windows.RoutedEventArgs e) + { + //marking the event as handled suppresses the context menu + e.Handled = (bool)SuppressContextMenu.IsChecked; + + PreviewOpenEventCounter.Text = (int.Parse(PreviewOpenEventCounter.Text) + 1).ToString(); + } } - - - protected override void OnClosing(System.ComponentModel.CancelEventArgs e) - { - //clean up notifyicon (would otherwise stay open until application finishes) - MyNotifyIcon.Dispose(); - - base.OnClosing(e); - } - } -} +} \ No newline at end of file From 0424c62f17d8721034fc34f86f445340c683504c Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sun, 17 Nov 2013 23:51:06 +0000 Subject: [PATCH 44/73] CHG Migrated WinForms sample to .NET 4. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@188 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/WindowsFormsSample/FancyPopup.xaml | 3 +- Source/WindowsFormsSample/FancyPopup.xaml.cs | 3 +- Source/WindowsFormsSample/Form1.cs | 9 +--- Source/WindowsFormsSample/Program.cs | 3 +- .../Properties/Resources.Designer.cs | 7 ++- .../Properties/Settings.Designer.cs | 34 ++++++------ .../WindowsFormsSample.csproj | 54 ++++++++++++++++--- 7 files changed, 71 insertions(+), 42 deletions(-) diff --git a/Source/WindowsFormsSample/FancyPopup.xaml b/Source/WindowsFormsSample/FancyPopup.xaml index efba38f..b021f27 100644 --- a/Source/WindowsFormsSample/FancyPopup.xaml +++ b/Source/WindowsFormsSample/FancyPopup.xaml @@ -110,6 +110,5 @@ - - + diff --git a/Source/WindowsFormsSample/FancyPopup.xaml.cs b/Source/WindowsFormsSample/FancyPopup.xaml.cs index c50f34f..9b940d1 100644 --- a/Source/WindowsFormsSample/FancyPopup.xaml.cs +++ b/Source/WindowsFormsSample/FancyPopup.xaml.cs @@ -1,12 +1,11 @@ using System.Windows; -using System.Windows.Controls; namespace Samples { /// /// Interaction logic for FancyPopup.xaml /// - public partial class FancyPopup : UserControl + public partial class FancyPopup { #region ClickCount dependency property diff --git a/Source/WindowsFormsSample/Form1.cs b/Source/WindowsFormsSample/Form1.cs index 93a7e2d..9cf870a 100644 --- a/Source/WindowsFormsSample/Form1.cs +++ b/Source/WindowsFormsSample/Form1.cs @@ -1,10 +1,4 @@ using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; using System.Windows; using System.Windows.Forms; using Hardcodet.Wpf.TaskbarNotification; @@ -37,7 +31,8 @@ namespace WindowsFormsSample { base.OnClosed(e); - //close the notify icon + //the notify icon only closes automatically on WPF applications + //-> dispose the notify icon manually notifyIcon.Dispose(); } } diff --git a/Source/WindowsFormsSample/Program.cs b/Source/WindowsFormsSample/Program.cs index cefff3c..921a50d 100644 --- a/Source/WindowsFormsSample/Program.cs +++ b/Source/WindowsFormsSample/Program.cs @@ -1,7 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Windows.Forms; +using Samples; namespace WindowsFormsSample { diff --git a/Source/WindowsFormsSample/Properties/Resources.Designer.cs b/Source/WindowsFormsSample/Properties/Resources.Designer.cs index 47cb61f..4dc5ac7 100644 --- a/Source/WindowsFormsSample/Properties/Resources.Designer.cs +++ b/Source/WindowsFormsSample/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.3074 +// Runtime Version:4.0.30319.18408 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -19,7 +19,7 @@ namespace WindowsFormsSample.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -60,6 +60,9 @@ namespace WindowsFormsSample.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// internal static System.Drawing.Icon Led { get { object obj = ResourceManager.GetObject("Led", resourceCulture); diff --git a/Source/WindowsFormsSample/Properties/Settings.Designer.cs b/Source/WindowsFormsSample/Properties/Settings.Designer.cs index 12508d3..2a00ed0 100644 --- a/Source/WindowsFormsSample/Properties/Settings.Designer.cs +++ b/Source/WindowsFormsSample/Properties/Settings.Designer.cs @@ -1,30 +1,26 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.3074 +// Runtime Version:4.0.30319.18408 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ -namespace WindowsFormsSample.Properties -{ - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { - return defaultInstance; - } +namespace WindowsFormsSample.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } } - } } diff --git a/Source/WindowsFormsSample/WindowsFormsSample.csproj b/Source/WindowsFormsSample/WindowsFormsSample.csproj index 6e5677f..6ee8d4e 100644 --- a/Source/WindowsFormsSample/WindowsFormsSample.csproj +++ b/Source/WindowsFormsSample/WindowsFormsSample.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,9 +10,29 @@ Properties WindowsFormsSample WindowsFormsSample - v3.5 + v4.0 512 WindowsFormsSample.Program + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + Client true @@ -22,6 +42,7 @@ DEBUG;TRACE prompt 4 + AllRules.ruleset pdbonly @@ -30,18 +51,16 @@ TRACE prompt 4 + AllRules.ruleset - - 3.0 - - - 3.0 - + + 3.5 + 3.5 @@ -99,6 +118,8 @@ MSBuild:Compile Designer + MSBuild:Compile + Designer @@ -113,6 +134,23 @@ + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + - + - - - - + + + + - - - - + + + + - + + + + - - - + + + + WPF NotifyIcon + + + + + + + + + + + + - - - - - + x:Class="Samples.FancyPopup" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:tb="http://www.hardcodet.net/taskbar" + Height="215" + Width="300" x:Name="me"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/Source/WindowsFormsSample/FancyPopup.xaml.cs b/Source/WindowsFormsSample/FancyPopup.xaml.cs index 9b940d1..6799925 100644 --- a/Source/WindowsFormsSample/FancyPopup.xaml.cs +++ b/Source/WindowsFormsSample/FancyPopup.xaml.cs @@ -2,44 +2,44 @@ namespace Samples { - /// - /// Interaction logic for FancyPopup.xaml - /// - public partial class FancyPopup - { - #region ClickCount dependency property - /// - /// The number of clicks on the popup button. + /// Interaction logic for FancyPopup.xaml /// - public static readonly DependencyProperty ClickCountProperty = - DependencyProperty.Register("ClickCount", - typeof (int), - typeof (FancyPopup), - new FrameworkPropertyMetadata(0)); - - /// - /// A property wrapper for the - /// dependency property:
- /// The number of clicks on the popup button. - ///
- public int ClickCount + public partial class FancyPopup { - get { return (int) GetValue(ClickCountProperty); } - set { SetValue(ClickCountProperty, value); } - } + #region ClickCount dependency property - #endregion + /// + /// The number of clicks on the popup button. + /// + public static readonly DependencyProperty ClickCountProperty = + DependencyProperty.Register("ClickCount", + typeof (int), + typeof (FancyPopup), + new FrameworkPropertyMetadata(0)); - public FancyPopup() - { - InitializeComponent(); - } + /// + /// A property wrapper for the + /// dependency property:
+ /// The number of clicks on the popup button. + ///
+ public int ClickCount + { + get { return (int) GetValue(ClickCountProperty); } + set { SetValue(ClickCountProperty, value); } + } - private void OnButtonClick(object sender, RoutedEventArgs e) - { - //just increment a counter - will be displayed on screen - ClickCount++; + #endregion + + public FancyPopup() + { + InitializeComponent(); + } + + private void OnButtonClick(object sender, RoutedEventArgs e) + { + //just increment a counter - will be displayed on screen + ClickCount++; + } } - } } \ No newline at end of file diff --git a/Source/WindowsFormsSample/Form1.cs b/Source/WindowsFormsSample/Form1.cs index 9cf870a..52da957 100644 --- a/Source/WindowsFormsSample/Form1.cs +++ b/Source/WindowsFormsSample/Form1.cs @@ -7,33 +7,33 @@ using WindowsFormsSample.Properties; namespace WindowsFormsSample { - public partial class Form1 : Form - { - private TaskbarIcon notifyIcon; - - public Form1() + public partial class Form1 : Form { - InitializeComponent(); + private TaskbarIcon notifyIcon; + + public Form1() + { + InitializeComponent(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + notifyIcon = new TaskbarIcon(); + notifyIcon.Icon = Resources.Led; + notifyIcon.ToolTipText = "Left-click to open popup"; + notifyIcon.Visibility = Visibility.Visible; + + notifyIcon.TrayPopup = new FancyPopup(); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + + //the notify icon only closes automatically on WPF applications + //-> dispose the notify icon manually + notifyIcon.Dispose(); + } } - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - notifyIcon = new TaskbarIcon(); - notifyIcon.Icon = Resources.Led; - notifyIcon.ToolTipText = "Left-click to open popup"; - notifyIcon.Visibility = Visibility.Visible; - - notifyIcon.TrayPopup = new FancyPopup(); - } - - protected override void OnClosed(EventArgs e) - { - base.OnClosed(e); - - //the notify icon only closes automatically on WPF applications - //-> dispose the notify icon manually - notifyIcon.Dispose(); - } - } -} +} \ No newline at end of file diff --git a/Source/WindowsFormsSample/Program.cs b/Source/WindowsFormsSample/Program.cs index 921a50d..b155e0a 100644 --- a/Source/WindowsFormsSample/Program.cs +++ b/Source/WindowsFormsSample/Program.cs @@ -4,17 +4,17 @@ using Samples; namespace WindowsFormsSample { - static class Program - { - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main() + internal static class Program { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new Form1()); + /// + /// The main entry point for the application. + /// + [STAThread] + private static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } } - } -} +} \ No newline at end of file diff --git a/Source/WindowsFormsSample/Properties/AssemblyInfo.cs b/Source/WindowsFormsSample/Properties/AssemblyInfo.cs index b32abd5..3ba7613 100644 --- a/Source/WindowsFormsSample/Properties/AssemblyInfo.cs +++ b/Source/WindowsFormsSample/Properties/AssemblyInfo.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. + [assembly: AssemblyTitle("WindowsFormsSample")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -17,9 +18,11 @@ using System.Runtime.InteropServices; // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. + [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM + [assembly: Guid("072bbfa0-9b8b-48df-bf88-3e4806b3e3e8")] // Version information for an assembly consists of the following four values: @@ -32,5 +35,6 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] + [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/Source/WindowsFormsSample/Properties/Settings.settings b/Source/WindowsFormsSample/Properties/Settings.settings index abf36c5..eeb7df0 100644 --- a/Source/WindowsFormsSample/Properties/Settings.settings +++ b/Source/WindowsFormsSample/Properties/Settings.settings @@ -1,7 +1,8 @@  + - + \ No newline at end of file From 4eb48c8bd7050aef96f5870b1f23104f5a90d8c0 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Fri, 22 Nov 2013 19:10:11 +0000 Subject: [PATCH 49/73] CHG Minor sample improvements. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@193 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Sample Project/App.xaml | 22 +++++++++---------- Source/Sample Project/Sample Project.csproj | 1 + .../SimpleWindowWithNotifyIcon.xaml | 17 +++++++------- .../03 - Popups/InlinePopupWindow.xaml | 3 +++ 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Source/Sample Project/App.xaml b/Source/Sample Project/App.xaml index e4e63cf..11ae36c 100644 --- a/Source/Sample Project/App.xaml +++ b/Source/Sample Project/App.xaml @@ -1,14 +1,14 @@  + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + StartupUri="Main.xaml"> - - - - - - - + + + + + + + - + \ No newline at end of file diff --git a/Source/Sample Project/Sample Project.csproj b/Source/Sample Project/Sample Project.csproj index 491f845..d268001 100644 --- a/Source/Sample Project/Sample Project.csproj +++ b/Source/Sample Project/Sample Project.csproj @@ -99,6 +99,7 @@ MSBuild:Compile Designer + FancyToolTip.xaml diff --git a/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml b/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml index 146c78d..acc53fe 100644 --- a/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml +++ b/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml @@ -7,15 +7,14 @@ Width="300"> - - - - - + + + + \ No newline at end of file diff --git a/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml b/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml index 1b18323..9645b30 100644 --- a/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml +++ b/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml @@ -3,6 +3,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:tb="http://www.hardcodet.net/taskbar" + xmlns:commands="clr-namespace:Samples.Commands" Height="300" Width="300"> @@ -32,6 +33,8 @@ Text="Enter Text..." />
- 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; From cb3721ce48e41b678d7c1b070de7d3f84ab5a8a7 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Fri, 22 Nov 2013 23:03:56 +0000 Subject: [PATCH 51/73] FIX ToolTipText changes update an existing wrapper ToolTip, if there is already one. NTFY-23 git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@195 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.Declarations.cs | 16 +++++++++++++--- Source/NotifyIconWpf/TaskbarIcon.cs | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 2956ce4..4b72aeb 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -298,10 +298,20 @@ namespace Hardcodet.Wpf.TaskbarNotification /// Provides information about the updated property. private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e) { - //only recreate tooltip if we're not using a custom control - if (TrayToolTipResolved == null || TrayToolTipResolved.Content is string) + //do not touch tooltips if we have a custom tooltip element + if (TrayToolTip == null) { - CreateCustomToolTip(); + ToolTip currentToolTip = TrayToolTipResolved; + if (currentToolTip == null) + { + //if we don't have a wrapper tooltip for the tooltip text, create it now + CreateCustomToolTip(); + } + else + { + //if we have a wrapper tooltip that shows the old tooltip text, just update content + currentToolTip.Content = e.NewValue; + } } WriteToolTipSettings(); diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index e01b0c0..f9bb617 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -522,7 +522,7 @@ namespace Hardcodet.Wpf.TaskbarNotification if (tt == null && TrayToolTip != null) { - //create an invisible tooltip that hosts the UIElement + //create an invisible wrapper tooltip that hosts the UIElement tt = new ToolTip(); tt.Placement = PlacementMode.Mouse; @@ -542,7 +542,7 @@ namespace Hardcodet.Wpf.TaskbarNotification } else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) { - //create a simple tooltip for the string + //create a simple tooltip for the ToolTipText string tt = new ToolTip(); tt.Content = ToolTipText; } From 6fa0462adc7738f5ac51ff2d26a64465373ad7c3 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Fri, 22 Nov 2013 23:05:08 +0000 Subject: [PATCH 52/73] CHG Formatting only. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@196 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/NotifyIconWpf/TaskbarIcon.Declarations.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 4b72aeb..56bd376 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -380,15 +380,13 @@ namespace Hardcodet.Wpf.TaskbarNotification //remove the taskbar icon reference from the previously used element SetParentTaskbarIcon((DependencyObject) e.OldValue, null); } - - + if (e.NewValue != null) { //set this taskbar icon as a reference to the new tooltip element SetParentTaskbarIcon((DependencyObject) e.NewValue, this); } - - + //update tooltip settings - needed to make sure a string is set, even //if the ToolTipText property is not set. Otherwise, the event that //triggers tooltip display is never fired. From 6ae24d3c2380c3c3bc803baf1e679f7c7aec655a Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Fri, 22 Nov 2013 23:35:36 +0000 Subject: [PATCH 53/73] XAML formatting. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@197 9f600761-6f11-4665-b6dc-0185e9171623 --- .../DataBoundToolTipWindow.xaml | 108 ++++++++---------- 1 file changed, 49 insertions(+), 59 deletions(-) diff --git a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml index 32337b0..8dc64f8 100644 --- a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml +++ b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml @@ -1,35 +1,31 @@ - + - + - - + + @@ -37,34 +33,31 @@ - + - - + - + HorizontalAlignment="Center" + VerticalAlignment="Center" /> @@ -72,29 +65,26 @@ - + - - - + + + From e0f4d731caef5dd0e8286fbc8c428995911bcab1 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Fri, 22 Nov 2013 23:37:09 +0000 Subject: [PATCH 54/73] ADD MVVM Sample. NTFY-24 git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@198 9f600761-6f11-4665-b6dc-0185e9171623 --- Source/Sample Project/Main.xaml | 20 ++++++--- Source/Sample Project/Main.xaml.cs | 6 +++ Source/Sample Project/Sample Project.csproj | 18 +++++++++ .../Tutorials/09 - MVVM/Clock.png | Bin 0 -> 20374 bytes .../Tutorials/09 - MVVM/ClockPopup.xaml | 37 +++++++++++++++++ .../Tutorials/09 - MVVM/ClockPopup.xaml.cs | 15 +++++++ .../09 - MVVM/MvvmSampleViewModel.cs | 38 ++++++++++++++++++ .../Tutorials/09 - MVVM/MvvmSampleWindow.xaml | 37 +++++++++++++++++ .../09 - MVVM/MvvmSampleWindow.xaml.cs | 15 +++++++ 9 files changed, 180 insertions(+), 6 deletions(-) create mode 100644 Source/Sample Project/Tutorials/09 - MVVM/Clock.png create mode 100644 Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml create mode 100644 Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml.cs create mode 100644 Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleViewModel.cs create mode 100644 Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml create mode 100644 Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml.cs diff --git a/Source/Sample Project/Main.xaml b/Source/Sample Project/Main.xaml index 969eac6..e8010df 100644 --- a/Source/Sample Project/Main.xaml +++ b/Source/Sample Project/Main.xaml @@ -3,11 +3,11 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="NotifyIcon Samples" - Height="563" + Height="626" Width="703" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - mc:Ignorable="d"> + mc:Ignorable="d" ResizeMode="NoResize"> @@ -118,12 +118,11 @@ x:Name="btnToolTipControl" Click="btnToolTipControl_Click" /> + HorizontalAlignment="Left" Width="110.93"> @@ -207,7 +206,7 @@ Height="1" Data="M11,517 L561.07363,517" Opacity="0.33" /> Info = 0x10, - /// - /// Internal identifier is set. Reserved, thus commented out. - /// + // Internal identifier is set. Reserved, thus commented out. //Guid = 0x20, + /// /// Windows Vista (Shell32.dll version 6.0.6) and later. If the ToolTip /// cannot be displayed immediately, discard it.
diff --git a/Source/NotifyIconWpf/Interop/IconState.cs b/Source/NotifyIconWpf/Interop/IconState.cs index 627eaee..9238dd0 100644 --- a/Source/NotifyIconWpf/Interop/IconState.cs +++ b/Source/NotifyIconWpf/Interop/IconState.cs @@ -16,9 +16,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop ///
Hidden = 0x01, - /// - /// The icon is shared - currently not supported, thus commented out. - /// + // The icon is shared - currently not supported, thus commented out. //Shared = 0x02 } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/Point.cs b/Source/NotifyIconWpf/Interop/Point.cs index 2c1f5bb..39e3e5e 100644 --- a/Source/NotifyIconWpf/Interop/Point.cs +++ b/Source/NotifyIconWpf/Interop/Point.cs @@ -8,7 +8,13 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop [StructLayout(LayoutKind.Sequential)] public struct Point { + /// + /// X coordinate. + /// public int X; + /// + /// Y coordinate. + /// public int Y; } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowClass.cs b/Source/NotifyIconWpf/Interop/WindowClass.cs index c3bc6f4..8757f04 100644 --- a/Source/NotifyIconWpf/Interop/WindowClass.cs +++ b/Source/NotifyIconWpf/Interop/WindowClass.cs @@ -17,6 +17,8 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop [StructLayout(LayoutKind.Sequential)] public struct WindowClass { + #pragma warning disable 1591 + public uint style; public WindowProcedureHandler lpfnWndProc; public int cbClsExtra; @@ -27,5 +29,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop public IntPtr hbrBackground; [MarshalAs(UnmanagedType.LPWStr)] public string lpszMenuName; [MarshalAs(UnmanagedType.LPWStr)] public string lpszClassName; + + #pragma warning restore 1591 } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index b134f88..fc21af9 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -71,7 +71,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop /// /// Handle for the message window. - /// internal IntPtr MessageWindowHandle { get; private set; } /// @@ -309,8 +309,7 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop #region Dispose /// - /// Set to true as soon as - /// has been invoked. + /// Set to true as soon as Dispose has been invoked. /// public bool IsDisposed { get; private set; } diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index 3e60352..b0e4bb7 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -142,6 +142,9 @@ namespace Hardcodet.Wpf.TaskbarNotification = DependencyProperty.RegisterReadOnly("CustomBalloon", typeof (Popup), typeof (TaskbarIcon), new FrameworkPropertyMetadata(null)); + /// + /// Maintains a currently displayed custom balloon. + /// public static readonly DependencyProperty CustomBalloonProperty = CustomBalloonPropertyKey.DependencyProperty; diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index a205e0f..0ce67de 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -514,7 +514,7 @@ namespace Hardcodet.Wpf.TaskbarNotification /// because there was no way to prevent a /// popup from causing cyclic open/close commands if it was /// placed under the mouse. ToolTip internally uses a Popup of - /// its own, but takes advance of Popup's internal + /// its own, but takes advance of Popup's internal /// property which prevents this issue. private void CreateCustomToolTip() { @@ -600,7 +600,7 @@ namespace Hardcodet.Wpf.TaskbarNotification /// because there was no way to prevent a /// popup from causing cyclic open/close commands if it was /// placed under the mouse. ToolTip internally uses a Popup of - /// its own, but takes advance of Popup's internal + /// its own, but takes advance of Popup's internal /// property which prevents this issue. private void CreatePopup() { @@ -986,8 +986,7 @@ namespace Hardcodet.Wpf.TaskbarNotification #region Dispose / Exit /// - /// Set to true as soon as - /// has been invoked. + /// Set to true as soon as Dispose has been invoked. /// public bool IsDisposed { get; private set; } From 3f5fd9284efb598c6dd694ef8c76913cc1fba72c Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Sat, 23 Nov 2013 18:22:31 +0000 Subject: [PATCH 68/73] FIX Adding missing sample command. git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@212 9f600761-6f11-4665-b6dc-0185e9171623 --- .../Commands/CloseWindowCommand.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Source/Sample Project/Commands/CloseWindowCommand.cs diff --git a/Source/Sample Project/Commands/CloseWindowCommand.cs b/Source/Sample Project/Commands/CloseWindowCommand.cs new file mode 100644 index 0000000..2b47832 --- /dev/null +++ b/Source/Sample Project/Commands/CloseWindowCommand.cs @@ -0,0 +1,24 @@ +using System.Windows; +using System.Windows.Input; + +namespace Samples.Commands +{ + /// + /// Closes the current window. + /// + public class CloseWindowCommand : CommandBase + { + public override void Execute(object parameter) + { + GetTaskbarWindow(parameter).Close(); + CommandManager.InvalidateRequerySuggested(); + } + + + public override bool CanExecute(object parameter) + { + Window win = GetTaskbarWindow(parameter); + return win != null; + } + } +} \ No newline at end of file From e409e784e6bfa27af5013d552bb2961d894fdec0 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Mon, 25 Nov 2013 14:15:05 +0100 Subject: [PATCH 69/73] DEL Deleting VS cache file. --- Source/NotifyIconWpf.sln.cache | 166 --------------------------------- 1 file changed, 166 deletions(-) delete mode 100644 Source/NotifyIconWpf.sln.cache diff --git a/Source/NotifyIconWpf.sln.cache b/Source/NotifyIconWpf.sln.cache deleted file mode 100644 index 90cddce..0000000 --- a/Source/NotifyIconWpf.sln.cache +++ /dev/null @@ -1,166 +0,0 @@ - - - <_SolutionProjectConfiguration>Debug|Any CPU - <_SolutionProjectToolsVersion>3.5 - <_SolutionProjectCacheVersion>3.5 - - - <_SolutionProjectProjects Include="NotifyIconWpf\NotifyIconWpf.csproj" /> - <_SolutionProjectProjects Include="Sample Project\Sample Project.csproj" /> - - - - Debug - AnyCPU - - - Debug - AnyCPU - - - - - Release - AnyCPU - - - Release - AnyCPU - - - - - - Debug - - - Any CPU - - - $(Configuration) - - - D:\Philipp\Repositories\evolve.net\WPF\NotifyIcon\Source\ - .sln - NotifyIconWpf.sln - NotifyIconWpf - D:\Philipp\Repositories\evolve.net\WPF\NotifyIcon\Source\NotifyIconWpf.sln - - - v2.0 - v3.5 - - - - - Debug|AnyCPU - Debug|AnyCPU - - - - - - - Release|AnyCPU - Release|AnyCPU - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 3cde71e26b7ee283c5d0a988cf7fc1e6b59664bd Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Mon, 25 Nov 2013 15:26:50 +0100 Subject: [PATCH 70/73] ADD Initial files. --- .gitattributes | 63 ++++++++++++++++++++ .gitignore | 156 +++++++++++++++++++++++++++++++++++++++++++++++++ README | 1 + 3 files changed, 220 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 README diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bc915c --- /dev/null +++ b/.gitignore @@ -0,0 +1,156 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/README b/README new file mode 100644 index 0000000..a539e4b --- /dev/null +++ b/README @@ -0,0 +1 @@ +Notify Icon WPF \ No newline at end of file From 6b07fab72589f497846751d1a4f1964ab23cee45 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Mon, 25 Nov 2013 15:43:33 +0100 Subject: [PATCH 71/73] CHG Moved files to new root folder. --- .../NuGet}/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec | 0 .../Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec | 0 .../Legacy Switch/readme.from.legacy.package.txt | 0 .../NuGet}/readme.1.0.5.txt | 0 .../Source}/BuildTargets.cmd | 0 .../Source}/Changelog.txt | 0 .../Source}/Cleanup_Solution_For_Deployment.bat | 0 .../Source}/NotifyIconWpf.sln | 0 .../Source}/NotifyIconWpf/BalloonIcon.cs | 0 .../NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd | 0 .../Source}/NotifyIconWpf/Interop/BalloonFlags.cs | 0 .../NotifyIconWpf/Interop/IconDataMembers.cs | 0 .../Source}/NotifyIconWpf/Interop/IconState.cs | 0 .../Source}/NotifyIconWpf/Interop/MouseEvent.cs | 0 .../Source}/NotifyIconWpf/Interop/NotifyCommand.cs | 0 .../Source}/NotifyIconWpf/Interop/NotifyIconData.cs | 0 .../NotifyIconWpf/Interop/NotifyIconVersion.cs | 0 .../Source}/NotifyIconWpf/Interop/Point.cs | 0 .../Source}/NotifyIconWpf/Interop/TrayInfo.cs | 0 .../Source}/NotifyIconWpf/Interop/WinApi.cs | 0 .../Source}/NotifyIconWpf/Interop/WindowClass.cs | 0 .../NotifyIconWpf/Interop/WindowMessageSink.cs | 0 .../Source}/NotifyIconWpf/NotifyIconWpf.csproj | 0 .../Source}/NotifyIconWpf/PopupActivationMode.cs | 0 .../NotifyIconWpf/Properties/AssemblyInfo.cs | 0 .../Source}/NotifyIconWpf/RoutedEventHelper.cs | 0 .../NotifyIconWpf/TaskbarIcon.Declarations.cs | 0 .../Source}/NotifyIconWpf/TaskbarIcon.cs | 0 .../Source}/NotifyIconWpf/Util.cs | 0 .../Source}/Sample Project/App.xaml | 0 .../Source}/Sample Project/App.xaml.cs | 0 .../Sample Project/Commands/CloseWindowCommand.cs | 0 .../Source}/Sample Project/Commands/CommandBase.cs | 0 .../Commands/HideSampleWindowCommand.cs | 0 .../Commands/ShowSampleWindowCommand.cs | 0 .../Source}/Sample Project/Icons/Bulb.ico | Bin .../Source}/Sample Project/Icons/Computers.ico | Bin .../Source}/Sample Project/Icons/Error.ico | Bin .../Source}/Sample Project/Icons/Inactive.ico | Bin .../Source}/Sample Project/Icons/NetDrives.ico | Bin .../Source}/Sample Project/Images/Add.png | Bin .../Source}/Sample Project/Images/Close.png | Bin .../Source}/Sample Project/Images/Info.png | Bin .../Source}/Sample Project/Images/Logo.png | Bin .../Source}/Sample Project/Images/Preferences.png | Bin .../Source}/Sample Project/Images/Remove.png | Bin .../Source}/Sample Project/Main.xaml | 0 .../Source}/Sample Project/Main.xaml.cs | 0 .../Sample Project/Properties/AssemblyInfo.cs | 0 .../Sample Project/Properties/Resources.Designer.cs | 0 .../Sample Project/Properties/Resources.resx | 0 .../Sample Project/Properties/Settings.Designer.cs | 0 .../Sample Project/Properties/Settings.settings | 0 .../Source}/Sample Project/Sample Project.csproj | 0 .../Sample Project/Showcase/FancyBalloon.xaml | 0 .../Sample Project/Showcase/FancyBalloon.xaml.cs | 0 .../Source}/Sample Project/Showcase/FancyPopup.xaml | 0 .../Sample Project/Showcase/FancyPopup.xaml.cs | 0 .../Sample Project/Showcase/FancyToolTip.xaml | 0 .../Sample Project/Showcase/FancyToolTip.xaml.cs | 0 .../Showcase/NotifyIconResources.xaml | 0 .../Sample Project/Showcase/ShowcaseWindow.xaml | 0 .../Sample Project/Showcase/ShowcaseWindow.xaml.cs | 0 .../Sample Project/Showcase/WelcomeBalloon.xaml | 0 .../Sample Project/Showcase/WelcomeBalloon.xaml.cs | 0 .../NotifyIconResourceDictionary.xaml | 0 .../SimpleWindowWithNotifyIcon.xaml | 0 .../SimpleWindowWithNotifyIcon.xaml.cs | 0 .../02 - ToolTips/InlineToolTipWindow.xaml | 0 .../02 - ToolTips/InlineToolTipWindow.xaml.cs | 0 .../Tutorials/02 - ToolTips/SimpleUserControl.xaml | 0 .../02 - ToolTips/SimpleUserControl.xaml.cs | 0 .../02 - ToolTips/UserControlToolTipWindow.xaml | 0 .../02 - ToolTips/UserControlToolTipWindow.xaml.cs | 0 .../Tutorials/03 - Popups/InlinePopupWindow.xaml | 0 .../Tutorials/03 - Popups/InlinePopupWindow.xaml.cs | 0 .../04 - ContextMenus/InlineContextMenuWindow.xaml | 0 .../InlineContextMenuWindow.xaml.cs | 0 .../05 - Balloons/BalloonSampleWindow.xaml | 0 .../05 - Balloons/BalloonSampleWindow.xaml.cs | 0 .../Tutorials/06 - Commands/CommandWindow.xaml | 0 .../Tutorials/06 - Commands/CommandWindow.xaml.cs | 0 .../Tutorials/06 - Commands/ShowMessageCommand.cs | 0 .../07 - Events/EventVisualizerWindow.xaml | 0 .../07 - Events/EventVisualizerWindow.xaml.cs | 0 .../08 - DataBinding/DataBoundToolTipWindow.xaml | 0 .../08 - DataBinding/DataBoundToolTipWindow.xaml.cs | 0 .../Sample Project/Tutorials/09 - MVVM/Clock.png | Bin .../Tutorials/09 - MVVM/ClockPopup.xaml | 0 .../Tutorials/09 - MVVM/ClockPopup.xaml.cs | 0 .../Tutorials/09 - MVVM/MvvmSampleViewModel.cs | 0 .../Tutorials/09 - MVVM/MvvmSampleWindow.xaml | 0 .../Tutorials/09 - MVVM/MvvmSampleWindow.xaml.cs | 0 .../Source}/Windowless Sample/App.xaml | 0 .../Source}/Windowless Sample/App.xaml.cs | 0 .../Source}/Windowless Sample/MainWindow.xaml | 0 .../Source}/Windowless Sample/MainWindow.xaml.cs | 0 .../Windowless Sample/NotifyIconResources.xaml | 0 .../Windowless Sample/NotifyIconViewModel.cs | 0 .../Windowless Sample/Properties/AssemblyInfo.cs | 0 .../Source}/Windowless Sample/Red.ico | Bin .../Windowless Sample/Windowless Sample.csproj | 0 .../Source}/WindowsFormsSample/FancyPopup.xaml | 0 .../Source}/WindowsFormsSample/FancyPopup.xaml.cs | 0 .../Source}/WindowsFormsSample/Form1.Designer.cs | 0 .../Source}/WindowsFormsSample/Form1.cs | 0 .../Source}/WindowsFormsSample/Form1.resx | 0 .../Source}/WindowsFormsSample/Icon/Led.ico | Bin .../WindowsFormsSample/Images/Preferences.png | Bin .../Source}/WindowsFormsSample/Program.cs | 0 .../WindowsFormsSample/Properties/AssemblyInfo.cs | 0 .../Properties/Resources.Designer.cs | 0 .../WindowsFormsSample/Properties/Resources.resx | 0 .../Properties/Settings.Designer.cs | 0 .../WindowsFormsSample/Properties/Settings.settings | 0 .../WindowsFormsSample/WindowsFormsSample.csproj | 0 116 files changed, 0 insertions(+), 0 deletions(-) rename {NuGet => Hardcodet.NotifyIcon.Wpf/NuGet}/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec (100%) rename {NuGet => Hardcodet.NotifyIcon.Wpf/NuGet}/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec (100%) rename {NuGet => Hardcodet.NotifyIcon.Wpf/NuGet}/Legacy Switch/readme.from.legacy.package.txt (100%) rename {NuGet => Hardcodet.NotifyIcon.Wpf/NuGet}/readme.1.0.5.txt (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/BuildTargets.cmd (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Changelog.txt (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Cleanup_Solution_For_Deployment.bat (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf.sln (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/BalloonIcon.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/BalloonFlags.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/IconDataMembers.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/IconState.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/MouseEvent.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/NotifyCommand.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/NotifyIconData.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/NotifyIconVersion.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/Point.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/TrayInfo.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/WinApi.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/WindowClass.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Interop/WindowMessageSink.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/NotifyIconWpf.csproj (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/PopupActivationMode.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Properties/AssemblyInfo.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/RoutedEventHelper.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/TaskbarIcon.Declarations.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/TaskbarIcon.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/NotifyIconWpf/Util.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/App.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/App.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Commands/CloseWindowCommand.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Commands/CommandBase.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Commands/HideSampleWindowCommand.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Commands/ShowSampleWindowCommand.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Icons/Bulb.ico (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Icons/Computers.ico (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Icons/Error.ico (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Icons/Inactive.ico (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Icons/NetDrives.ico (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Images/Add.png (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Images/Close.png (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Images/Info.png (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Images/Logo.png (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Images/Preferences.png (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Images/Remove.png (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Main.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Main.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Properties/AssemblyInfo.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Properties/Resources.Designer.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Properties/Resources.resx (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Properties/Settings.Designer.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Properties/Settings.settings (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Sample Project.csproj (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/FancyBalloon.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/FancyBalloon.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/FancyPopup.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/FancyPopup.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/FancyToolTip.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/FancyToolTip.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/NotifyIconResources.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/ShowcaseWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/ShowcaseWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/WelcomeBalloon.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Showcase/WelcomeBalloon.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/01 - Declaration/NotifyIconResourceDictionary.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/06 - Commands/ShowMessageCommand.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/09 - MVVM/Clock.png (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/09 - MVVM/MvvmSampleViewModel.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/App.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/App.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/MainWindow.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/MainWindow.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/NotifyIconResources.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/NotifyIconViewModel.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/Properties/AssemblyInfo.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/Red.ico (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/Windowless Sample/Windowless Sample.csproj (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/FancyPopup.xaml (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/FancyPopup.xaml.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Form1.Designer.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Form1.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Form1.resx (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Icon/Led.ico (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Images/Preferences.png (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Program.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Properties/AssemblyInfo.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Properties/Resources.Designer.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Properties/Resources.resx (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Properties/Settings.Designer.cs (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/Properties/Settings.settings (100%) rename {Source => Hardcodet.NotifyIcon.Wpf/Source}/WindowsFormsSample/WindowsFormsSample.csproj (100%) diff --git a/NuGet/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec b/Hardcodet.NotifyIcon.Wpf/NuGet/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec similarity index 100% rename from NuGet/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec rename to Hardcodet.NotifyIcon.Wpf/NuGet/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec diff --git a/NuGet/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec b/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec similarity index 100% rename from NuGet/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec rename to Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec diff --git a/NuGet/Legacy Switch/readme.from.legacy.package.txt b/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/readme.from.legacy.package.txt similarity index 100% rename from NuGet/Legacy Switch/readme.from.legacy.package.txt rename to Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/readme.from.legacy.package.txt diff --git a/NuGet/readme.1.0.5.txt b/Hardcodet.NotifyIcon.Wpf/NuGet/readme.1.0.5.txt similarity index 100% rename from NuGet/readme.1.0.5.txt rename to Hardcodet.NotifyIcon.Wpf/NuGet/readme.1.0.5.txt diff --git a/Source/BuildTargets.cmd b/Hardcodet.NotifyIcon.Wpf/Source/BuildTargets.cmd similarity index 100% rename from Source/BuildTargets.cmd rename to Hardcodet.NotifyIcon.Wpf/Source/BuildTargets.cmd diff --git a/Source/Changelog.txt b/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt similarity index 100% rename from Source/Changelog.txt rename to Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt diff --git a/Source/Cleanup_Solution_For_Deployment.bat b/Hardcodet.NotifyIcon.Wpf/Source/Cleanup_Solution_For_Deployment.bat similarity index 100% rename from Source/Cleanup_Solution_For_Deployment.bat rename to Hardcodet.NotifyIcon.Wpf/Source/Cleanup_Solution_For_Deployment.bat diff --git a/Source/NotifyIconWpf.sln b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf.sln similarity index 100% rename from Source/NotifyIconWpf.sln rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf.sln diff --git a/Source/NotifyIconWpf/BalloonIcon.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/BalloonIcon.cs similarity index 100% rename from Source/NotifyIconWpf/BalloonIcon.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/BalloonIcon.cs diff --git a/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd similarity index 100% rename from Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd diff --git a/Source/NotifyIconWpf/Interop/BalloonFlags.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/BalloonFlags.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/BalloonFlags.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/BalloonFlags.cs diff --git a/Source/NotifyIconWpf/Interop/IconDataMembers.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconDataMembers.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/IconDataMembers.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconDataMembers.cs diff --git a/Source/NotifyIconWpf/Interop/IconState.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconState.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/IconState.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconState.cs diff --git a/Source/NotifyIconWpf/Interop/MouseEvent.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/MouseEvent.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/MouseEvent.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/MouseEvent.cs diff --git a/Source/NotifyIconWpf/Interop/NotifyCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyCommand.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/NotifyCommand.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyCommand.cs diff --git a/Source/NotifyIconWpf/Interop/NotifyIconData.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconData.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/NotifyIconData.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconData.cs diff --git a/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/NotifyIconVersion.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs diff --git a/Source/NotifyIconWpf/Interop/Point.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/Point.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/Point.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/Point.cs diff --git a/Source/NotifyIconWpf/Interop/TrayInfo.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/TrayInfo.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/TrayInfo.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/TrayInfo.cs diff --git a/Source/NotifyIconWpf/Interop/WinApi.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WinApi.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/WinApi.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WinApi.cs diff --git a/Source/NotifyIconWpf/Interop/WindowClass.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowClass.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/WindowClass.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowClass.cs diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowMessageSink.cs similarity index 100% rename from Source/NotifyIconWpf/Interop/WindowMessageSink.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowMessageSink.cs diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/NotifyIconWpf.csproj similarity index 100% rename from Source/NotifyIconWpf/NotifyIconWpf.csproj rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/NotifyIconWpf.csproj diff --git a/Source/NotifyIconWpf/PopupActivationMode.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/PopupActivationMode.cs similarity index 100% rename from Source/NotifyIconWpf/PopupActivationMode.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/PopupActivationMode.cs diff --git a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Properties/AssemblyInfo.cs similarity index 100% rename from Source/NotifyIconWpf/Properties/AssemblyInfo.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Properties/AssemblyInfo.cs diff --git a/Source/NotifyIconWpf/RoutedEventHelper.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/RoutedEventHelper.cs similarity index 100% rename from Source/NotifyIconWpf/RoutedEventHelper.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/RoutedEventHelper.cs diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs similarity index 100% rename from Source/NotifyIconWpf/TaskbarIcon.Declarations.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.cs similarity index 100% rename from Source/NotifyIconWpf/TaskbarIcon.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.cs diff --git a/Source/NotifyIconWpf/Util.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Util.cs similarity index 100% rename from Source/NotifyIconWpf/Util.cs rename to Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Util.cs diff --git a/Source/Sample Project/App.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml similarity index 100% rename from Source/Sample Project/App.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml diff --git a/Source/Sample Project/App.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml.cs similarity index 100% rename from Source/Sample Project/App.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml.cs diff --git a/Source/Sample Project/Commands/CloseWindowCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CloseWindowCommand.cs similarity index 100% rename from Source/Sample Project/Commands/CloseWindowCommand.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CloseWindowCommand.cs diff --git a/Source/Sample Project/Commands/CommandBase.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CommandBase.cs similarity index 100% rename from Source/Sample Project/Commands/CommandBase.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CommandBase.cs diff --git a/Source/Sample Project/Commands/HideSampleWindowCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/HideSampleWindowCommand.cs similarity index 100% rename from Source/Sample Project/Commands/HideSampleWindowCommand.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/HideSampleWindowCommand.cs diff --git a/Source/Sample Project/Commands/ShowSampleWindowCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/ShowSampleWindowCommand.cs similarity index 100% rename from Source/Sample Project/Commands/ShowSampleWindowCommand.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/ShowSampleWindowCommand.cs diff --git a/Source/Sample Project/Icons/Bulb.ico b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/Bulb.ico similarity index 100% rename from Source/Sample Project/Icons/Bulb.ico rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/Bulb.ico diff --git a/Source/Sample Project/Icons/Computers.ico b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/Computers.ico similarity index 100% rename from Source/Sample Project/Icons/Computers.ico rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/Computers.ico diff --git a/Source/Sample Project/Icons/Error.ico b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/Error.ico similarity index 100% rename from Source/Sample Project/Icons/Error.ico rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/Error.ico diff --git a/Source/Sample Project/Icons/Inactive.ico b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/Inactive.ico similarity index 100% rename from Source/Sample Project/Icons/Inactive.ico rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/Inactive.ico diff --git a/Source/Sample Project/Icons/NetDrives.ico b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/NetDrives.ico similarity index 100% rename from Source/Sample Project/Icons/NetDrives.ico rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Icons/NetDrives.ico diff --git a/Source/Sample Project/Images/Add.png b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Add.png similarity index 100% rename from Source/Sample Project/Images/Add.png rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Add.png diff --git a/Source/Sample Project/Images/Close.png b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Close.png similarity index 100% rename from Source/Sample Project/Images/Close.png rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Close.png diff --git a/Source/Sample Project/Images/Info.png b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Info.png similarity index 100% rename from Source/Sample Project/Images/Info.png rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Info.png diff --git a/Source/Sample Project/Images/Logo.png b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Logo.png similarity index 100% rename from Source/Sample Project/Images/Logo.png rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Logo.png diff --git a/Source/Sample Project/Images/Preferences.png b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Preferences.png similarity index 100% rename from Source/Sample Project/Images/Preferences.png rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Preferences.png diff --git a/Source/Sample Project/Images/Remove.png b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Remove.png similarity index 100% rename from Source/Sample Project/Images/Remove.png rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Images/Remove.png diff --git a/Source/Sample Project/Main.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Main.xaml similarity index 100% rename from Source/Sample Project/Main.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Main.xaml diff --git a/Source/Sample Project/Main.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Main.xaml.cs similarity index 100% rename from Source/Sample Project/Main.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Main.xaml.cs diff --git a/Source/Sample Project/Properties/AssemblyInfo.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/AssemblyInfo.cs similarity index 100% rename from Source/Sample Project/Properties/AssemblyInfo.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/AssemblyInfo.cs diff --git a/Source/Sample Project/Properties/Resources.Designer.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/Resources.Designer.cs similarity index 100% rename from Source/Sample Project/Properties/Resources.Designer.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/Resources.Designer.cs diff --git a/Source/Sample Project/Properties/Resources.resx b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/Resources.resx similarity index 100% rename from Source/Sample Project/Properties/Resources.resx rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/Resources.resx diff --git a/Source/Sample Project/Properties/Settings.Designer.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/Settings.Designer.cs similarity index 100% rename from Source/Sample Project/Properties/Settings.Designer.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/Settings.Designer.cs diff --git a/Source/Sample Project/Properties/Settings.settings b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/Settings.settings similarity index 100% rename from Source/Sample Project/Properties/Settings.settings rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Properties/Settings.settings diff --git a/Source/Sample Project/Sample Project.csproj b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Sample Project.csproj similarity index 100% rename from Source/Sample Project/Sample Project.csproj rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Sample Project.csproj diff --git a/Source/Sample Project/Showcase/FancyBalloon.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyBalloon.xaml similarity index 100% rename from Source/Sample Project/Showcase/FancyBalloon.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyBalloon.xaml diff --git a/Source/Sample Project/Showcase/FancyBalloon.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyBalloon.xaml.cs similarity index 100% rename from Source/Sample Project/Showcase/FancyBalloon.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyBalloon.xaml.cs diff --git a/Source/Sample Project/Showcase/FancyPopup.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyPopup.xaml similarity index 100% rename from Source/Sample Project/Showcase/FancyPopup.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyPopup.xaml diff --git a/Source/Sample Project/Showcase/FancyPopup.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyPopup.xaml.cs similarity index 100% rename from Source/Sample Project/Showcase/FancyPopup.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyPopup.xaml.cs diff --git a/Source/Sample Project/Showcase/FancyToolTip.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml similarity index 100% rename from Source/Sample Project/Showcase/FancyToolTip.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml diff --git a/Source/Sample Project/Showcase/FancyToolTip.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml.cs similarity index 100% rename from Source/Sample Project/Showcase/FancyToolTip.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml.cs diff --git a/Source/Sample Project/Showcase/NotifyIconResources.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/NotifyIconResources.xaml similarity index 100% rename from Source/Sample Project/Showcase/NotifyIconResources.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/NotifyIconResources.xaml diff --git a/Source/Sample Project/Showcase/ShowcaseWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/ShowcaseWindow.xaml similarity index 100% rename from Source/Sample Project/Showcase/ShowcaseWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/ShowcaseWindow.xaml diff --git a/Source/Sample Project/Showcase/ShowcaseWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/ShowcaseWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Showcase/ShowcaseWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/ShowcaseWindow.xaml.cs diff --git a/Source/Sample Project/Showcase/WelcomeBalloon.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/WelcomeBalloon.xaml similarity index 100% rename from Source/Sample Project/Showcase/WelcomeBalloon.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/WelcomeBalloon.xaml diff --git a/Source/Sample Project/Showcase/WelcomeBalloon.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/WelcomeBalloon.xaml.cs similarity index 100% rename from Source/Sample Project/Showcase/WelcomeBalloon.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/WelcomeBalloon.xaml.cs diff --git a/Source/Sample Project/Tutorials/01 - Declaration/NotifyIconResourceDictionary.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/01 - Declaration/NotifyIconResourceDictionary.xaml similarity index 100% rename from Source/Sample Project/Tutorials/01 - Declaration/NotifyIconResourceDictionary.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/01 - Declaration/NotifyIconResourceDictionary.xaml diff --git a/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml similarity index 100% rename from Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml diff --git a/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/01 - Declaration/SimpleWindowWithNotifyIcon.xaml.cs diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/InlineToolTipWindow.xaml.cs diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml similarity index 100% rename from Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/SimpleUserControl.xaml.cs diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml diff --git a/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/02 - ToolTips/UserControlToolTipWindow.xaml.cs diff --git a/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml diff --git a/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/03 - Popups/InlinePopupWindow.xaml.cs diff --git a/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml diff --git a/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/04 - ContextMenus/InlineContextMenuWindow.xaml.cs diff --git a/Source/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml diff --git a/Source/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/05 - Balloons/BalloonSampleWindow.xaml.cs diff --git a/Source/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml diff --git a/Source/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/06 - Commands/CommandWindow.xaml.cs diff --git a/Source/Sample Project/Tutorials/06 - Commands/ShowMessageCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/06 - Commands/ShowMessageCommand.cs similarity index 100% rename from Source/Sample Project/Tutorials/06 - Commands/ShowMessageCommand.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/06 - Commands/ShowMessageCommand.cs diff --git a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml diff --git a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs diff --git a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml diff --git a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs diff --git a/Source/Sample Project/Tutorials/09 - MVVM/Clock.png b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/Clock.png similarity index 100% rename from Source/Sample Project/Tutorials/09 - MVVM/Clock.png rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/Clock.png diff --git a/Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml similarity index 100% rename from Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml diff --git a/Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/ClockPopup.xaml.cs diff --git a/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleViewModel.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleViewModel.cs similarity index 100% rename from Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleViewModel.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleViewModel.cs diff --git a/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml similarity index 100% rename from Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml diff --git a/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml.cs similarity index 100% rename from Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Tutorials/09 - MVVM/MvvmSampleWindow.xaml.cs diff --git a/Source/Windowless Sample/App.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/App.xaml similarity index 100% rename from Source/Windowless Sample/App.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/App.xaml diff --git a/Source/Windowless Sample/App.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/App.xaml.cs similarity index 100% rename from Source/Windowless Sample/App.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/App.xaml.cs diff --git a/Source/Windowless Sample/MainWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/MainWindow.xaml similarity index 100% rename from Source/Windowless Sample/MainWindow.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/MainWindow.xaml diff --git a/Source/Windowless Sample/MainWindow.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/MainWindow.xaml.cs similarity index 100% rename from Source/Windowless Sample/MainWindow.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/MainWindow.xaml.cs diff --git a/Source/Windowless Sample/NotifyIconResources.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/NotifyIconResources.xaml similarity index 100% rename from Source/Windowless Sample/NotifyIconResources.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/NotifyIconResources.xaml diff --git a/Source/Windowless Sample/NotifyIconViewModel.cs b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/NotifyIconViewModel.cs similarity index 100% rename from Source/Windowless Sample/NotifyIconViewModel.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/NotifyIconViewModel.cs diff --git a/Source/Windowless Sample/Properties/AssemblyInfo.cs b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/Properties/AssemblyInfo.cs similarity index 100% rename from Source/Windowless Sample/Properties/AssemblyInfo.cs rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/Properties/AssemblyInfo.cs diff --git a/Source/Windowless Sample/Red.ico b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/Red.ico similarity index 100% rename from Source/Windowless Sample/Red.ico rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/Red.ico diff --git a/Source/Windowless Sample/Windowless Sample.csproj b/Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/Windowless Sample.csproj similarity index 100% rename from Source/Windowless Sample/Windowless Sample.csproj rename to Hardcodet.NotifyIcon.Wpf/Source/Windowless Sample/Windowless Sample.csproj diff --git a/Source/WindowsFormsSample/FancyPopup.xaml b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/FancyPopup.xaml similarity index 100% rename from Source/WindowsFormsSample/FancyPopup.xaml rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/FancyPopup.xaml diff --git a/Source/WindowsFormsSample/FancyPopup.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/FancyPopup.xaml.cs similarity index 100% rename from Source/WindowsFormsSample/FancyPopup.xaml.cs rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/FancyPopup.xaml.cs diff --git a/Source/WindowsFormsSample/Form1.Designer.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.Designer.cs similarity index 100% rename from Source/WindowsFormsSample/Form1.Designer.cs rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.Designer.cs diff --git a/Source/WindowsFormsSample/Form1.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.cs similarity index 100% rename from Source/WindowsFormsSample/Form1.cs rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.cs diff --git a/Source/WindowsFormsSample/Form1.resx b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.resx similarity index 100% rename from Source/WindowsFormsSample/Form1.resx rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.resx diff --git a/Source/WindowsFormsSample/Icon/Led.ico b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Icon/Led.ico similarity index 100% rename from Source/WindowsFormsSample/Icon/Led.ico rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Icon/Led.ico diff --git a/Source/WindowsFormsSample/Images/Preferences.png b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Images/Preferences.png similarity index 100% rename from Source/WindowsFormsSample/Images/Preferences.png rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Images/Preferences.png diff --git a/Source/WindowsFormsSample/Program.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Program.cs similarity index 100% rename from Source/WindowsFormsSample/Program.cs rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Program.cs diff --git a/Source/WindowsFormsSample/Properties/AssemblyInfo.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/AssemblyInfo.cs similarity index 100% rename from Source/WindowsFormsSample/Properties/AssemblyInfo.cs rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/AssemblyInfo.cs diff --git a/Source/WindowsFormsSample/Properties/Resources.Designer.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.Designer.cs similarity index 100% rename from Source/WindowsFormsSample/Properties/Resources.Designer.cs rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.Designer.cs diff --git a/Source/WindowsFormsSample/Properties/Resources.resx b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.resx similarity index 100% rename from Source/WindowsFormsSample/Properties/Resources.resx rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.resx diff --git a/Source/WindowsFormsSample/Properties/Settings.Designer.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.Designer.cs similarity index 100% rename from Source/WindowsFormsSample/Properties/Settings.Designer.cs rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.Designer.cs diff --git a/Source/WindowsFormsSample/Properties/Settings.settings b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.settings similarity index 100% rename from Source/WindowsFormsSample/Properties/Settings.settings rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.settings diff --git a/Source/WindowsFormsSample/WindowsFormsSample.csproj b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/WindowsFormsSample.csproj similarity index 100% rename from Source/WindowsFormsSample/WindowsFormsSample.csproj rename to Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/WindowsFormsSample.csproj From eac1c5d8858f516b980ff1a7f11c2388e17c9ee4 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Mon, 25 Nov 2013 17:33:40 +0100 Subject: [PATCH 72/73] ADD Git attributes. CHG End of line conversion. --- .gitattributes | 63 + .gitignore | 156 + .../Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec | 78 +- ...codet.Wpf.TaskbarNotification.1.0.5.nuspec | 48 +- .../readme.from.legacy.package.txt | 16 +- .../NuGet/readme.1.0.5.txt | 20 +- .../Source/BuildTargets.cmd | 18 +- Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt | 152 +- .../Cleanup_Solution_For_Deployment.bat | 40 +- .../Source/NotifyIconWpf.sln | 90 +- .../Source/NotifyIconWpf/BalloonIcon.cs | 102 +- .../Diagrams/TaskbarIcon Overview.cd | 58 +- .../NotifyIconWpf/Interop/BalloonFlags.cs | 120 +- .../NotifyIconWpf/Interop/IconDataMembers.cs | 138 +- .../Source/NotifyIconWpf/Interop/IconState.cs | 42 +- .../NotifyIconWpf/Interop/MouseEvent.cs | 106 +- .../NotifyIconWpf/Interop/NotifyCommand.cs | 80 +- .../NotifyIconWpf/Interop/NotifyIconData.cs | 328 +- .../Interop/NotifyIconVersion.cs | 52 +- .../Source/NotifyIconWpf/Interop/Point.cs | 38 +- .../Source/NotifyIconWpf/Interop/TrayInfo.cs | 326 +- .../Source/NotifyIconWpf/Interop/WinApi.cs | 176 +- .../NotifyIconWpf/Interop/WindowClass.cs | 68 +- .../Interop/WindowMessageSink.cs | 732 ++-- .../Source/NotifyIconWpf/NotifyIconWpf.csproj | 164 +- .../NotifyIconWpf/PopupActivationMode.cs | 148 +- .../NotifyIconWpf/Properties/AssemblyInfo.cs | 128 +- .../Source/NotifyIconWpf/RoutedEventHelper.cs | 160 +- .../NotifyIconWpf/TaskbarIcon.Declarations.cs | 3780 ++++++++--------- .../Source/NotifyIconWpf/TaskbarIcon.cs | 2182 +++++----- .../Source/NotifyIconWpf/Util.cs | 616 +-- .../Source/Sample Project/App.xaml | 26 +- .../Source/Sample Project/App.xaml.cs | 32 +- .../Commands/CloseWindowCommand.cs | 46 +- .../Sample Project/Commands/CommandBase.cs | 312 +- .../Commands/HideSampleWindowCommand.cs | 46 +- .../Commands/ShowSampleWindowCommand.cs | 46 +- .../Source/Sample Project/Main.xaml | 482 +-- .../Source/Sample Project/Main.xaml.cs | 210 +- .../Sample Project/Properties/AssemblyInfo.cs | 114 +- .../Properties/Resources.Designer.cs | 186 +- .../Sample Project/Properties/Resources.resx | 258 +- .../Properties/Settings.Designer.cs | 52 +- .../Properties/Settings.settings | 14 +- .../Sample Project/Sample Project.csproj | 708 +-- .../Sample Project/Showcase/FancyBalloon.xaml | 322 +- .../Showcase/FancyBalloon.xaml.cs | 212 +- .../Sample Project/Showcase/FancyPopup.xaml | 230 +- .../Showcase/FancyPopup.xaml.cs | 90 +- .../Sample Project/Showcase/FancyToolTip.xaml | 226 +- .../Showcase/FancyToolTip.xaml.cs | 100 +- .../Showcase/NotifyIconResources.xaml | 160 +- .../Showcase/ShowcaseWindow.xaml | 1278 +++--- .../Showcase/ShowcaseWindow.xaml.cs | 182 +- .../Showcase/WelcomeBalloon.xaml | 208 +- .../Showcase/WelcomeBalloon.xaml.cs | 52 +- .../NotifyIconResourceDictionary.xaml | 18 +- .../SimpleWindowWithNotifyIcon.xaml | 38 +- .../SimpleWindowWithNotifyIcon.xaml.cs | 44 +- .../02 - ToolTips/InlineToolTipWindow.xaml | 80 +- .../02 - ToolTips/InlineToolTipWindow.xaml.cs | 66 +- .../02 - ToolTips/SimpleUserControl.xaml | 40 +- .../02 - ToolTips/SimpleUserControl.xaml.cs | 52 +- .../UserControlToolTipWindow.xaml | 52 +- .../UserControlToolTipWindow.xaml.cs | 66 +- .../03 - Popups/InlinePopupWindow.xaml | 120 +- .../03 - Popups/InlinePopupWindow.xaml.cs | 66 +- .../InlineContextMenuWindow.xaml | 160 +- .../InlineContextMenuWindow.xaml.cs | 78 +- .../05 - Balloons/BalloonSampleWindow.xaml | 100 +- .../05 - Balloons/BalloonSampleWindow.xaml.cs | 128 +- .../06 - Commands/CommandWindow.xaml | 126 +- .../06 - Commands/CommandWindow.xaml.cs | 70 +- .../06 - Commands/ShowMessageCommand.cs | 48 +- .../07 - Events/EventVisualizerWindow.xaml | 528 +-- .../07 - Events/EventVisualizerWindow.xaml.cs | 46 +- .../DataBoundToolTipWindow.xaml | 180 +- .../DataBoundToolTipWindow.xaml.cs | 48 +- .../Tutorials/09 - MVVM/ClockPopup.xaml | 72 +- .../Tutorials/09 - MVVM/ClockPopup.xaml.cs | 28 +- .../09 - MVVM/MvvmSampleViewModel.cs | 74 +- .../Tutorials/09 - MVVM/MvvmSampleWindow.xaml | 74 +- .../09 - MVVM/MvvmSampleWindow.xaml.cs | 30 +- .../Source/Windowless Sample/App.xaml | 42 +- .../Source/Windowless Sample/App.xaml.cs | 54 +- .../Source/Windowless Sample/MainWindow.xaml | 16 +- .../Windowless Sample/MainWindow.xaml.cs | 56 +- .../NotifyIconResources.xaml | 62 +- .../Windowless Sample/NotifyIconViewModel.cs | 172 +- .../Properties/AssemblyInfo.cs | 110 +- .../Windowless Sample.csproj | 194 +- .../Source/WindowsFormsSample/FancyPopup.xaml | 256 +- .../WindowsFormsSample/FancyPopup.xaml.cs | 88 +- .../WindowsFormsSample/Form1.Designer.cs | 124 +- .../Source/WindowsFormsSample/Form1.cs | 76 +- .../Source/WindowsFormsSample/Form1.resx | 238 +- .../Source/WindowsFormsSample/Program.cs | 38 +- .../Properties/AssemblyInfo.cs | 78 +- .../Properties/Resources.Designer.cs | 146 +- .../Properties/Resources.resx | 246 +- .../Properties/Settings.Designer.cs | 52 +- .../Properties/Settings.settings | 14 +- .../WindowsFormsSample.csproj | 322 +- 103 files changed, 10426 insertions(+), 10207 deletions(-) create mode 100644 .gitattributes create mode 100644 .gitignore diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bc915c --- /dev/null +++ b/.gitignore @@ -0,0 +1,156 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/Hardcodet.NotifyIcon.Wpf/NuGet/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec b/Hardcodet.NotifyIcon.Wpf/NuGet/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec index 195247c..b05302f 100644 --- a/Hardcodet.NotifyIcon.Wpf/NuGet/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec +++ b/Hardcodet.NotifyIcon.Wpf/NuGet/Hardcodet.NotifyIcon.Wpf.1.0.5.nuspec @@ -1,42 +1,42 @@ - - - - Hardcodet.NotifyIcon.Wpf - 1.0.5 - Hardcodet WPF NotifyIcon - Philipp Sumi - Philipp Sumi - http://www.codeproject.com/info/cpol10.aspx - http://www.hardcodet.net/projects/wpf-notifyicon - false + + + + Hardcodet.NotifyIcon.Wpf + 1.0.5 + Hardcodet WPF NotifyIcon + Philipp Sumi + Philipp Sumi + http://www.codeproject.com/info/cpol10.aspx + http://www.hardcodet.net/projects/wpf-notifyicon + false This is an implementation of a NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. It does not just rely on the Windows Forms NotifyIcon component, but is a purely independent control which leverages several features of the WPF framework in order to display rich tooltips, popups, context menus, and balloon messages. It can be used directly in code or embedded in any XAML file. -Source code and extensive sample application available at http://www.hardcodet.net/projects/wpf-notifyicon - NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. - Mostly bug fixes and full x64 / Win 8 support. Contains source and binaries for .NET 3.5 - 4.51. - Copyright (c) 2013 Philipp Sumi - - NotifyIcon WPF Tray Notify ToolTip Popup Balloon Toast - - - - - - - - - - - - - - - - - - - - - - +Source code and extensive sample application available at http://www.hardcodet.net/projects/wpf-notifyicon + NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. + Mostly bug fixes and full x64 / Win 8 support. Contains source and binaries for .NET 3.5 - 4.51. + Copyright (c) 2013 Philipp Sumi + + NotifyIcon WPF Tray Notify ToolTip Popup Balloon Toast + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec b/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec index aae06f7..046317c 100644 --- a/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec +++ b/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/Hardcodet.Wpf.TaskbarNotification.1.0.5.nuspec @@ -1,31 +1,31 @@ - - - - Hardcodet.Wpf.TaskbarNotification - 1.0.5 - Hardcodet.Wpf.TaskbarNotification - Philipp Sumi - Philipp Sumi - http://www.codeproject.com/info/cpol10.aspx - http://www.hardcodet.net/projects/wpf-notifyicon - false + + + + Hardcodet.Wpf.TaskbarNotification + 1.0.5 + Hardcodet.Wpf.TaskbarNotification + Philipp Sumi + Philipp Sumi + http://www.codeproject.com/info/cpol10.aspx + http://www.hardcodet.net/projects/wpf-notifyicon + false THIS PACKAGE IS OBSOLETE. Please switch to the officially maintained NuGet package: Hardcodet.NotifyIcon.WPF This is an implementation of a NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. It does not just rely on the Windows Forms NotifyIcon component, but is a purely independent control which leverages several features of the WPF framework in order to display rich tooltips, popups, context menus, and balloon messages. It can be used directly in code or embedded in any XAML file. -Source code and extensive sample application available at http://www.hardcodet.net/projects/wpf-notifyicon - This package is obsolete. Please switch to the maintained NuGet package: Hardcodet.NotifyIcon.WPF - Mostly bug fixes and full x64 / Win 8 support. Contains source and binaries for .NET 3.5 - 4.51. - Copyright (c) 2013 Philipp Sumi - - NotifyIcon WPF Tray Notify ToolTip Popup Balloon Toast - - - - - - - +Source code and extensive sample application available at http://www.hardcodet.net/projects/wpf-notifyicon + This package is obsolete. Please switch to the maintained NuGet package: Hardcodet.NotifyIcon.WPF + Mostly bug fixes and full x64 / Win 8 support. Contains source and binaries for .NET 3.5 - 4.51. + Copyright (c) 2013 Philipp Sumi + + NotifyIcon WPF Tray Notify ToolTip Popup Balloon Toast + + + + + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/readme.from.legacy.package.txt b/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/readme.from.legacy.package.txt index faf6894..ac394ba 100644 --- a/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/readme.from.legacy.package.txt +++ b/Hardcodet.NotifyIcon.Wpf/NuGet/Legacy Switch/readme.from.legacy.package.txt @@ -1,9 +1,9 @@ -Hardcodet NotifyIcon for WPF -**************************** - -THIS PACKAGE IS OBSOLETE. - -This package has a dependency to the official package in order to keep things working for you, but consider switching to the official NuGet package: Hardcodet.NotifyIcon.Wpf - -For direct NuGet links, source code or samples, please visit the project page: +Hardcodet NotifyIcon for WPF +**************************** + +THIS PACKAGE IS OBSOLETE. + +This package has a dependency to the official package in order to keep things working for you, but consider switching to the official NuGet package: Hardcodet.NotifyIcon.Wpf + +For direct NuGet links, source code or samples, please visit the project page: http://www.hardcodet.net/projects/wpf-notifyicon \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/NuGet/readme.1.0.5.txt b/Hardcodet.NotifyIcon.Wpf/NuGet/readme.1.0.5.txt index 832c9fa..44773fc 100644 --- a/Hardcodet.NotifyIcon.Wpf/NuGet/readme.1.0.5.txt +++ b/Hardcodet.NotifyIcon.Wpf/NuGet/readme.1.0.5.txt @@ -1,10 +1,10 @@ -Hardcodet NotifyIcon for WPF 1.0.5 -********************************** - -This is an implementation of a NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. It does not just rely on the Windows Forms NotifyIcon component, but is a purely independent control which leverages several features of the WPF framework in order to display rich tooltips, popups, context menus, and balloon messages. It can be used directly in code or embedded in any XAML file. - -This package contains only binaries. For source code and samples, please visit the project page: -http://www.hardcodet.net/projects/wpf-notifyicon - - - +Hardcodet NotifyIcon for WPF 1.0.5 +********************************** + +This is an implementation of a NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. It does not just rely on the Windows Forms NotifyIcon component, but is a purely independent control which leverages several features of the WPF framework in order to display rich tooltips, popups, context menus, and balloon messages. It can be used directly in code or embedded in any XAML file. + +This package contains only binaries. For source code and samples, please visit the project page: +http://www.hardcodet.net/projects/wpf-notifyicon + + + diff --git a/Hardcodet.NotifyIcon.Wpf/Source/BuildTargets.cmd b/Hardcodet.NotifyIcon.Wpf/Source/BuildTargets.cmd index bada9ef..5640701 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/BuildTargets.cmd +++ b/Hardcodet.NotifyIcon.Wpf/Source/BuildTargets.cmd @@ -1,9 +1,9 @@ -"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v3.5;TargetFrameworkProfile="";OutputPath=..\..\Binaries\net35 /t:Rebuild -"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v3.5;TargetFrameworkProfile="Client";OutputPath=..\..\Binaries\net35-client /t:Rebuild - -"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v4.0;TargetFrameworkProfile="";OutputPath=..\..\Binaries\net40 /t:Rebuild -"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v4.0;TargetFrameworkProfile="Client";OutputPath=..\..\Binaries\net40-client /t:Rebuild - -"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v4.5;TargetFrameworkProfile="";OutputPath=..\..\Binaries\net45 /t:Rebuild - -"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v4.5.1;TargetFrameworkProfile="";OutputPath=..\..\Binaries\net451 /t:Rebuild +"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v3.5;TargetFrameworkProfile="";OutputPath=..\..\Binaries\net35 /t:Rebuild +"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v3.5;TargetFrameworkProfile="Client";OutputPath=..\..\Binaries\net35-client /t:Rebuild + +"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v4.0;TargetFrameworkProfile="";OutputPath=..\..\Binaries\net40 /t:Rebuild +"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v4.0;TargetFrameworkProfile="Client";OutputPath=..\..\Binaries\net40-client /t:Rebuild + +"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v4.5;TargetFrameworkProfile="";OutputPath=..\..\Binaries\net45 /t:Rebuild + +"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" NotifyIconWpf\NotifyIconWpf.csproj /p:Configuration=Release;TargetFrameworkVersion=v4.5.1;TargetFrameworkProfile="";OutputPath=..\..\Binaries\net451 /t:Rebuild diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt b/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt index 1869505..d38878c 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt +++ b/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt @@ -1,77 +1,77 @@ -hardcodet.net NotifyIcon for WPF - Changelog -Copyright (c) 2009-2013 Philipp Sumi -Contact and Information: http://www.hardcodet.net - - -1.0.5 (2013.11.20) -***** - -FIX Support for x64 applications targeting .NET 4 x64 or higher (big thanks to Mark Junker for submitting a patch!) -CHG Component does no longer throw an exception is no Explorer shell is present, - but waits for it to be created. -CHG NotifyIcon is not only removed on user-initiated disposal, but also garbage collection. -CHG The attached ParentTaskbarIconProperty is now derived, so data binding to the attached DP - becomes much simpler - (e.g. ) -CHG WinAPI interop now uses Unicode in order to prevent issues with Asian languages. Thanks to JO Hyeong-Ryeol for posting an easy fix! -FIX Context menues receiving keyboard events, which allows for TextBoxes in context menus. -FIX Coordinates calculated properly on operating systems with non-standard DPIs. Thanks Rusi Filipov for bug reporting and testing. -FIX Data-bound ToolTipText may have caused ToolTips to remain open in case of property changes. - - ----------------------------------------------------------------------------- - -1.0.4 (2009.09.21) -***** - -FIX If a popup is opened, its window handle is now being set as the foreground. - This fixes an issue with certain controls being disabled on popups. - (thanks Andrew Smith for pointing me in the right direction!). -FIX Changed dispatcher access in order to work in WinForms scenarios, too. -FIX Corrected typo in WindowMessageSink.BalloonToolTipChanged event (thanks Mertsch). - Used internally (although event is public), so this shouldn't be a breaking change. -FIX Dispose only deregisters OnExit event listenter if there is actually an - application (not the case in WinForms environments). - - ----------------------------------------------------------------------------- - -1.0.3 (2009.07.02) -***** -FIX Commands did not work with RoutedCommands which require an explicit target - (thanks Rodolfo Grave). -ADD Added command target properties for both left and double click commands. - Allows to explicitly define another control as the target of a routed - command. - - ----------------------------------------------------------------------------- - -1.0.2 (2009.05.18) -***** -FIX Late-bound DataContext did not coerce properly with ContextMenu, thus - assigning it the TaskbarIcon rather than the TaskbarIcon's DataContext. - Thanks Nic Pillinger for discovering the issue. - - ----------------------------------------------------------------------------- - -1.0.1 (2009.05.15) -***** -CHG DataContext is also assigned to ContextMenu (thanks Nic Pillinger), - and properly coerced for ToolTips and Popups. Also checks whether - target item has a binding on the DataContext - (does not just override if DataContext is null). -CHG Popup creation no longer calls Popup.CreateRootPopup which tries to - bind to dependency properties that do not exist, thus causing debug - warnings (thanks to Loic Berthollet). -CHG The LeftClickCommand now executes with a delay in order to make sure - it's not a double-click. -FIX Removed debug output in WindowMessageSink. - - ----------------------------------------------------------------------------- - -1.0.0 -***** +hardcodet.net NotifyIcon for WPF - Changelog +Copyright (c) 2009-2013 Philipp Sumi +Contact and Information: http://www.hardcodet.net + + +1.0.5 (2013.11.20) +***** + +FIX Support for x64 applications targeting .NET 4 x64 or higher (big thanks to Mark Junker for submitting a patch!) +CHG Component does no longer throw an exception is no Explorer shell is present, + but waits for it to be created. +CHG NotifyIcon is not only removed on user-initiated disposal, but also garbage collection. +CHG The attached ParentTaskbarIconProperty is now derived, so data binding to the attached DP + becomes much simpler + (e.g. ) +CHG WinAPI interop now uses Unicode in order to prevent issues with Asian languages. Thanks to JO Hyeong-Ryeol for posting an easy fix! +FIX Context menues receiving keyboard events, which allows for TextBoxes in context menus. +FIX Coordinates calculated properly on operating systems with non-standard DPIs. Thanks Rusi Filipov for bug reporting and testing. +FIX Data-bound ToolTipText may have caused ToolTips to remain open in case of property changes. + + +---------------------------------------------------------------------------- + +1.0.4 (2009.09.21) +***** + +FIX If a popup is opened, its window handle is now being set as the foreground. + This fixes an issue with certain controls being disabled on popups. + (thanks Andrew Smith for pointing me in the right direction!). +FIX Changed dispatcher access in order to work in WinForms scenarios, too. +FIX Corrected typo in WindowMessageSink.BalloonToolTipChanged event (thanks Mertsch). + Used internally (although event is public), so this shouldn't be a breaking change. +FIX Dispose only deregisters OnExit event listenter if there is actually an + application (not the case in WinForms environments). + + +---------------------------------------------------------------------------- + +1.0.3 (2009.07.02) +***** +FIX Commands did not work with RoutedCommands which require an explicit target + (thanks Rodolfo Grave). +ADD Added command target properties for both left and double click commands. + Allows to explicitly define another control as the target of a routed + command. + + +---------------------------------------------------------------------------- + +1.0.2 (2009.05.18) +***** +FIX Late-bound DataContext did not coerce properly with ContextMenu, thus + assigning it the TaskbarIcon rather than the TaskbarIcon's DataContext. + Thanks Nic Pillinger for discovering the issue. + + +---------------------------------------------------------------------------- + +1.0.1 (2009.05.15) +***** +CHG DataContext is also assigned to ContextMenu (thanks Nic Pillinger), + and properly coerced for ToolTips and Popups. Also checks whether + target item has a binding on the DataContext + (does not just override if DataContext is null). +CHG Popup creation no longer calls Popup.CreateRootPopup which tries to + bind to dependency properties that do not exist, thus causing debug + warnings (thanks to Loic Berthollet). +CHG The LeftClickCommand now executes with a delay in order to make sure + it's not a double-click. +FIX Removed debug output in WindowMessageSink. + + +---------------------------------------------------------------------------- + +1.0.0 +***** ADD Initial release. \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Cleanup_Solution_For_Deployment.bat b/Hardcodet.NotifyIcon.Wpf/Source/Cleanup_Solution_For_Deployment.bat index 1f49792..01581a4 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Cleanup_Solution_For_Deployment.bat +++ b/Hardcodet.NotifyIcon.Wpf/Source/Cleanup_Solution_For_Deployment.bat @@ -1,20 +1,20 @@ -del /s /ah /f *.suo -del /s /f *.user -del /s /f *.cache -del /s /f *.scc -del /s /f *.vssscc -del /s /f *.vspscc -del /s /f *.keep -del /s /ah /f vssver2.scc - -rd /s /q bin obj ClientBin _Resharper.* _Upgrade* - -del dirs.txt -dir /s /b /ad bin > dirs.txt -dir /s /b /ad obj >> dirs.txt -dir /s /b /ad ClientBin >> dirs.txt -dir /s /b /ad _Resharper.* >> dirs.txt -dir /s /b /ad _Upgrade* >> dirs.txt - -for /f "delims=;" %%i in (dirs.txt) DO rd /s /q "%%i" -del dirs.txt +del /s /ah /f *.suo +del /s /f *.user +del /s /f *.cache +del /s /f *.scc +del /s /f *.vssscc +del /s /f *.vspscc +del /s /f *.keep +del /s /ah /f vssver2.scc + +rd /s /q bin obj ClientBin _Resharper.* _Upgrade* + +del dirs.txt +dir /s /b /ad bin > dirs.txt +dir /s /b /ad obj >> dirs.txt +dir /s /b /ad ClientBin >> dirs.txt +dir /s /b /ad _Resharper.* >> dirs.txt +dir /s /b /ad _Upgrade* >> dirs.txt + +for /f "delims=;" %%i in (dirs.txt) DO rd /s /q "%%i" +del dirs.txt diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf.sln b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf.sln index e188016..acefad4 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf.sln +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf.sln @@ -1,45 +1,45 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C37AE34D-A8C4-4AEC-995C-3C763300934E}" - ProjectSection(SolutionItems) = preProject - Changelog.txt = Changelog.txt - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotifyIconWpf", "NotifyIconWpf\NotifyIconWpf.csproj", "{7AC63864-7638-41C4-969C-D3197EF2BED9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample Project", "Sample Project\Sample Project.csproj", "{71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsFormsSample", "WindowsFormsSample\WindowsFormsSample.csproj", "{F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Windowless Sample", "Windowless Sample\Windowless Sample.csproj", "{964EBFBE-A600-49B2-BDD8-422B46F1D544}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.Build.0 = Release|Any CPU - {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Release|Any CPU.Build.0 = Release|Any CPU - {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}.Release|Any CPU.Build.0 = Release|Any CPU - {964EBFBE-A600-49B2-BDD8-422B46F1D544}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {964EBFBE-A600-49B2-BDD8-422B46F1D544}.Debug|Any CPU.Build.0 = Debug|Any CPU - {964EBFBE-A600-49B2-BDD8-422B46F1D544}.Release|Any CPU.ActiveCfg = Release|Any CPU - {964EBFBE-A600-49B2-BDD8-422B46F1D544}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C37AE34D-A8C4-4AEC-995C-3C763300934E}" + ProjectSection(SolutionItems) = preProject + Changelog.txt = Changelog.txt + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotifyIconWpf", "NotifyIconWpf\NotifyIconWpf.csproj", "{7AC63864-7638-41C4-969C-D3197EF2BED9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample Project", "Sample Project\Sample Project.csproj", "{71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsFormsSample", "WindowsFormsSample\WindowsFormsSample.csproj", "{F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Windowless Sample", "Windowless Sample\Windowless Sample.csproj", "{964EBFBE-A600-49B2-BDD8-422B46F1D544}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.Build.0 = Release|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Release|Any CPU.Build.0 = Release|Any CPU + {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8}.Release|Any CPU.Build.0 = Release|Any CPU + {964EBFBE-A600-49B2-BDD8-422B46F1D544}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {964EBFBE-A600-49B2-BDD8-422B46F1D544}.Debug|Any CPU.Build.0 = Debug|Any CPU + {964EBFBE-A600-49B2-BDD8-422B46F1D544}.Release|Any CPU.ActiveCfg = Release|Any CPU + {964EBFBE-A600-49B2-BDD8-422B46F1D544}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/BalloonIcon.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/BalloonIcon.cs index e8e630a..4979133 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/BalloonIcon.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/BalloonIcon.cs @@ -1,52 +1,52 @@ -// hardcodet.net NotifyIcon for WPF -// Copyright (c) 2009 - 2013 Philipp Sumi -// Contact and Information: http://www.hardcodet.net -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the Code Project Open License (CPOL); -// either version 1.0 of the License, or (at your option) any later -// version. -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE - - -namespace Hardcodet.Wpf.TaskbarNotification -{ - /// - /// Supported icons for the tray's balloon messages. - /// - public enum BalloonIcon - { - /// - /// The balloon message is displayed without an icon. - /// - None, - - /// - /// An information is displayed. - /// - Info, - - /// - /// A warning is displayed. - /// - Warning, - - /// - /// An error is displayed. - /// - Error - } +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 - 2013 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Supported icons for the tray's balloon messages. + /// + public enum BalloonIcon + { + /// + /// The balloon message is displayed without an icon. + /// + None, + + /// + /// An information is displayed. + /// + Info, + + /// + /// A warning is displayed. + /// + Warning, + + /// + /// An error is displayed. + /// + Error + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd index e368a8f..b43adff 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd @@ -1,30 +1,30 @@ - - - - - - - - - - N6qdVIeUdLmQtSUbiJhEGdYRjvJYXlhbEVBDKuPRO5s= - TaskbarIcon.cs - - - - - - - ABAEAAAAAAAAAAABAAAAAAAAAAAAAAAAAIAKAIAAAAA= - PopupActivationMode.cs - - - - - - AAAAAAAAAAAAAQAAAAAAABAAAAAAAAAAAAAAAEEAAAA= - BalloonIcon.cs - - - + + + + + + + + + + N6qdVIeUdLmQtSUbiJhEGdYRjvJYXlhbEVBDKuPRO5s= + TaskbarIcon.cs + + + + + + + ABAEAAAAAAAAAAABAAAAAAAAAAAAAAAAAIAKAIAAAAA= + PopupActivationMode.cs + + + + + + AAAAAAAAAAAAAQAAAAAAABAAAAAAAAAAAAAAAEEAAAA= + BalloonIcon.cs + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/BalloonFlags.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/BalloonFlags.cs index 0243003..2e02633 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/BalloonFlags.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/BalloonFlags.cs @@ -1,61 +1,61 @@ -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Flags that define the icon that is shown on a balloon - /// tooltip. - /// - public enum BalloonFlags - { - /// - /// No icon is displayed. - /// - None = 0x00, - - /// - /// An information icon is displayed. - /// - Info = 0x01, - - /// - /// A warning icon is displayed. - /// - Warning = 0x02, - - /// - /// An error icon is displayed. - /// - Error = 0x03, - - /// - /// Windows XP Service Pack 2 (SP2) and later. - /// Use a custom icon as the title icon. - /// - User = 0x04, - - /// - /// Windows XP (Shell32.dll version 6.0) and later. - /// Do not play the associated sound. Applies only to balloon ToolTips. - /// - NoSound = 0x10, - - /// - /// Windows Vista (Shell32.dll version 6.0.6) and later. The large version - /// of the icon should be used as the balloon icon. This corresponds to the - /// icon with dimensions SM_CXICON x SM_CYICON. If this flag is not set, - /// the icon with dimensions XM_CXSMICON x SM_CYSMICON is used.
- /// - This flag can be used with all stock icons.
- /// - Applications that use older customized icons (NIIF_USER with hIcon) must - /// provide a new SM_CXICON x SM_CYICON version in the tray icon (hIcon). These - /// icons are scaled down when they are displayed in the System Tray or - /// System Control Area (SCA).
- /// - New customized icons (NIIF_USER with hBalloonIcon) must supply an - /// SM_CXICON x SM_CYICON version in the supplied icon (hBalloonIcon). - ///
- LargeIcon = 0x20, - - /// - /// Windows 7 and later. - /// - RespectQuietTime = 0x80 - } +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Flags that define the icon that is shown on a balloon + /// tooltip. + /// + public enum BalloonFlags + { + /// + /// No icon is displayed. + /// + None = 0x00, + + /// + /// An information icon is displayed. + /// + Info = 0x01, + + /// + /// A warning icon is displayed. + /// + Warning = 0x02, + + /// + /// An error icon is displayed. + /// + Error = 0x03, + + /// + /// Windows XP Service Pack 2 (SP2) and later. + /// Use a custom icon as the title icon. + /// + User = 0x04, + + /// + /// Windows XP (Shell32.dll version 6.0) and later. + /// Do not play the associated sound. Applies only to balloon ToolTips. + /// + NoSound = 0x10, + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The large version + /// of the icon should be used as the balloon icon. This corresponds to the + /// icon with dimensions SM_CXICON x SM_CYICON. If this flag is not set, + /// the icon with dimensions XM_CXSMICON x SM_CYSMICON is used.
+ /// - This flag can be used with all stock icons.
+ /// - Applications that use older customized icons (NIIF_USER with hIcon) must + /// provide a new SM_CXICON x SM_CYICON version in the tray icon (hIcon). These + /// icons are scaled down when they are displayed in the System Tray or + /// System Control Area (SCA).
+ /// - New customized icons (NIIF_USER with hBalloonIcon) must supply an + /// SM_CXICON x SM_CYICON version in the supplied icon (hBalloonIcon). + ///
+ LargeIcon = 0x20, + + /// + /// Windows 7 and later. + /// + RespectQuietTime = 0x80 + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconDataMembers.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconDataMembers.cs index 75b05cf..c96d478 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconDataMembers.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconDataMembers.cs @@ -1,70 +1,70 @@ -using System; - -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Indicates which members of a structure - /// were set, and thus contain valid data or provide additional information - /// to the ToolTip as to how it should display. - /// - [Flags] - public enum IconDataMembers - { - /// - /// The message ID is set. - /// - Message = 0x01, - - /// - /// The notification icon is set. - /// - Icon = 0x02, - - /// - /// The tooltip is set. - /// - Tip = 0x04, - - /// - /// State information () is set. This - /// applies to both and - /// . - /// - State = 0x08, - - /// - /// The balloon ToolTip is set. Accordingly, the following - /// members are set: , - /// , , - /// and . - /// - Info = 0x10, - - // Internal identifier is set. Reserved, thus commented out. - //Guid = 0x20, - - /// - /// Windows Vista (Shell32.dll version 6.0.6) and later. If the ToolTip - /// cannot be displayed immediately, discard it.
- /// Use this flag for ToolTips that represent real-time information which - /// would be meaningless or misleading if displayed at a later time. - /// For example, a message that states "Your telephone is ringing."
- /// This modifies and must be combined with the flag. - ///
- Realtime = 0x40, - - /// - /// Windows Vista (Shell32.dll version 6.0.6) and later. - /// Use the standard ToolTip. Normally, when uVersion is set - /// to NOTIFYICON_VERSION_4, the standard ToolTip is replaced - /// by the application-drawn pop-up user interface (UI). - /// If the application wants to show the standard tooltip - /// in that case, regardless of whether the on-hover UI is showing, - /// it can specify NIF_SHOWTIP to indicate the standard tooltip - /// should still be shown.
- /// Note that the NIF_SHOWTIP flag is effective until the next call - /// to Shell_NotifyIcon. - ///
- UseLegacyToolTips = 0x80 - } +using System; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Indicates which members of a structure + /// were set, and thus contain valid data or provide additional information + /// to the ToolTip as to how it should display. + /// + [Flags] + public enum IconDataMembers + { + /// + /// The message ID is set. + /// + Message = 0x01, + + /// + /// The notification icon is set. + /// + Icon = 0x02, + + /// + /// The tooltip is set. + /// + Tip = 0x04, + + /// + /// State information () is set. This + /// applies to both and + /// . + /// + State = 0x08, + + /// + /// The balloon ToolTip is set. Accordingly, the following + /// members are set: , + /// , , + /// and . + /// + Info = 0x10, + + // Internal identifier is set. Reserved, thus commented out. + //Guid = 0x20, + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. If the ToolTip + /// cannot be displayed immediately, discard it.
+ /// Use this flag for ToolTips that represent real-time information which + /// would be meaningless or misleading if displayed at a later time. + /// For example, a message that states "Your telephone is ringing."
+ /// This modifies and must be combined with the flag. + ///
+ Realtime = 0x40, + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. + /// Use the standard ToolTip. Normally, when uVersion is set + /// to NOTIFYICON_VERSION_4, the standard ToolTip is replaced + /// by the application-drawn pop-up user interface (UI). + /// If the application wants to show the standard tooltip + /// in that case, regardless of whether the on-hover UI is showing, + /// it can specify NIF_SHOWTIP to indicate the standard tooltip + /// should still be shown.
+ /// Note that the NIF_SHOWTIP flag is effective until the next call + /// to Shell_NotifyIcon. + ///
+ UseLegacyToolTips = 0x80 + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconState.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconState.cs index 9238dd0..7fb7f26 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconState.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/IconState.cs @@ -1,22 +1,22 @@ -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// The state of the icon - can be set to - /// hide the icon. - /// - public enum IconState - { - /// - /// The icon is visible. - /// - Visible = 0x00, - - /// - /// Hide the icon. - /// - Hidden = 0x01, - - // The icon is shared - currently not supported, thus commented out. - //Shared = 0x02 - } +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// The state of the icon - can be set to + /// hide the icon. + /// + public enum IconState + { + /// + /// The icon is visible. + /// + Visible = 0x00, + + /// + /// Hide the icon. + /// + Hidden = 0x01, + + // The icon is shared - currently not supported, thus commented out. + //Shared = 0x02 + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/MouseEvent.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/MouseEvent.cs index 3aec31c..fc70578 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/MouseEvent.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/MouseEvent.cs @@ -1,54 +1,54 @@ -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Event flags for clicked events. - /// - public enum MouseEvent - { - /// - /// The mouse was moved withing the - /// taskbar icon's area. - /// - MouseMove, - - /// - /// The right mouse button was clicked. - /// - IconRightMouseDown, - - /// - /// The left mouse button was clicked. - /// - IconLeftMouseDown, - - /// - /// The right mouse button was released. - /// - IconRightMouseUp, - - /// - /// The left mouse button was released. - /// - IconLeftMouseUp, - - /// - /// The middle mouse button was clicked. - /// - IconMiddleMouseDown, - - /// - /// The middle mouse button was released. - /// - IconMiddleMouseUp, - - /// - /// The taskbar icon was double clicked. - /// - IconDoubleClick, - - /// - /// The balloon tip was clicked. - /// - BalloonToolTipClicked - } +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Event flags for clicked events. + /// + public enum MouseEvent + { + /// + /// The mouse was moved withing the + /// taskbar icon's area. + /// + MouseMove, + + /// + /// The right mouse button was clicked. + /// + IconRightMouseDown, + + /// + /// The left mouse button was clicked. + /// + IconLeftMouseDown, + + /// + /// The right mouse button was released. + /// + IconRightMouseUp, + + /// + /// The left mouse button was released. + /// + IconLeftMouseUp, + + /// + /// The middle mouse button was clicked. + /// + IconMiddleMouseDown, + + /// + /// The middle mouse button was released. + /// + IconMiddleMouseUp, + + /// + /// The taskbar icon was double clicked. + /// + IconDoubleClick, + + /// + /// The balloon tip was clicked. + /// + BalloonToolTipClicked + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyCommand.cs index 3e72985..12e134c 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyCommand.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyCommand.cs @@ -1,41 +1,41 @@ -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Main operations performed on the - /// function. - /// - public enum NotifyCommand - { - /// - /// The taskbar icon is being created. - /// - Add = 0x00, - - /// - /// The settings of the taskbar icon are being updated. - /// - Modify = 0x01, - - /// - /// The taskbar icon is deleted. - /// - Delete = 0x02, - - /// - /// Focus is returned to the taskbar icon. Currently not in use. - /// - SetFocus = 0x03, - - /// - /// Shell32.dll version 5.0 and later only. Instructs the taskbar - /// to behave according to the version number specified in the - /// uVersion member of the structure pointed to by lpdata. - /// This message allows you to specify whether you want the version - /// 5.0 behavior found on Microsoft Windows 2000 systems, or the - /// behavior found on earlier Shell versions. The default value for - /// uVersion is zero, indicating that the original Windows 95 notify - /// icon behavior should be used. - /// - SetVersion = 0x04 - } +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Main operations performed on the + /// function. + /// + public enum NotifyCommand + { + /// + /// The taskbar icon is being created. + /// + Add = 0x00, + + /// + /// The settings of the taskbar icon are being updated. + /// + Modify = 0x01, + + /// + /// The taskbar icon is deleted. + /// + Delete = 0x02, + + /// + /// Focus is returned to the taskbar icon. Currently not in use. + /// + SetFocus = 0x03, + + /// + /// Shell32.dll version 5.0 and later only. Instructs the taskbar + /// to behave according to the version number specified in the + /// uVersion member of the structure pointed to by lpdata. + /// This message allows you to specify whether you want the version + /// 5.0 behavior found on Microsoft Windows 2000 systems, or the + /// behavior found on earlier Shell versions. The default value for + /// uVersion is zero, indicating that the original Windows 95 notify + /// icon behavior should be used. + /// + SetVersion = 0x04 + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconData.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconData.cs index 59f8f13..e51db51 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconData.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconData.cs @@ -1,165 +1,165 @@ -using System; -using System.Runtime.InteropServices; - -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// A struct that is submitted in order to configure - /// the taskbar icon. Provides various members that - /// can be configured partially, according to the - /// values of the - /// that were defined. - /// - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct NotifyIconData - { - /// - /// Size of this structure, in bytes. - /// - public uint cbSize; - - /// - /// Handle to the window that receives notification messages associated with an icon in the - /// taskbar status area. The Shell uses hWnd and uID to identify which icon to operate on - /// when Shell_NotifyIcon is invoked. - /// - public IntPtr WindowHandle; - - /// - /// Application-defined identifier of the taskbar icon. The Shell uses hWnd and uID to identify - /// which icon to operate on when Shell_NotifyIcon is invoked. You can have multiple icons - /// associated with a single hWnd by assigning each a different uID. This feature, however - /// is currently not used. - /// - public uint TaskbarIconId; - - /// - /// Flags that indicate which of the other members contain valid data. This member can be - /// a combination of the NIF_XXX constants. - /// - public IconDataMembers ValidMembers; - - /// - /// Application-defined message identifier. The system uses this identifier to send - /// notifications to the window identified in hWnd. - /// - public uint CallbackMessageId; - - /// - /// A handle to the icon that should be displayed. Just - /// Icon.Handle. - /// - public IntPtr IconHandle; - - /// - /// String with the text for a standard ToolTip. It can have a maximum of 64 characters including - /// the terminating NULL. For Version 5.0 and later, szTip can have a maximum of - /// 128 characters, including the terminating NULL. - /// - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string ToolTipText; - - - /// - /// State of the icon. Remember to also set the . - /// - public IconState IconState; - - /// - /// A value that specifies which bits of the state member are retrieved or modified. - /// For example, setting this member to - /// causes only the item's hidden - /// state to be retrieved. - /// - public IconState StateMask; - - /// - /// String with the text for a balloon ToolTip. It can have a maximum of 255 characters. - /// To remove the ToolTip, set the NIF_INFO flag in uFlags and set szInfo to an empty string. - /// - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string BalloonText; - - /// - /// Mainly used to set the version when is invoked - /// with . However, for legacy operations, - /// the same member is also used to set timouts for balloon ToolTips. - /// - public uint VersionOrTimeout; - - /// - /// String containing a title for a balloon ToolTip. This title appears in boldface - /// above the text. It can have a maximum of 63 characters. - /// - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string BalloonTitle; - - /// - /// Adds an icon to a balloon ToolTip, which is placed to the left of the title. If the - /// member is zero-length, the icon is not shown. - /// - public BalloonFlags BalloonFlags; - - /// - /// Windows XP (Shell32.dll version 6.0) and later.
- /// - Windows 7 and later: A registered GUID that identifies the icon. - /// This value overrides uID and is the recommended method of identifying the icon.
- /// - Windows XP through Windows Vista: Reserved. - ///
- public Guid TaskbarIconGuid; - - /// - /// Windows Vista (Shell32.dll version 6.0.6) and later. The handle of a customized - /// balloon icon provided by the application that should be used independently - /// of the tray icon. If this member is non-NULL and the - /// flag is set, this icon is used as the balloon icon.
- /// If this member is NULL, the legacy behavior is carried out. - ///
- public IntPtr CustomBalloonIconHandle; - - - /// - /// Creates a default data structure that provides - /// a hidden taskbar icon without the icon being set. - /// - /// - /// - public static NotifyIconData CreateDefault(IntPtr handle) - { - var data = new NotifyIconData(); - - if (Environment.OSVersion.Version.Major >= 6) - { - //use the current size - data.cbSize = (uint) Marshal.SizeOf(data); - } - else - { - //we need to set another size on xp/2003- otherwise certain - //features (e.g. balloon tooltips) don't work. - data.cbSize = 952; // NOTIFYICONDATAW_V3_SIZE - - //set to fixed timeout - data.VersionOrTimeout = 10; - } - - data.WindowHandle = handle; - data.TaskbarIconId = 0x0; - data.CallbackMessageId = WindowMessageSink.CallbackMessageId; - data.VersionOrTimeout = (uint) NotifyIconVersion.Win95; - - data.IconHandle = IntPtr.Zero; - - //hide initially - data.IconState = IconState.Hidden; - data.StateMask = IconState.Hidden; - - //set flags - data.ValidMembers = IconDataMembers.Message - | IconDataMembers.Icon - | IconDataMembers.Tip; - - //reset strings - data.ToolTipText = data.BalloonText = data.BalloonTitle = String.Empty; - - return data; - } - } +using System; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// A struct that is submitted in order to configure + /// the taskbar icon. Provides various members that + /// can be configured partially, according to the + /// values of the + /// that were defined. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct NotifyIconData + { + /// + /// Size of this structure, in bytes. + /// + public uint cbSize; + + /// + /// Handle to the window that receives notification messages associated with an icon in the + /// taskbar status area. The Shell uses hWnd and uID to identify which icon to operate on + /// when Shell_NotifyIcon is invoked. + /// + public IntPtr WindowHandle; + + /// + /// Application-defined identifier of the taskbar icon. The Shell uses hWnd and uID to identify + /// which icon to operate on when Shell_NotifyIcon is invoked. You can have multiple icons + /// associated with a single hWnd by assigning each a different uID. This feature, however + /// is currently not used. + /// + public uint TaskbarIconId; + + /// + /// Flags that indicate which of the other members contain valid data. This member can be + /// a combination of the NIF_XXX constants. + /// + public IconDataMembers ValidMembers; + + /// + /// Application-defined message identifier. The system uses this identifier to send + /// notifications to the window identified in hWnd. + /// + public uint CallbackMessageId; + + /// + /// A handle to the icon that should be displayed. Just + /// Icon.Handle. + /// + public IntPtr IconHandle; + + /// + /// String with the text for a standard ToolTip. It can have a maximum of 64 characters including + /// the terminating NULL. For Version 5.0 and later, szTip can have a maximum of + /// 128 characters, including the terminating NULL. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string ToolTipText; + + + /// + /// State of the icon. Remember to also set the . + /// + public IconState IconState; + + /// + /// A value that specifies which bits of the state member are retrieved or modified. + /// For example, setting this member to + /// causes only the item's hidden + /// state to be retrieved. + /// + public IconState StateMask; + + /// + /// String with the text for a balloon ToolTip. It can have a maximum of 255 characters. + /// To remove the ToolTip, set the NIF_INFO flag in uFlags and set szInfo to an empty string. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string BalloonText; + + /// + /// Mainly used to set the version when is invoked + /// with . However, for legacy operations, + /// the same member is also used to set timouts for balloon ToolTips. + /// + public uint VersionOrTimeout; + + /// + /// String containing a title for a balloon ToolTip. This title appears in boldface + /// above the text. It can have a maximum of 63 characters. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string BalloonTitle; + + /// + /// Adds an icon to a balloon ToolTip, which is placed to the left of the title. If the + /// member is zero-length, the icon is not shown. + /// + public BalloonFlags BalloonFlags; + + /// + /// Windows XP (Shell32.dll version 6.0) and later.
+ /// - Windows 7 and later: A registered GUID that identifies the icon. + /// This value overrides uID and is the recommended method of identifying the icon.
+ /// - Windows XP through Windows Vista: Reserved. + ///
+ public Guid TaskbarIconGuid; + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The handle of a customized + /// balloon icon provided by the application that should be used independently + /// of the tray icon. If this member is non-NULL and the + /// flag is set, this icon is used as the balloon icon.
+ /// If this member is NULL, the legacy behavior is carried out. + ///
+ public IntPtr CustomBalloonIconHandle; + + + /// + /// Creates a default data structure that provides + /// a hidden taskbar icon without the icon being set. + /// + /// + /// + public static NotifyIconData CreateDefault(IntPtr handle) + { + var data = new NotifyIconData(); + + if (Environment.OSVersion.Version.Major >= 6) + { + //use the current size + data.cbSize = (uint) Marshal.SizeOf(data); + } + else + { + //we need to set another size on xp/2003- otherwise certain + //features (e.g. balloon tooltips) don't work. + data.cbSize = 952; // NOTIFYICONDATAW_V3_SIZE + + //set to fixed timeout + data.VersionOrTimeout = 10; + } + + data.WindowHandle = handle; + data.TaskbarIconId = 0x0; + data.CallbackMessageId = WindowMessageSink.CallbackMessageId; + data.VersionOrTimeout = (uint) NotifyIconVersion.Win95; + + data.IconHandle = IntPtr.Zero; + + //hide initially + data.IconState = IconState.Hidden; + data.StateMask = IconState.Hidden; + + //set flags + data.ValidMembers = IconDataMembers.Message + | IconDataMembers.Icon + | IconDataMembers.Tip; + + //reset strings + data.ToolTipText = data.BalloonText = data.BalloonTitle = String.Empty; + + return data; + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs index 277f278..5e8a436 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs @@ -1,27 +1,27 @@ -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// The notify icon version that is used. The higher - /// the version, the more capabilities are available. - /// - public enum NotifyIconVersion - { - /// - /// Default behavior (legacy Win95). Expects - /// a size of 488. - /// - Win95 = 0x0, - - /// - /// Behavior representing Win2000 an higher. Expects - /// a size of 504. - /// - Win2000 = 0x3, - - /// - /// Extended tooltip support, which is available - /// for Vista and later. - /// - Vista = 0x4 - } +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// The notify icon version that is used. The higher + /// the version, the more capabilities are available. + /// + public enum NotifyIconVersion + { + /// + /// Default behavior (legacy Win95). Expects + /// a size of 488. + /// + Win95 = 0x0, + + /// + /// Behavior representing Win2000 an higher. Expects + /// a size of 504. + /// + Win2000 = 0x3, + + /// + /// Extended tooltip support, which is available + /// for Vista and later. + /// + Vista = 0x4 + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/Point.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/Point.cs index 39e3e5e..585344f 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/Point.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/Point.cs @@ -1,20 +1,20 @@ -using System.Runtime.InteropServices; - -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Win API struct providing coordinates for a single point. - /// - [StructLayout(LayoutKind.Sequential)] - public struct Point - { - /// - /// X coordinate. - /// - public int X; - /// - /// Y coordinate. - /// - public int Y; - } +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Win API struct providing coordinates for a single point. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Point + { + /// + /// X coordinate. + /// + public int X; + /// + /// Y coordinate. + /// + public int Y; + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/TrayInfo.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/TrayInfo.cs index 9ddc83f..468a833 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/TrayInfo.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/TrayInfo.cs @@ -1,164 +1,164 @@ -// Some interop code taken from Mike Marshall's AnyForm - -using System; -using System.Drawing; -using System.Runtime.InteropServices; - - -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Resolves the current tray position. - /// - public static class TrayInfo - { - /// - /// Gets the position of the system tray. - /// - /// Tray coordinates. - public static Point GetTrayLocation() - { - var info = new AppBarInfo(); - info.GetSystemTaskBarPosition(); - - Rectangle rcWorkArea = info.WorkArea; - - int x = 0, y = 0; - if (info.Edge == AppBarInfo.ScreenEdge.Left) - { - x = rcWorkArea.Left + 2; - y = rcWorkArea.Bottom; - } - else if (info.Edge == AppBarInfo.ScreenEdge.Bottom) - { - x = rcWorkArea.Right; - y = rcWorkArea.Bottom; - } - else if (info.Edge == AppBarInfo.ScreenEdge.Top) - { - x = rcWorkArea.Right; - y = rcWorkArea.Top; - } - else if (info.Edge == AppBarInfo.ScreenEdge.Right) - { - x = rcWorkArea.Right; - y = rcWorkArea.Bottom; - } - - return new Point {X = x, Y = y}; - } - } - - - internal class AppBarInfo - { - [DllImport("user32.dll")] - private static extern IntPtr FindWindow(String lpClassName, String lpWindowName); - - [DllImport("shell32.dll")] - private static extern UInt32 SHAppBarMessage(UInt32 dwMessage, ref APPBARDATA data); - - [DllImport("user32.dll")] - private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, - IntPtr pvParam, UInt32 fWinIni); - - - private const int ABE_BOTTOM = 3; - private const int ABE_LEFT = 0; - private const int ABE_RIGHT = 2; - private const int ABE_TOP = 1; - - private const int ABM_GETTASKBARPOS = 0x00000005; - - // SystemParametersInfo constants - private const UInt32 SPI_GETWORKAREA = 0x0030; - - private APPBARDATA m_data; - - public ScreenEdge Edge - { - get { return (ScreenEdge) m_data.uEdge; } - } - - - public Rectangle WorkArea - { - get - { - Int32 bResult = 0; - var rc = new RECT(); - IntPtr rawRect = Marshal.AllocHGlobal(Marshal.SizeOf(rc)); - bResult = SystemParametersInfo(SPI_GETWORKAREA, 0, rawRect, 0); - rc = (RECT) Marshal.PtrToStructure(rawRect, rc.GetType()); - - if (bResult == 1) - { - Marshal.FreeHGlobal(rawRect); - return new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); - } - - return new Rectangle(0, 0, 0, 0); - } - } - - - public void GetPosition(string strClassName, string strWindowName) - { - m_data = new APPBARDATA(); - m_data.cbSize = (UInt32) Marshal.SizeOf(m_data.GetType()); - - IntPtr hWnd = FindWindow(strClassName, strWindowName); - - if (hWnd != IntPtr.Zero) - { - UInt32 uResult = SHAppBarMessage(ABM_GETTASKBARPOS, ref m_data); - - if (uResult != 1) - { - throw new Exception("Failed to communicate with the given AppBar"); - } - } - else - { - throw new Exception("Failed to find an AppBar that matched the given criteria"); - } - } - - - public void GetSystemTaskBarPosition() - { - GetPosition("Shell_TrayWnd", null); - } - - - public enum ScreenEdge - { - Undefined = -1, - Left = ABE_LEFT, - Top = ABE_TOP, - Right = ABE_RIGHT, - Bottom = ABE_BOTTOM - } - - - [StructLayout(LayoutKind.Sequential)] - private struct APPBARDATA - { - public UInt32 cbSize; - public IntPtr hWnd; - public UInt32 uCallbackMessage; - public UInt32 uEdge; - public RECT rc; - public Int32 lParam; - } - - [StructLayout(LayoutKind.Sequential)] - private struct RECT - { - public Int32 left; - public Int32 top; - public Int32 right; - public Int32 bottom; - } - } +// Some interop code taken from Mike Marshall's AnyForm + +using System; +using System.Drawing; +using System.Runtime.InteropServices; + + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Resolves the current tray position. + /// + public static class TrayInfo + { + /// + /// Gets the position of the system tray. + /// + /// Tray coordinates. + public static Point GetTrayLocation() + { + var info = new AppBarInfo(); + info.GetSystemTaskBarPosition(); + + Rectangle rcWorkArea = info.WorkArea; + + int x = 0, y = 0; + if (info.Edge == AppBarInfo.ScreenEdge.Left) + { + x = rcWorkArea.Left + 2; + y = rcWorkArea.Bottom; + } + else if (info.Edge == AppBarInfo.ScreenEdge.Bottom) + { + x = rcWorkArea.Right; + y = rcWorkArea.Bottom; + } + else if (info.Edge == AppBarInfo.ScreenEdge.Top) + { + x = rcWorkArea.Right; + y = rcWorkArea.Top; + } + else if (info.Edge == AppBarInfo.ScreenEdge.Right) + { + x = rcWorkArea.Right; + y = rcWorkArea.Bottom; + } + + return new Point {X = x, Y = y}; + } + } + + + internal class AppBarInfo + { + [DllImport("user32.dll")] + private static extern IntPtr FindWindow(String lpClassName, String lpWindowName); + + [DllImport("shell32.dll")] + private static extern UInt32 SHAppBarMessage(UInt32 dwMessage, ref APPBARDATA data); + + [DllImport("user32.dll")] + private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, + IntPtr pvParam, UInt32 fWinIni); + + + private const int ABE_BOTTOM = 3; + private const int ABE_LEFT = 0; + private const int ABE_RIGHT = 2; + private const int ABE_TOP = 1; + + private const int ABM_GETTASKBARPOS = 0x00000005; + + // SystemParametersInfo constants + private const UInt32 SPI_GETWORKAREA = 0x0030; + + private APPBARDATA m_data; + + public ScreenEdge Edge + { + get { return (ScreenEdge) m_data.uEdge; } + } + + + public Rectangle WorkArea + { + get + { + Int32 bResult = 0; + var rc = new RECT(); + IntPtr rawRect = Marshal.AllocHGlobal(Marshal.SizeOf(rc)); + bResult = SystemParametersInfo(SPI_GETWORKAREA, 0, rawRect, 0); + rc = (RECT) Marshal.PtrToStructure(rawRect, rc.GetType()); + + if (bResult == 1) + { + Marshal.FreeHGlobal(rawRect); + return new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); + } + + return new Rectangle(0, 0, 0, 0); + } + } + + + public void GetPosition(string strClassName, string strWindowName) + { + m_data = new APPBARDATA(); + m_data.cbSize = (UInt32) Marshal.SizeOf(m_data.GetType()); + + IntPtr hWnd = FindWindow(strClassName, strWindowName); + + if (hWnd != IntPtr.Zero) + { + UInt32 uResult = SHAppBarMessage(ABM_GETTASKBARPOS, ref m_data); + + if (uResult != 1) + { + throw new Exception("Failed to communicate with the given AppBar"); + } + } + else + { + throw new Exception("Failed to find an AppBar that matched the given criteria"); + } + } + + + public void GetSystemTaskBarPosition() + { + GetPosition("Shell_TrayWnd", null); + } + + + public enum ScreenEdge + { + Undefined = -1, + Left = ABE_LEFT, + Top = ABE_TOP, + Right = ABE_RIGHT, + Bottom = ABE_BOTTOM + } + + + [StructLayout(LayoutKind.Sequential)] + private struct APPBARDATA + { + public UInt32 cbSize; + public IntPtr hWnd; + public UInt32 uCallbackMessage; + public UInt32 uEdge; + public RECT rc; + public Int32 lParam; + } + + [StructLayout(LayoutKind.Sequential)] + private struct RECT + { + public Int32 left; + public Int32 top; + public Int32 right; + public Int32 bottom; + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WinApi.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WinApi.cs index 8aef54a..a3e4df2 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WinApi.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WinApi.cs @@ -1,89 +1,89 @@ -using System; -using System.Runtime.InteropServices; - -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Win32 API imports. - /// - internal static class WinApi - { - /// - /// Creates, updates or deletes the taskbar icon. - /// - [DllImport("shell32.Dll", CharSet = CharSet.Unicode)] - public static extern bool Shell_NotifyIcon(NotifyCommand cmd, [In] ref NotifyIconData data); - - - /// - /// Creates the helper window that receives messages from the taskar icon. - /// - [DllImport("USER32.DLL", EntryPoint = "CreateWindowExW", SetLastError = true)] - public static extern IntPtr CreateWindowEx(int dwExStyle, [MarshalAs(UnmanagedType.LPWStr)] string lpClassName, - [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, int dwStyle, int x, int y, - int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, - IntPtr lpParam); - - - /// - /// Processes a default windows procedure. - /// - [DllImport("USER32.DLL")] - public static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wparam, IntPtr lparam); - - /// - /// Registers the helper window class. - /// - [DllImport("USER32.DLL", EntryPoint = "RegisterClassW", SetLastError = true)] - public static extern short RegisterClass(ref WindowClass lpWndClass); - - /// - /// Registers a listener for a window message. - /// - /// - /// - [DllImport("User32.Dll", EntryPoint = "RegisterWindowMessageW")] - public static extern uint RegisterWindowMessage([MarshalAs(UnmanagedType.LPWStr)] string lpString); - - /// - /// Used to destroy the hidden helper window that receives messages from the - /// taskbar icon. - /// - /// - /// - [DllImport("USER32.DLL", SetLastError = true)] - public static extern bool DestroyWindow(IntPtr hWnd); - - - /// - /// Gives focus to a given window. - /// - /// - /// - [DllImport("USER32.DLL")] - public static extern bool SetForegroundWindow(IntPtr hWnd); - - - /// - /// Gets the maximum number of milliseconds that can elapse between a - /// first click and a second click for the OS to consider the - /// mouse action a double-click. - /// - /// The maximum amount of time, in milliseconds, that can - /// elapse between a first click and a second click for the OS to - /// consider the mouse action a double-click. - [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] - public static extern int GetDoubleClickTime(); - - - /// - /// 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); - } +using System; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Win32 API imports. + /// + internal static class WinApi + { + /// + /// Creates, updates or deletes the taskbar icon. + /// + [DllImport("shell32.Dll", CharSet = CharSet.Unicode)] + public static extern bool Shell_NotifyIcon(NotifyCommand cmd, [In] ref NotifyIconData data); + + + /// + /// Creates the helper window that receives messages from the taskar icon. + /// + [DllImport("USER32.DLL", EntryPoint = "CreateWindowExW", SetLastError = true)] + public static extern IntPtr CreateWindowEx(int dwExStyle, [MarshalAs(UnmanagedType.LPWStr)] string lpClassName, + [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, int dwStyle, int x, int y, + int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, + IntPtr lpParam); + + + /// + /// Processes a default windows procedure. + /// + [DllImport("USER32.DLL")] + public static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wparam, IntPtr lparam); + + /// + /// Registers the helper window class. + /// + [DllImport("USER32.DLL", EntryPoint = "RegisterClassW", SetLastError = true)] + public static extern short RegisterClass(ref WindowClass lpWndClass); + + /// + /// Registers a listener for a window message. + /// + /// + /// + [DllImport("User32.Dll", EntryPoint = "RegisterWindowMessageW")] + public static extern uint RegisterWindowMessage([MarshalAs(UnmanagedType.LPWStr)] string lpString); + + /// + /// Used to destroy the hidden helper window that receives messages from the + /// taskbar icon. + /// + /// + /// + [DllImport("USER32.DLL", SetLastError = true)] + public static extern bool DestroyWindow(IntPtr hWnd); + + + /// + /// Gives focus to a given window. + /// + /// + /// + [DllImport("USER32.DLL")] + public static extern bool SetForegroundWindow(IntPtr hWnd); + + + /// + /// Gets the maximum number of milliseconds that can elapse between a + /// first click and a second click for the OS to consider the + /// mouse action a double-click. + /// + /// The maximum amount of time, in milliseconds, that can + /// elapse between a first click and a second click for the OS to + /// consider the mouse action a double-click. + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + public static extern int GetDoubleClickTime(); + + + /// + /// 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); + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowClass.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowClass.cs index 8757f04..06ccf7e 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowClass.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowClass.cs @@ -1,35 +1,35 @@ -using System; -using System.Runtime.InteropServices; - -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Callback delegate which is used by the Windows API to - /// submit window messages. - /// - public delegate IntPtr WindowProcedureHandler(IntPtr hwnd, uint uMsg, IntPtr wparam, IntPtr lparam); - - - /// - /// Win API WNDCLASS struct - represents a single window. - /// Used to receive window messages. - /// - [StructLayout(LayoutKind.Sequential)] - public struct WindowClass - { - #pragma warning disable 1591 - - public uint style; - public WindowProcedureHandler lpfnWndProc; - public int cbClsExtra; - public int cbWndExtra; - public IntPtr hInstance; - public IntPtr hIcon; - public IntPtr hCursor; - public IntPtr hbrBackground; - [MarshalAs(UnmanagedType.LPWStr)] public string lpszMenuName; - [MarshalAs(UnmanagedType.LPWStr)] public string lpszClassName; - - #pragma warning restore 1591 - } +using System; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Callback delegate which is used by the Windows API to + /// submit window messages. + /// + public delegate IntPtr WindowProcedureHandler(IntPtr hwnd, uint uMsg, IntPtr wparam, IntPtr lparam); + + + /// + /// Win API WNDCLASS struct - represents a single window. + /// Used to receive window messages. + /// + [StructLayout(LayoutKind.Sequential)] + public struct WindowClass + { + #pragma warning disable 1591 + + public uint style; + public WindowProcedureHandler lpfnWndProc; + public int cbClsExtra; + public int cbWndExtra; + public IntPtr hInstance; + public IntPtr hIcon; + public IntPtr hCursor; + public IntPtr hbrBackground; + [MarshalAs(UnmanagedType.LPWStr)] public string lpszMenuName; + [MarshalAs(UnmanagedType.LPWStr)] public string lpszClassName; + + #pragma warning restore 1591 + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index fc21af9..8b55f18 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -1,367 +1,367 @@ -// hardcodet.net NotifyIcon for WPF -// Copyright (c) 2009 - 2013 Philipp Sumi -// Contact and Information: http://www.hardcodet.net -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the Code Project Open License (CPOL); -// either version 1.0 of the License, or (at your option) any later -// version. -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE - - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace Hardcodet.Wpf.TaskbarNotification.Interop -{ - /// - /// Receives messages from the taskbar icon through - /// window messages of an underlying helper window. - /// - public class WindowMessageSink : IDisposable - { - #region members - - /// - /// The ID of messages that are received from the the - /// taskbar icon. - /// - public const int CallbackMessageId = 0x400; - - /// - /// The ID of the message that is being received if the - /// taskbar is (re)started. - /// - private uint taskbarRestartMessageId; - - /// - /// Used to track whether a mouse-up event is just - /// the aftermath of a double-click and therefore needs - /// to be suppressed. - /// - private bool isDoubleClick; - - /// - /// A delegate that processes messages of the hidden - /// native window that receives window messages. Storing - /// this reference makes sure we don't loose our reference - /// to the message window. - /// - private WindowProcedureHandler messageHandler; - - /// - /// Window class ID. - /// - internal string WindowId { get; private set; } - - /// - /// Handle for the message window. - /// - internal IntPtr MessageWindowHandle { get; private set; } - - /// - /// The version of the underlying icon. Defines how - /// incoming messages are interpreted. - /// - public NotifyIconVersion Version { get; set; } - - #endregion - - #region events - - /// - /// The custom tooltip should be closed or hidden. - /// - public event Action ChangeToolTipStateRequest; - - /// - /// Fired in case the user clicked or moved within - /// the taskbar icon area. - /// - public event Action MouseEventReceived; - - /// - /// Fired if a balloon ToolTip was either displayed - /// or closed (indicated by the boolean flag). - /// - public event Action BalloonToolTipChanged; - - /// - /// Fired if the taskbar was created or restarted. Requires the taskbar - /// icon to be reset. - /// - public event Action TaskbarCreated; - - #endregion - - #region construction - - /// - /// Creates a new message sink that receives message from - /// a given taskbar icon. - /// - /// - public WindowMessageSink(NotifyIconVersion version) - { - Version = version; - CreateMessageWindow(); - } - - - private WindowMessageSink() - { - } - - - /// - /// Creates a dummy instance that provides an empty - /// pointer rather than a real window handler.
- /// Used at design time. - ///
- /// - internal static WindowMessageSink CreateEmpty() - { - return new WindowMessageSink - { - MessageWindowHandle = IntPtr.Zero, - Version = NotifyIconVersion.Vista - }; - } - - #endregion - - #region CreateMessageWindow - - /// - /// Creates the helper message window that is used - /// to receive messages from the taskbar icon. - /// - private void CreateMessageWindow() - { - //generate a unique ID for the window - WindowId = "WPFTaskbarIcon_" + DateTime.Now.Ticks; - - //register window message handler - messageHandler = OnWindowMessageReceived; - - // Create a simple window class which is reference through - //the messageHandler delegate - WindowClass wc; - - wc.style = 0; - wc.lpfnWndProc = messageHandler; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = IntPtr.Zero; - wc.hIcon = IntPtr.Zero; - wc.hCursor = IntPtr.Zero; - wc.hbrBackground = IntPtr.Zero; - wc.lpszMenuName = ""; - wc.lpszClassName = WindowId; - - // Register the window class - WinApi.RegisterClass(ref wc); - - // Get the message used to indicate the taskbar has been restarted - // This is used to re-add icons when the taskbar restarts - taskbarRestartMessageId = WinApi.RegisterWindowMessage("TaskbarCreated"); - - // Create the message window - MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, IntPtr.Zero, IntPtr.Zero, - IntPtr.Zero, IntPtr.Zero); - - if (MessageWindowHandle == IntPtr.Zero) - { -#if SILVERLIGHT - throw new Exception("Message window handle was not a valid pointer."); -#else - throw new Win32Exception("Message window handle was not a valid pointer"); -#endif - } - } - - #endregion - - #region Handle Window Messages - - /// - /// Callback method that receives messages from the taskbar area. - /// - private IntPtr OnWindowMessageReceived(IntPtr hwnd, uint messageId, IntPtr wparam, IntPtr lparam) - { - if (messageId == taskbarRestartMessageId) - { - //recreate the icon if the taskbar was restarted (e.g. due to Win Explorer shutdown) - TaskbarCreated(); - } - - //forward message - ProcessWindowMessage(messageId, wparam, lparam); - - // Pass the message to the default window procedure - return WinApi.DefWindowProc(hwnd, messageId, wparam, lparam); - } - - - /// - /// Processes incoming system messages. - /// - /// Callback ID. - /// If the version is - /// or higher, this parameter can be used to resolve mouse coordinates. - /// Currently not in use. - /// Provides information about the event. - private void ProcessWindowMessage(uint msg, IntPtr wParam, IntPtr lParam) - { - if (msg != CallbackMessageId) return; - - switch (lParam.ToInt32()) - { - case 0x200: - MouseEventReceived(MouseEvent.MouseMove); - break; - - case 0x201: - MouseEventReceived(MouseEvent.IconLeftMouseDown); - break; - - case 0x202: - if (!isDoubleClick) - { - MouseEventReceived(MouseEvent.IconLeftMouseUp); - } - isDoubleClick = false; - break; - - case 0x203: - isDoubleClick = true; - MouseEventReceived(MouseEvent.IconDoubleClick); - break; - - case 0x204: - MouseEventReceived(MouseEvent.IconRightMouseDown); - break; - - case 0x205: - MouseEventReceived(MouseEvent.IconRightMouseUp); - break; - - case 0x206: - //double click with right mouse button - do not trigger event - break; - - case 0x207: - MouseEventReceived(MouseEvent.IconMiddleMouseDown); - break; - - case 520: - MouseEventReceived(MouseEvent.IconMiddleMouseUp); - break; - - case 0x209: - //double click with middle mouse button - do not trigger event - break; - - case 0x402: - BalloonToolTipChanged(true); - break; - - case 0x403: - case 0x404: - BalloonToolTipChanged(false); - break; - - case 0x405: - MouseEventReceived(MouseEvent.BalloonToolTipClicked); - break; - - case 0x406: - ChangeToolTipStateRequest(true); - break; - - case 0x407: - ChangeToolTipStateRequest(false); - break; - - default: - Debug.WriteLine("Unhandled NotifyIcon message ID: " + lParam); - break; - } - } - - #endregion - - #region Dispose - - /// - /// Set to true as soon as Dispose has been invoked. - /// - public bool IsDisposed { get; private set; } - - - /// - /// Disposes the object. - /// - /// This method is not virtual by design. Derived classes - /// should override . - /// - public void Dispose() - { - Dispose(true); - - // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SupressFinalize to - // take this object off the finalization queue - // and prevent finalization code for this object - // from executing a second time. - GC.SuppressFinalize(this); - } - - /// - /// This destructor will run only if the - /// method does not get called. This gives this base class the - /// opportunity to finalize. - /// - /// Important: Do not provide destructors in types derived from - /// this class. - /// - /// - ~WindowMessageSink() - { - Dispose(false); - } - - - /// - /// Removes the windows hook that receives window - /// messages and closes the underlying helper window. - /// - private void Dispose(bool disposing) - { - //don't do anything if the component is already disposed - if (IsDisposed) return; - IsDisposed = true; - - //always destroy the unmanaged handle (even if called from the GC) - WinApi.DestroyWindow(MessageWindowHandle); - messageHandler = null; - } - - #endregion - } +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 - 2013 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Receives messages from the taskbar icon through + /// window messages of an underlying helper window. + /// + public class WindowMessageSink : IDisposable + { + #region members + + /// + /// The ID of messages that are received from the the + /// taskbar icon. + /// + public const int CallbackMessageId = 0x400; + + /// + /// The ID of the message that is being received if the + /// taskbar is (re)started. + /// + private uint taskbarRestartMessageId; + + /// + /// Used to track whether a mouse-up event is just + /// the aftermath of a double-click and therefore needs + /// to be suppressed. + /// + private bool isDoubleClick; + + /// + /// A delegate that processes messages of the hidden + /// native window that receives window messages. Storing + /// this reference makes sure we don't loose our reference + /// to the message window. + /// + private WindowProcedureHandler messageHandler; + + /// + /// Window class ID. + /// + internal string WindowId { get; private set; } + + /// + /// Handle for the message window. + /// + internal IntPtr MessageWindowHandle { get; private set; } + + /// + /// The version of the underlying icon. Defines how + /// incoming messages are interpreted. + /// + public NotifyIconVersion Version { get; set; } + + #endregion + + #region events + + /// + /// The custom tooltip should be closed or hidden. + /// + public event Action ChangeToolTipStateRequest; + + /// + /// Fired in case the user clicked or moved within + /// the taskbar icon area. + /// + public event Action MouseEventReceived; + + /// + /// Fired if a balloon ToolTip was either displayed + /// or closed (indicated by the boolean flag). + /// + public event Action BalloonToolTipChanged; + + /// + /// Fired if the taskbar was created or restarted. Requires the taskbar + /// icon to be reset. + /// + public event Action TaskbarCreated; + + #endregion + + #region construction + + /// + /// Creates a new message sink that receives message from + /// a given taskbar icon. + /// + /// + public WindowMessageSink(NotifyIconVersion version) + { + Version = version; + CreateMessageWindow(); + } + + + private WindowMessageSink() + { + } + + + /// + /// Creates a dummy instance that provides an empty + /// pointer rather than a real window handler.
+ /// Used at design time. + ///
+ /// + internal static WindowMessageSink CreateEmpty() + { + return new WindowMessageSink + { + MessageWindowHandle = IntPtr.Zero, + Version = NotifyIconVersion.Vista + }; + } + + #endregion + + #region CreateMessageWindow + + /// + /// Creates the helper message window that is used + /// to receive messages from the taskbar icon. + /// + private void CreateMessageWindow() + { + //generate a unique ID for the window + WindowId = "WPFTaskbarIcon_" + DateTime.Now.Ticks; + + //register window message handler + messageHandler = OnWindowMessageReceived; + + // Create a simple window class which is reference through + //the messageHandler delegate + WindowClass wc; + + wc.style = 0; + wc.lpfnWndProc = messageHandler; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = IntPtr.Zero; + wc.hIcon = IntPtr.Zero; + wc.hCursor = IntPtr.Zero; + wc.hbrBackground = IntPtr.Zero; + wc.lpszMenuName = ""; + wc.lpszClassName = WindowId; + + // Register the window class + WinApi.RegisterClass(ref wc); + + // Get the message used to indicate the taskbar has been restarted + // This is used to re-add icons when the taskbar restarts + taskbarRestartMessageId = WinApi.RegisterWindowMessage("TaskbarCreated"); + + // Create the message window + MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, IntPtr.Zero, IntPtr.Zero, + IntPtr.Zero, IntPtr.Zero); + + if (MessageWindowHandle == IntPtr.Zero) + { +#if SILVERLIGHT + throw new Exception("Message window handle was not a valid pointer."); +#else + throw new Win32Exception("Message window handle was not a valid pointer"); +#endif + } + } + + #endregion + + #region Handle Window Messages + + /// + /// Callback method that receives messages from the taskbar area. + /// + private IntPtr OnWindowMessageReceived(IntPtr hwnd, uint messageId, IntPtr wparam, IntPtr lparam) + { + if (messageId == taskbarRestartMessageId) + { + //recreate the icon if the taskbar was restarted (e.g. due to Win Explorer shutdown) + TaskbarCreated(); + } + + //forward message + ProcessWindowMessage(messageId, wparam, lparam); + + // Pass the message to the default window procedure + return WinApi.DefWindowProc(hwnd, messageId, wparam, lparam); + } + + + /// + /// Processes incoming system messages. + /// + /// Callback ID. + /// If the version is + /// or higher, this parameter can be used to resolve mouse coordinates. + /// Currently not in use. + /// Provides information about the event. + private void ProcessWindowMessage(uint msg, IntPtr wParam, IntPtr lParam) + { + if (msg != CallbackMessageId) return; + + switch (lParam.ToInt32()) + { + case 0x200: + MouseEventReceived(MouseEvent.MouseMove); + break; + + case 0x201: + MouseEventReceived(MouseEvent.IconLeftMouseDown); + break; + + case 0x202: + if (!isDoubleClick) + { + MouseEventReceived(MouseEvent.IconLeftMouseUp); + } + isDoubleClick = false; + break; + + case 0x203: + isDoubleClick = true; + MouseEventReceived(MouseEvent.IconDoubleClick); + break; + + case 0x204: + MouseEventReceived(MouseEvent.IconRightMouseDown); + break; + + case 0x205: + MouseEventReceived(MouseEvent.IconRightMouseUp); + break; + + case 0x206: + //double click with right mouse button - do not trigger event + break; + + case 0x207: + MouseEventReceived(MouseEvent.IconMiddleMouseDown); + break; + + case 520: + MouseEventReceived(MouseEvent.IconMiddleMouseUp); + break; + + case 0x209: + //double click with middle mouse button - do not trigger event + break; + + case 0x402: + BalloonToolTipChanged(true); + break; + + case 0x403: + case 0x404: + BalloonToolTipChanged(false); + break; + + case 0x405: + MouseEventReceived(MouseEvent.BalloonToolTipClicked); + break; + + case 0x406: + ChangeToolTipStateRequest(true); + break; + + case 0x407: + ChangeToolTipStateRequest(false); + break; + + default: + Debug.WriteLine("Unhandled NotifyIcon message ID: " + lParam); + break; + } + } + + #endregion + + #region Dispose + + /// + /// Set to true as soon as Dispose has been invoked. + /// + public bool IsDisposed { get; private set; } + + + /// + /// Disposes the object. + /// + /// This method is not virtual by design. Derived classes + /// should override . + /// + public void Dispose() + { + Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// This destructor will run only if the + /// method does not get called. This gives this base class the + /// opportunity to finalize. + /// + /// Important: Do not provide destructors in types derived from + /// this class. + /// + /// + ~WindowMessageSink() + { + Dispose(false); + } + + + /// + /// Removes the windows hook that receives window + /// messages and closes the underlying helper window. + /// + private void Dispose(bool disposing) + { + //don't do anything if the component is already disposed + if (IsDisposed) return; + IsDisposed = true; + + //always destroy the unmanaged handle (even if called from the GC) + WinApi.DestroyWindow(MessageWindowHandle); + messageHandler = null; + } + + #endregion + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/NotifyIconWpf.csproj index 82c3ecf..981fc5e 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/NotifyIconWpf.csproj +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -1,83 +1,83 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {7AC63864-7638-41C4-969C-D3197EF2BED9} - library - Properties - Hardcodet.Wpf.TaskbarNotification - Hardcodet.Wpf.TaskbarNotification - v4.0 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - Client - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\Hardcodet.Wpf.TaskbarNotification.xml - AllRules.ruleset - - - - - - - - - - - - - Code - - - - - - - - - - - - - - - - Code - - - - - - - - - + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {7AC63864-7638-41C4-969C-D3197EF2BED9} + library + Properties + Hardcodet.Wpf.TaskbarNotification + Hardcodet.Wpf.TaskbarNotification + v4.0 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AnyCPU + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Hardcodet.Wpf.TaskbarNotification.xml + AllRules.ruleset + + + + + + + + + + + + + Code + + + + + + + + + + + + + + + + Code + + + + + + + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/PopupActivationMode.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/PopupActivationMode.cs index 227fb0a..1415f39 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/PopupActivationMode.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/PopupActivationMode.cs @@ -1,75 +1,75 @@ -// hardcodet.net NotifyIcon for WPF -// Copyright (c) 2009 - 2013 Philipp Sumi -// Contact and Information: http://www.hardcodet.net -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the Code Project Open License (CPOL); -// either version 1.0 of the License, or (at your option) any later -// version. -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE - - -namespace Hardcodet.Wpf.TaskbarNotification -{ - /// - /// Defines flags that define when a popup - /// is being displyed. - /// - public enum PopupActivationMode - { - /// - /// The item is displayed if the user clicks the - /// tray icon with the left mouse button. - /// - LeftClick, - - /// - /// The item is displayed if the user clicks the - /// tray icon with the right mouse button. - /// - RightClick, - - /// - /// The item is displayed if the user double-clicks the - /// tray icon. - /// - DoubleClick, - - /// - /// The item is displayed if the user clicks the - /// tray icon with the left or the right mouse button. - /// - LeftOrRightClick, - - /// - /// The item is displayed if the user clicks the - /// tray icon with the left mouse button or if a - /// double-click is being performed. - /// - LeftOrDoubleClick, - - /// - /// The item is displayed if the user clicks the - /// tray icon with the middle mouse button. - /// - MiddleClick, - - /// - /// The item is displayed whenever a click occurs. - /// - All - } +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 - 2013 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Defines flags that define when a popup + /// is being displyed. + /// + public enum PopupActivationMode + { + /// + /// The item is displayed if the user clicks the + /// tray icon with the left mouse button. + /// + LeftClick, + + /// + /// The item is displayed if the user clicks the + /// tray icon with the right mouse button. + /// + RightClick, + + /// + /// The item is displayed if the user double-clicks the + /// tray icon. + /// + DoubleClick, + + /// + /// The item is displayed if the user clicks the + /// tray icon with the left or the right mouse button. + /// + LeftOrRightClick, + + /// + /// The item is displayed if the user clicks the + /// tray icon with the left mouse button or if a + /// double-click is being performed. + /// + LeftOrDoubleClick, + + /// + /// The item is displayed if the user clicks the + /// tray icon with the middle mouse button. + /// + MiddleClick, + + /// + /// The item is displayed whenever a click occurs. + /// + All + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Properties/AssemblyInfo.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Properties/AssemblyInfo.cs index 12f8fda..49d0d2e 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Properties/AssemblyInfo.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Properties/AssemblyInfo.cs @@ -1,64 +1,64 @@ -using System; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; -using System.Windows.Markup; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyTitle("NotifyIcon for WPF")] -[assembly: AssemblyDescription("NotifyIcon implementation for the WPF platform.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("hardcodet.net")] -[assembly: AssemblyProduct("NotifyIcon WPF")] -[assembly: AssemblyCopyright("Copyright © Philipp Sumi 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - - -[assembly: AssemblyVersion("1.0.5.0")] -[assembly: AssemblyFileVersion("1.0.5.0")] - - -//provides simplified declaration in XAML -[assembly: XmlnsPrefix("http://www.hardcodet.net/taskbar", "tb")] -[assembly: XmlnsDefinition("http://www.hardcodet.net/taskbar", "Hardcodet.Wpf.TaskbarNotification")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) - )] - - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] - +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Markup; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("NotifyIcon for WPF")] +[assembly: AssemblyDescription("NotifyIcon implementation for the WPF platform.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("hardcodet.net")] +[assembly: AssemblyProduct("NotifyIcon WPF")] +[assembly: AssemblyCopyright("Copyright © Philipp Sumi 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + + +[assembly: AssemblyVersion("1.0.5.0")] +[assembly: AssemblyFileVersion("1.0.5.0")] + + +//provides simplified declaration in XAML +[assembly: XmlnsPrefix("http://www.hardcodet.net/taskbar", "tb")] +[assembly: XmlnsDefinition("http://www.hardcodet.net/taskbar", "Hardcodet.Wpf.TaskbarNotification")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) + )] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] + diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/RoutedEventHelper.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/RoutedEventHelper.cs index 89bc299..2e3004a 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/RoutedEventHelper.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/RoutedEventHelper.cs @@ -1,81 +1,81 @@ -using System; -using System.Windows; - -namespace Hardcodet.Wpf.TaskbarNotification -{ - /// - /// Helper class used by routed events of the - /// class. - /// - internal static class RoutedEventHelper - { - #region RoutedEvent Helper Methods - - /// - /// A static helper method to raise a routed event on a target UIElement or ContentElement. - /// - /// UIElement or ContentElement on which to raise the event - /// RoutedEventArgs to use when raising the event - internal static void RaiseEvent(DependencyObject target, RoutedEventArgs args) - { - if (target is UIElement) - { - (target as UIElement).RaiseEvent(args); - } - else if (target is ContentElement) - { - (target as ContentElement).RaiseEvent(args); - } - } - - /// - /// A static helper method that adds a handler for a routed event - /// to a target UIElement or ContentElement. - /// - /// UIElement or ContentElement that listens to the event - /// Event that will be handled - /// Event handler to be added - internal static void AddHandler(DependencyObject element, RoutedEvent routedEvent, Delegate handler) - { - UIElement uie = element as UIElement; - if (uie != null) - { - uie.AddHandler(routedEvent, handler); - } - else - { - ContentElement ce = element as ContentElement; - if (ce != null) - { - ce.AddHandler(routedEvent, handler); - } - } - } - - /// - /// A static helper method that removes a handler for a routed event - /// from a target UIElement or ContentElement. - /// - /// UIElement or ContentElement that listens to the event - /// Event that will no longer be handled - /// Event handler to be removed - internal static void RemoveHandler(DependencyObject element, RoutedEvent routedEvent, Delegate handler) - { - UIElement uie = element as UIElement; - if (uie != null) - { - uie.RemoveHandler(routedEvent, handler); - } - else - { - ContentElement ce = element as ContentElement; - if (ce != null) - { - ce.RemoveHandler(routedEvent, handler); - } - } - } - - #endregion - } +using System; +using System.Windows; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Helper class used by routed events of the + /// class. + /// + internal static class RoutedEventHelper + { + #region RoutedEvent Helper Methods + + /// + /// A static helper method to raise a routed event on a target UIElement or ContentElement. + /// + /// UIElement or ContentElement on which to raise the event + /// RoutedEventArgs to use when raising the event + internal static void RaiseEvent(DependencyObject target, RoutedEventArgs args) + { + if (target is UIElement) + { + (target as UIElement).RaiseEvent(args); + } + else if (target is ContentElement) + { + (target as ContentElement).RaiseEvent(args); + } + } + + /// + /// A static helper method that adds a handler for a routed event + /// to a target UIElement or ContentElement. + /// + /// UIElement or ContentElement that listens to the event + /// Event that will be handled + /// Event handler to be added + internal static void AddHandler(DependencyObject element, RoutedEvent routedEvent, Delegate handler) + { + UIElement uie = element as UIElement; + if (uie != null) + { + uie.AddHandler(routedEvent, handler); + } + else + { + ContentElement ce = element as ContentElement; + if (ce != null) + { + ce.AddHandler(routedEvent, handler); + } + } + } + + /// + /// A static helper method that removes a handler for a routed event + /// from a target UIElement or ContentElement. + /// + /// UIElement or ContentElement that listens to the event + /// Event that will no longer be handled + /// Event handler to be removed + internal static void RemoveHandler(DependencyObject element, RoutedEvent routedEvent, Delegate handler) + { + UIElement uie = element as UIElement; + if (uie != null) + { + uie.RemoveHandler(routedEvent, handler); + } + else + { + ContentElement ce = element as ContentElement; + if (ce != null) + { + ce.RemoveHandler(routedEvent, handler); + } + } + } + + #endregion + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index b0e4bb7..a12c56e 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -1,1891 +1,1891 @@ -// hardcodet.net NotifyIcon for WPF -// Copyright (c) 2009 - 2013 Philipp Sumi -// Contact and Information: http://www.hardcodet.net -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the Code Project Open License (CPOL); -// either version 1.0 of the License, or (at your option) any later -// version. -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE - - -using System; -using System.ComponentModel; -using System.Drawing; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Input; -using System.Windows.Media; -using Hardcodet.Wpf.TaskbarNotification.Interop; - -namespace Hardcodet.Wpf.TaskbarNotification -{ - /// - /// Contains declarations of WPF dependency properties - /// and events. - /// - partial class TaskbarIcon - { - /// - /// Category name that is set on designer properties. - /// - public const string CategoryName = "NotifyIcon"; - - - //POPUP CONTROLS - - #region TrayPopupResolved - - /// - /// TrayPopupResolved Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey TrayPopupResolvedPropertyKey - = DependencyProperty.RegisterReadOnly("TrayPopupResolved", typeof (Popup), typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - - /// - /// A read-only dependency property that returns the - /// that is being displayed in the taskbar area based on a user action. - /// - public static readonly DependencyProperty TrayPopupResolvedProperty - = TrayPopupResolvedPropertyKey.DependencyProperty; - - /// - /// Gets the TrayPopupResolved property. Returns - /// a which is either the - /// control itself or a - /// control that contains the - /// . - /// - [Category(CategoryName)] - public Popup TrayPopupResolved - { - get { return (Popup) GetValue(TrayPopupResolvedProperty); } - } - - /// - /// Provides a secure method for setting the TrayPopupResolved property. - /// This dependency property indicates .... - /// - /// The new value for the property. - protected void SetTrayPopupResolved(Popup value) - { - SetValue(TrayPopupResolvedPropertyKey, value); - } - - #endregion - - #region TrayToolTipResolved - - /// - /// TrayToolTipResolved Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey TrayToolTipResolvedPropertyKey - = DependencyProperty.RegisterReadOnly("TrayToolTipResolved", typeof (ToolTip), typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - - /// - /// A read-only dependency property that returns the - /// that is being displayed. - /// - public static readonly DependencyProperty TrayToolTipResolvedProperty - = TrayToolTipResolvedPropertyKey.DependencyProperty; - - /// - /// Gets the TrayToolTipResolved property. Returns - /// a control that was created - /// in order to display either - /// or . - /// - [Category(CategoryName)] - [Browsable(true)] - [Bindable(true)] - public ToolTip TrayToolTipResolved - { - get { return (ToolTip) GetValue(TrayToolTipResolvedProperty); } - } - - /// - /// Provides a secure method for setting the - /// property. - /// - /// The new value for the property. - protected void SetTrayToolTipResolved(ToolTip value) - { - SetValue(TrayToolTipResolvedPropertyKey, value); - } - - #endregion - - #region CustomBalloon - - /// - /// CustomBalloon Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey CustomBalloonPropertyKey - = DependencyProperty.RegisterReadOnly("CustomBalloon", typeof (Popup), typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// Maintains a currently displayed custom balloon. - /// - public static readonly DependencyProperty CustomBalloonProperty - = CustomBalloonPropertyKey.DependencyProperty; - - /// - /// A custom popup that is being displayed in the tray area in order - /// to display messages to the user. - /// - public Popup CustomBalloon - { - get { return (Popup) GetValue(CustomBalloonProperty); } - } - - /// - /// Provides a secure method for setting the property. - /// - /// The new value for the property. - protected void SetCustomBalloon(Popup value) - { - SetValue(CustomBalloonPropertyKey, value); - } - - #endregion - - //DEPENDENCY PROPERTIES - - #region Icon property / IconSource dependency property - - private Icon icon; - - /// - /// Gets or sets the icon to be displayed. This is not a - /// dependency property - if you want to assign the property - /// through XAML, please use the - /// dependency property. - /// - [Browsable(false)] - public Icon Icon - { - get { return icon; } - set - { - icon = value; - iconData.IconHandle = value == null ? IntPtr.Zero : icon.Handle; - - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Icon); - } - } - - - /// - /// Resolves an image source and updates the property accordingly. - /// - public static readonly DependencyProperty IconSourceProperty = - DependencyProperty.Register("IconSource", - typeof (ImageSource), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null, IconSourcePropertyChanged)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Resolves an image source and updates the property accordingly. - ///
- [Category(CategoryName)] - [Description("Sets the displayed taskbar icon.")] - public ImageSource IconSource - { - get { return (ImageSource) GetValue(IconSourceProperty); } - set { SetValue(IconSourceProperty, value); } - } - - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnIconSourcePropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// - /// Provides information about the updated property. - private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e) - { - ImageSource newValue = (ImageSource) e.NewValue; - - //resolving the ImageSource at design time is unlikely to work - if (!Util.IsDesignMode) Icon = newValue.ToIcon(); - } - - #endregion - - #region ToolTipText dependency property - - /// - /// A tooltip text that is being displayed if no custom - /// was set or if custom tooltips are not supported. - /// - public static readonly DependencyProperty ToolTipTextProperty = - DependencyProperty.Register("ToolTipText", - typeof (string), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(String.Empty, ToolTipTextPropertyChanged)); - - - /// - /// A property wrapper for the - /// dependency property:
- /// A tooltip text that is being displayed if no custom - /// was set or if custom tooltips are not supported. - ///
- [Category(CategoryName)] - [Description("Alternative to a fully blown ToolTip, which is only displayed on Vista and above.")] - public string ToolTipText - { - get { return (string) GetValue(ToolTipTextProperty); } - set { SetValue(ToolTipTextProperty, value); } - } - - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnToolTipTextPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// - /// Provides information about the updated property. - private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e) - { - //do not touch tooltips if we have a custom tooltip element - if (TrayToolTip == null) - { - ToolTip currentToolTip = TrayToolTipResolved; - if (currentToolTip == null) - { - //if we don't have a wrapper tooltip for the tooltip text, create it now - CreateCustomToolTip(); - } - else - { - //if we have a wrapper tooltip that shows the old tooltip text, just update content - currentToolTip.Content = e.NewValue; - } - } - - WriteToolTipSettings(); - } - - #endregion - - #region TrayToolTip dependency property - - /// - /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. - /// Works only with Vista and above. Accordingly, you should make sure that - /// the property is set as well. - /// - public static readonly DependencyProperty TrayToolTipProperty = - DependencyProperty.Register("TrayToolTip", - typeof (UIElement), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null, TrayToolTipPropertyChanged)); - - /// - /// A property wrapper for the - /// dependency property:
- /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. - /// Works only with Vista and above. Accordingly, you should make sure that - /// the property is set as well. - ///
- [Category(CategoryName)] - [Description("Custom UI element that is displayed as a tooltip. Only on Vista and above")] - public UIElement TrayToolTip - { - get { return (UIElement) GetValue(TrayToolTipProperty); } - set { SetValue(TrayToolTipProperty, value); } - } - - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void TrayToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnTrayToolTipPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// - /// Provides information about the updated property. - private void OnTrayToolTipPropertyChanged(DependencyPropertyChangedEventArgs e) - { - //recreate tooltip control - CreateCustomToolTip(); - - if (e.OldValue != null) - { - //remove the taskbar icon reference from the previously used element - SetParentTaskbarIcon((DependencyObject) e.OldValue, null); - } - - if (e.NewValue != null) - { - //set this taskbar icon as a reference to the new tooltip element - SetParentTaskbarIcon((DependencyObject) e.NewValue, this); - } - - //update tooltip settings - needed to make sure a string is set, even - //if the ToolTipText property is not set. Otherwise, the event that - //triggers tooltip display is never fired. - WriteToolTipSettings(); - } - - #endregion - - #region TrayPopup dependency property - - /// - /// A control that is displayed as a popup when the taskbar icon is clicked. - /// - public static readonly DependencyProperty TrayPopupProperty = - DependencyProperty.Register("TrayPopup", - typeof (UIElement), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null, TrayPopupPropertyChanged)); - - /// - /// A property wrapper for the - /// dependency property:
- /// A control that is displayed as a popup when the taskbar icon is clicked. - ///
- [Category(CategoryName)] - [Description("Displayed as a Popup if the user clicks on the taskbar icon.")] - public UIElement TrayPopup - { - get { return (UIElement) GetValue(TrayPopupProperty); } - set { SetValue(TrayPopupProperty, value); } - } - - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void TrayPopupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnTrayPopupPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// - /// Provides information about the updated property. - private void OnTrayPopupPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - { - //remove the taskbar icon reference from the previously used element - SetParentTaskbarIcon((DependencyObject) e.OldValue, null); - } - - - if (e.NewValue != null) - { - //set this taskbar icon as a reference to the new tooltip element - SetParentTaskbarIcon((DependencyObject) e.NewValue, this); - } - - //create a pop - CreatePopup(); - } - - #endregion - - #region MenuActivation dependency property - - /// - /// Defines what mouse events display the context menu. - /// Defaults to . - /// - public static readonly DependencyProperty MenuActivationProperty = - DependencyProperty.Register("MenuActivation", - typeof (PopupActivationMode), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(PopupActivationMode.RightClick)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Defines what mouse events display the context menu. - /// Defaults to . - ///
- [Category(CategoryName)] - [Description("Defines what mouse events display the context menu.")] - public PopupActivationMode MenuActivation - { - get { return (PopupActivationMode) GetValue(MenuActivationProperty); } - set { SetValue(MenuActivationProperty, value); } - } - - #endregion - - #region PopupActivation dependency property - - /// - /// Defines what mouse events trigger the . - /// Default is . - /// - public static readonly DependencyProperty PopupActivationProperty = - DependencyProperty.Register("PopupActivation", - typeof (PopupActivationMode), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(PopupActivationMode.LeftClick)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Defines what mouse events trigger the . - /// Default is . - ///
- [Category(CategoryName)] - [Description("Defines what mouse events display the TaskbarIconPopup.")] - public PopupActivationMode PopupActivation - { - get { return (PopupActivationMode) GetValue(PopupActivationProperty); } - set { SetValue(PopupActivationProperty, value); } - } - - #endregion - - #region Visibility dependency property override - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnVisibilityPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// - /// Provides information about the updated property. - private void OnVisibilityPropertyChanged(DependencyPropertyChangedEventArgs e) - { - Visibility newValue = (Visibility) e.NewValue; - - //update - if (newValue == Visibility.Visible) - { - CreateTaskbarIcon(); - } - else - { - RemoveTaskbarIcon(); - } - } - - #endregion - - #region DataContext dependency property override / target update - - /// - /// Updates the of a given - /// . This method only updates target elements - /// that do not already have a data context of their own, and either assigns - /// the of the NotifyIcon, or the - /// NotifyIcon itself, if no data context was assigned at all. - /// - private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue) - { - //if there is no target or it's data context is determined through a binding - //of its own, keep it - if (target == null || target.IsDataContextDataBound()) return; - - //if the target's data context is the NotifyIcon's old DataContext or the NotifyIcon itself, - //update it - if (ReferenceEquals(this, target.DataContext) || Equals(oldDataContextValue, target.DataContext)) - { - //assign own data context, if available. If there is no data - //context at all, assign NotifyIcon itself. - target.DataContext = newDataContextValue ?? this; - } - } - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnDataContextPropertyChanged(e); - } - - - /// - /// Handles changes of the dependency property. As - /// WPF internally uses the dependency property system and bypasses the - /// property wrapper, updates of the property's value - /// should be handled here. - /// - /// Provides information about the updated property. - private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e) - { - object newValue = e.NewValue; - object oldValue = e.OldValue; - - //replace custom data context for ToolTips, Popup, and - //ContextMenu - UpdateDataContext(TrayPopupResolved, oldValue, newValue); - UpdateDataContext(TrayToolTipResolved, oldValue, newValue); - UpdateDataContext(ContextMenu, oldValue, newValue); - } - - #endregion - - #region ContextMenu dependency property override - - /// - /// A static callback listener which is being invoked if the - /// dependency property has - /// been changed. Invokes the - /// instance method of the changed instance. - /// - /// The currently processed owner of the property. - /// Provides information about the updated property. - private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TaskbarIcon owner = (TaskbarIcon) d; - owner.OnContextMenuPropertyChanged(e); - } - - - /// - /// Releases the old and updates the new property - /// in order to reflect both the NotifyIcon's - /// property and have the assigned. - /// - /// Provides information about the updated property. - private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - { - //remove the taskbar icon reference from the previously used element - SetParentTaskbarIcon((DependencyObject) e.OldValue, null); - } - - if (e.NewValue != null) - { - //set this taskbar icon as a reference to the new tooltip element - SetParentTaskbarIcon((DependencyObject) e.NewValue, this); - } - - UpdateDataContext((ContextMenu) e.NewValue, null, DataContext); - } - - #endregion - - #region DoubleClickCommand dependency property - - /// - /// Associates a command that is being executed if the tray icon is being - /// double clicked. - /// - public static readonly DependencyProperty DoubleClickCommandProperty = - DependencyProperty.Register("DoubleClickCommand", - typeof (ICommand), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Associates a command that is being executed if the tray icon is being - /// double clicked. - ///
- [Category(CategoryName)] - [Description("A command that is being executed if the tray icon is being double-clicked.")] - public ICommand DoubleClickCommand - { - get { return (ICommand) GetValue(DoubleClickCommandProperty); } - set { SetValue(DoubleClickCommandProperty, value); } - } - - #endregion - - #region DoubleClickCommandParameter dependency property - - /// - /// Command parameter for the . - /// - public static readonly DependencyProperty DoubleClickCommandParameterProperty = - DependencyProperty.Register("DoubleClickCommandParameter", - typeof (object), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Command parameter for the . - ///
- [Category(CategoryName)] - [Description("Parameter to submit to the DoubleClickCommand when the user double clicks on the NotifyIcon.")] - public object DoubleClickCommandParameter - { - get { return GetValue(DoubleClickCommandParameterProperty); } - set { SetValue(DoubleClickCommandParameterProperty, value); } - } - - #endregion - - #region DoubleClickCommandTarget dependency property - - /// - /// The target of the command that is fired if the notify icon is double clicked. - /// - public static readonly DependencyProperty DoubleClickCommandTargetProperty = - DependencyProperty.Register("DoubleClickCommandTarget", - typeof (IInputElement), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// The target of the command that is fired if the notify icon is double clicked. - ///
- [Category(CategoryName)] - [Description("The target of the command that is fired if the notify icon is double clicked.")] - public IInputElement DoubleClickCommandTarget - { - get { return (IInputElement) GetValue(DoubleClickCommandTargetProperty); } - set { SetValue(DoubleClickCommandTargetProperty, value); } - } - - #endregion - - #region LeftClickCommand dependency property - - /// - /// Associates a command that is being executed if the tray icon is being - /// double clicked. - /// - public static readonly DependencyProperty LeftClickCommandProperty = - DependencyProperty.Register("LeftClickCommand", - typeof (ICommand), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Associates a command that is being executed if the tray icon is being - /// left-clicked. - ///
- [Category(CategoryName)] - [Description("A command that is being executed if the tray icon is being left-clicked.")] - public ICommand LeftClickCommand - { - get { return (ICommand) GetValue(LeftClickCommandProperty); } - set { SetValue(LeftClickCommandProperty, value); } - } - - #endregion - - #region LeftClickCommandParameter dependency property - - /// - /// Command parameter for the . - /// - public static readonly DependencyProperty LeftClickCommandParameterProperty = - DependencyProperty.Register("LeftClickCommandParameter", - typeof (object), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// Command parameter for the . - ///
- [Category(CategoryName)] - [Description("The target of the command that is fired if the notify icon is clicked with the left mouse button." - )] - public object LeftClickCommandParameter - { - get { return GetValue(LeftClickCommandParameterProperty); } - set { SetValue(LeftClickCommandParameterProperty, value); } - } - - #endregion - - #region LeftClickCommandTarget dependency property - - /// - /// The target of the command that is fired if the notify icon is clicked. - /// - public static readonly DependencyProperty LeftClickCommandTargetProperty = - DependencyProperty.Register("LeftClickCommandTarget", - typeof (IInputElement), - typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null)); - - /// - /// A property wrapper for the - /// dependency property:
- /// The target of the command that is fired if the notify icon is clicked. - ///
- [Category(CategoryName)] - [Description("The target of the command that is fired if the notify icon is clicked with the left mouse button." - )] - public IInputElement LeftClickCommandTarget - { - get { return (IInputElement) GetValue(LeftClickCommandTargetProperty); } - set { SetValue(LeftClickCommandTargetProperty, value); } - } - - #endregion - - //EVENTS - - #region TrayLeftMouseDown - - /// - /// TrayLeftMouseDown Routed Event - /// - public static readonly RoutedEvent TrayLeftMouseDownEvent = EventManager.RegisterRoutedEvent( - "TrayLeftMouseDown", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the user presses the left mouse button. - /// - [Category(CategoryName)] - public event RoutedEventHandler TrayLeftMouseDown - { - add { AddHandler(TrayLeftMouseDownEvent, value); } - remove { RemoveHandler(TrayLeftMouseDownEvent, value); } - } - - /// - /// A helper method to raise the TrayLeftMouseDown event. - /// - protected RoutedEventArgs RaiseTrayLeftMouseDownEvent() - { - RoutedEventArgs args = RaiseTrayLeftMouseDownEvent(this); - return args; - } - - /// - /// A static helper method to raise the TrayLeftMouseDown event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayLeftMouseDownEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayLeftMouseDownEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayRightMouseDown - - /// - /// TrayRightMouseDown Routed Event - /// - public static readonly RoutedEvent TrayRightMouseDownEvent = - EventManager.RegisterRoutedEvent("TrayRightMouseDown", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the presses the right mouse button. - /// - public event RoutedEventHandler TrayRightMouseDown - { - add { AddHandler(TrayRightMouseDownEvent, value); } - remove { RemoveHandler(TrayRightMouseDownEvent, value); } - } - - /// - /// A helper method to raise the TrayRightMouseDown event. - /// - protected RoutedEventArgs RaiseTrayRightMouseDownEvent() - { - return RaiseTrayRightMouseDownEvent(this); - } - - /// - /// A static helper method to raise the TrayRightMouseDown event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayRightMouseDownEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayRightMouseDownEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayMiddleMouseDown - - /// - /// TrayMiddleMouseDown Routed Event - /// - public static readonly RoutedEvent TrayMiddleMouseDownEvent = - EventManager.RegisterRoutedEvent("TrayMiddleMouseDown", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the user presses the middle mouse button. - /// - public event RoutedEventHandler TrayMiddleMouseDown - { - add { AddHandler(TrayMiddleMouseDownEvent, value); } - remove { RemoveHandler(TrayMiddleMouseDownEvent, value); } - } - - /// - /// A helper method to raise the TrayMiddleMouseDown event. - /// - protected RoutedEventArgs RaiseTrayMiddleMouseDownEvent() - { - return RaiseTrayMiddleMouseDownEvent(this); - } - - /// - /// A static helper method to raise the TrayMiddleMouseDown event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayMiddleMouseDownEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayMiddleMouseDownEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayLeftMouseUp - - /// - /// TrayLeftMouseUp Routed Event - /// - public static readonly RoutedEvent TrayLeftMouseUpEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseUp", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the user releases the left mouse button. - /// - public event RoutedEventHandler TrayLeftMouseUp - { - add { AddHandler(TrayLeftMouseUpEvent, value); } - remove { RemoveHandler(TrayLeftMouseUpEvent, value); } - } - - /// - /// A helper method to raise the TrayLeftMouseUp event. - /// - protected RoutedEventArgs RaiseTrayLeftMouseUpEvent() - { - return RaiseTrayLeftMouseUpEvent(this); - } - - /// - /// A static helper method to raise the TrayLeftMouseUp event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayLeftMouseUpEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayLeftMouseUpEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayRightMouseUp - - /// - /// TrayRightMouseUp Routed Event - /// - public static readonly RoutedEvent TrayRightMouseUpEvent = EventManager.RegisterRoutedEvent("TrayRightMouseUp", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the user releases the right mouse button. - /// - public event RoutedEventHandler TrayRightMouseUp - { - add { AddHandler(TrayRightMouseUpEvent, value); } - remove { RemoveHandler(TrayRightMouseUpEvent, value); } - } - - /// - /// A helper method to raise the TrayRightMouseUp event. - /// - protected RoutedEventArgs RaiseTrayRightMouseUpEvent() - { - return RaiseTrayRightMouseUpEvent(this); - } - - /// - /// A static helper method to raise the TrayRightMouseUp event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayRightMouseUpEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayRightMouseUpEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayMiddleMouseUp - - /// - /// TrayMiddleMouseUp Routed Event - /// - public static readonly RoutedEvent TrayMiddleMouseUpEvent = EventManager.RegisterRoutedEvent( - "TrayMiddleMouseUp", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the user releases the middle mouse button. - /// - public event RoutedEventHandler TrayMiddleMouseUp - { - add { AddHandler(TrayMiddleMouseUpEvent, value); } - remove { RemoveHandler(TrayMiddleMouseUpEvent, value); } - } - - /// - /// A helper method to raise the TrayMiddleMouseUp event. - /// - protected RoutedEventArgs RaiseTrayMiddleMouseUpEvent() - { - return RaiseTrayMiddleMouseUpEvent(this); - } - - /// - /// A static helper method to raise the TrayMiddleMouseUp event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayMiddleMouseUpEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayMiddleMouseUpEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayMouseDoubleClick - - /// - /// TrayMouseDoubleClick Routed Event - /// - public static readonly RoutedEvent TrayMouseDoubleClickEvent = - EventManager.RegisterRoutedEvent("TrayMouseDoubleClick", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the user double-clicks the taskbar icon. - /// - public event RoutedEventHandler TrayMouseDoubleClick - { - add { AddHandler(TrayMouseDoubleClickEvent, value); } - remove { RemoveHandler(TrayMouseDoubleClickEvent, value); } - } - - /// - /// A helper method to raise the TrayMouseDoubleClick event. - /// - protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent() - { - RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this); - DoubleClickCommand.ExecuteIfEnabled(DoubleClickCommandParameter, DoubleClickCommandTarget ?? this); - return args; - } - - /// - /// A static helper method to raise the TrayMouseDoubleClick event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayMouseDoubleClickEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayMouseDoubleClickEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayMouseMove - - /// - /// TrayMouseMove Routed Event - /// - public static readonly RoutedEvent TrayMouseMoveEvent = EventManager.RegisterRoutedEvent("TrayMouseMove", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the user moves the mouse over the taskbar icon. - /// - public event RoutedEventHandler TrayMouseMove - { - add { AddHandler(TrayMouseMoveEvent, value); } - remove { RemoveHandler(TrayMouseMoveEvent, value); } - } - - /// - /// A helper method to raise the TrayMouseMove event. - /// - protected RoutedEventArgs RaiseTrayMouseMoveEvent() - { - return RaiseTrayMouseMoveEvent(this); - } - - /// - /// A static helper method to raise the TrayMouseMove event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayMouseMoveEvent(DependencyObject target) - { - if (target == null) return null; - - var args = new RoutedEventArgs(); - args.RoutedEvent = TrayMouseMoveEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayBalloonTipShown - - /// - /// TrayBalloonTipShown Routed Event - /// - public static readonly RoutedEvent TrayBalloonTipShownEvent = - EventManager.RegisterRoutedEvent("TrayBalloonTipShown", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when a balloon ToolTip is displayed. - /// - public event RoutedEventHandler TrayBalloonTipShown - { - add { AddHandler(TrayBalloonTipShownEvent, value); } - remove { RemoveHandler(TrayBalloonTipShownEvent, value); } - } - - /// - /// A helper method to raise the TrayBalloonTipShown event. - /// - protected RoutedEventArgs RaiseTrayBalloonTipShownEvent() - { - return RaiseTrayBalloonTipShownEvent(this); - } - - /// - /// A static helper method to raise the TrayBalloonTipShown event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayBalloonTipShownEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayBalloonTipShownEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayBalloonTipClosed - - /// - /// TrayBalloonTipClosed Routed Event - /// - public static readonly RoutedEvent TrayBalloonTipClosedEvent = - EventManager.RegisterRoutedEvent("TrayBalloonTipClosed", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when a balloon ToolTip was closed. - /// - public event RoutedEventHandler TrayBalloonTipClosed - { - add { AddHandler(TrayBalloonTipClosedEvent, value); } - remove { RemoveHandler(TrayBalloonTipClosedEvent, value); } - } - - /// - /// A helper method to raise the TrayBalloonTipClosed event. - /// - protected RoutedEventArgs RaiseTrayBalloonTipClosedEvent() - { - return RaiseTrayBalloonTipClosedEvent(this); - } - - /// - /// A static helper method to raise the TrayBalloonTipClosed event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayBalloonTipClosedEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayBalloonTipClosedEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayBalloonTipClicked - - /// - /// TrayBalloonTipClicked Routed Event - /// - public static readonly RoutedEvent TrayBalloonTipClickedEvent = - EventManager.RegisterRoutedEvent("TrayBalloonTipClicked", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Occurs when the user clicks on a balloon ToolTip. - /// - public event RoutedEventHandler TrayBalloonTipClicked - { - add { AddHandler(TrayBalloonTipClickedEvent, value); } - remove { RemoveHandler(TrayBalloonTipClickedEvent, value); } - } - - /// - /// A helper method to raise the TrayBalloonTipClicked event. - /// - protected RoutedEventArgs RaiseTrayBalloonTipClickedEvent() - { - return RaiseTrayBalloonTipClickedEvent(this); - } - - /// - /// A static helper method to raise the TrayBalloonTipClicked event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayBalloonTipClickedEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayBalloonTipClickedEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayContextMenuOpen (and PreviewTrayContextMenuOpen) - - /// - /// TrayContextMenuOpen Routed Event - /// - public static readonly RoutedEvent TrayContextMenuOpenEvent = - EventManager.RegisterRoutedEvent("TrayContextMenuOpen", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Bubbled event that occurs when the context menu of the taskbar icon is being displayed. - /// - public event RoutedEventHandler TrayContextMenuOpen - { - add { AddHandler(TrayContextMenuOpenEvent, value); } - remove { RemoveHandler(TrayContextMenuOpenEvent, value); } - } - - /// - /// A helper method to raise the TrayContextMenuOpen event. - /// - protected RoutedEventArgs RaiseTrayContextMenuOpenEvent() - { - return RaiseTrayContextMenuOpenEvent(this); - } - - /// - /// A static helper method to raise the TrayContextMenuOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayContextMenuOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayContextMenuOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - /// - /// PreviewTrayContextMenuOpen Routed Event - /// - public static readonly RoutedEvent PreviewTrayContextMenuOpenEvent = - EventManager.RegisterRoutedEvent("PreviewTrayContextMenuOpen", - RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Tunneled event that occurs when the context menu of the taskbar icon is being displayed. - /// - public event RoutedEventHandler PreviewTrayContextMenuOpen - { - add { AddHandler(PreviewTrayContextMenuOpenEvent, value); } - remove { RemoveHandler(PreviewTrayContextMenuOpenEvent, value); } - } - - /// - /// A helper method to raise the PreviewTrayContextMenuOpen event. - /// - protected RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent() - { - return RaisePreviewTrayContextMenuOpenEvent(this); - } - - /// - /// A static helper method to raise the PreviewTrayContextMenuOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTrayContextMenuOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayPopupOpen (and PreviewTrayPopupOpen) - - /// - /// TrayPopupOpen Routed Event - /// - public static readonly RoutedEvent TrayPopupOpenEvent = EventManager.RegisterRoutedEvent("TrayPopupOpen", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Bubbled event that occurs when the custom popup is being opened. - /// - public event RoutedEventHandler TrayPopupOpen - { - add { AddHandler(TrayPopupOpenEvent, value); } - remove { RemoveHandler(TrayPopupOpenEvent, value); } - } - - /// - /// A helper method to raise the TrayPopupOpen event. - /// - protected RoutedEventArgs RaiseTrayPopupOpenEvent() - { - return RaiseTrayPopupOpenEvent(this); - } - - /// - /// A static helper method to raise the TrayPopupOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayPopupOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayPopupOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - /// - /// PreviewTrayPopupOpen Routed Event - /// - public static readonly RoutedEvent PreviewTrayPopupOpenEvent = - EventManager.RegisterRoutedEvent("PreviewTrayPopupOpen", - RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Tunneled event that occurs when the custom popup is being opened. - /// - public event RoutedEventHandler PreviewTrayPopupOpen - { - add { AddHandler(PreviewTrayPopupOpenEvent, value); } - remove { RemoveHandler(PreviewTrayPopupOpenEvent, value); } - } - - /// - /// A helper method to raise the PreviewTrayPopupOpen event. - /// - protected RoutedEventArgs RaisePreviewTrayPopupOpenEvent() - { - return RaisePreviewTrayPopupOpenEvent(this); - } - - /// - /// A static helper method to raise the PreviewTrayPopupOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTrayPopupOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTrayPopupOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayToolTipOpen (and PreviewTrayToolTipOpen) - - /// - /// TrayToolTipOpen Routed Event - /// - public static readonly RoutedEvent TrayToolTipOpenEvent = EventManager.RegisterRoutedEvent("TrayToolTipOpen", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Bubbled event that occurs when the custom ToolTip is being displayed. - /// - public event RoutedEventHandler TrayToolTipOpen - { - add { AddHandler(TrayToolTipOpenEvent, value); } - remove { RemoveHandler(TrayToolTipOpenEvent, value); } - } - - /// - /// A helper method to raise the TrayToolTipOpen event. - /// - protected RoutedEventArgs RaiseTrayToolTipOpenEvent() - { - return RaiseTrayToolTipOpenEvent(this); - } - - /// - /// A static helper method to raise the TrayToolTipOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayToolTipOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayToolTipOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - /// - /// PreviewTrayToolTipOpen Routed Event - /// - public static readonly RoutedEvent PreviewTrayToolTipOpenEvent = - EventManager.RegisterRoutedEvent("PreviewTrayToolTipOpen", - RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Tunneled event that occurs when the custom ToolTip is being displayed. - /// - public event RoutedEventHandler PreviewTrayToolTipOpen - { - add { AddHandler(PreviewTrayToolTipOpenEvent, value); } - remove { RemoveHandler(PreviewTrayToolTipOpenEvent, value); } - } - - /// - /// A helper method to raise the PreviewTrayToolTipOpen event. - /// - protected RoutedEventArgs RaisePreviewTrayToolTipOpenEvent() - { - return RaisePreviewTrayToolTipOpenEvent(this); - } - - /// - /// A static helper method to raise the PreviewTrayToolTipOpen event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTrayToolTipOpenEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTrayToolTipOpenEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region TrayToolTipClose (and PreviewTrayToolTipClose) - - /// - /// TrayToolTipClose Routed Event - /// - public static readonly RoutedEvent TrayToolTipCloseEvent = EventManager.RegisterRoutedEvent("TrayToolTipClose", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Bubbled event that occurs when a custom tooltip is being closed. - /// - public event RoutedEventHandler TrayToolTipClose - { - add { AddHandler(TrayToolTipCloseEvent, value); } - remove { RemoveHandler(TrayToolTipCloseEvent, value); } - } - - /// - /// A helper method to raise the TrayToolTipClose event. - /// - protected RoutedEventArgs RaiseTrayToolTipCloseEvent() - { - return RaiseTrayToolTipCloseEvent(this); - } - - /// - /// A static helper method to raise the TrayToolTipClose event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseTrayToolTipCloseEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = TrayToolTipCloseEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - /// - /// PreviewTrayToolTipClose Routed Event - /// - public static readonly RoutedEvent PreviewTrayToolTipCloseEvent = - EventManager.RegisterRoutedEvent("PreviewTrayToolTipClose", - RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Tunneled event that occurs when a custom tooltip is being closed. - /// - public event RoutedEventHandler PreviewTrayToolTipClose - { - add { AddHandler(PreviewTrayToolTipCloseEvent, value); } - remove { RemoveHandler(PreviewTrayToolTipCloseEvent, value); } - } - - /// - /// A helper method to raise the PreviewTrayToolTipClose event. - /// - protected RoutedEventArgs RaisePreviewTrayToolTipCloseEvent() - { - return RaisePreviewTrayToolTipCloseEvent(this); - } - - /// - /// A static helper method to raise the PreviewTrayToolTipClose event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePreviewTrayToolTipCloseEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PreviewTrayToolTipCloseEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - //ATTACHED EVENTS - - #region PopupOpened - - /// - /// PopupOpened Attached Routed Event - /// - public static readonly RoutedEvent PopupOpenedEvent = EventManager.RegisterRoutedEvent("PopupOpened", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Adds a handler for the PopupOpened attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddPopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, PopupOpenedEvent, handler); - } - - /// - /// Removes a handler for the PopupOpened attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemovePopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, PopupOpenedEvent, handler); - } - - /// - /// A static helper method to raise the PopupOpened event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaisePopupOpenedEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = PopupOpenedEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region ToolTipOpened - - /// - /// ToolTipOpened Attached Routed Event - /// - public static readonly RoutedEvent ToolTipOpenedEvent = EventManager.RegisterRoutedEvent("ToolTipOpened", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Adds a handler for the ToolTipOpened attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, ToolTipOpenedEvent, handler); - } - - /// - /// Removes a handler for the ToolTipOpened attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemoveToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, ToolTipOpenedEvent, handler); - } - - /// - /// A static helper method to raise the ToolTipOpened event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseToolTipOpenedEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = ToolTipOpenedEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region ToolTipClose - - /// - /// ToolTipClose Attached Routed Event - /// - public static readonly RoutedEvent ToolTipCloseEvent = EventManager.RegisterRoutedEvent("ToolTipClose", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Adds a handler for the ToolTipClose attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, ToolTipCloseEvent, handler); - } - - /// - /// Removes a handler for the ToolTipClose attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemoveToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, ToolTipCloseEvent, handler); - } - - /// - /// A static helper method to raise the ToolTipClose event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - internal static RoutedEventArgs RaiseToolTipCloseEvent(DependencyObject target) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(); - args.RoutedEvent = ToolTipCloseEvent; - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region BalloonShowing - - /// - /// BalloonShowing Attached Routed Event - /// - public static readonly RoutedEvent BalloonShowingEvent = EventManager.RegisterRoutedEvent("BalloonShowing", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Adds a handler for the BalloonShowing attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, BalloonShowingEvent, handler); - } - - /// - /// Removes a handler for the BalloonShowing attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemoveBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, BalloonShowingEvent, handler); - } - - /// - /// A static helper method to raise the BalloonShowing event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - /// The instance that manages the balloon. - internal static RoutedEventArgs RaiseBalloonShowingEvent(DependencyObject target, TaskbarIcon source) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(BalloonShowingEvent, source); - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - #region BalloonClosing - - /// - /// BalloonClosing Attached Routed Event - /// - public static readonly RoutedEvent BalloonClosingEvent = EventManager.RegisterRoutedEvent("BalloonClosing", - RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); - - /// - /// Adds a handler for the BalloonClosing attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be added - public static void AddBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.AddHandler(element, BalloonClosingEvent, handler); - } - - /// - /// Removes a handler for the BalloonClosing attached event - /// - /// UIElement or ContentElement that listens to the event - /// Event handler to be removed - public static void RemoveBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) - { - RoutedEventHelper.RemoveHandler(element, BalloonClosingEvent, handler); - } - - /// - /// A static helper method to raise the BalloonClosing event on a target element. - /// - /// UIElement or ContentElement on which to raise the event - /// The instance that manages the balloon. - internal static RoutedEventArgs RaiseBalloonClosingEvent(DependencyObject target, TaskbarIcon source) - { - if (target == null) return null; - - RoutedEventArgs args = new RoutedEventArgs(BalloonClosingEvent, source); - RoutedEventHelper.RaiseEvent(target, args); - return args; - } - - #endregion - - //ATTACHED PROPERTIES - - #region ParentTaskbarIcon - - /// - /// An attached property that is assigned to displayed UI elements (balloos, tooltips, context menus), and - /// that can be used to bind to this control. The attached property is being derived, so binding is - /// quite straightforward: - /// - /// - /// - /// - public static readonly DependencyProperty ParentTaskbarIconProperty = - DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof (TaskbarIcon), typeof (TaskbarIcon), - new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); - - /// - /// Gets the ParentTaskbarIcon property. This dependency property - /// indicates .... - /// - public static TaskbarIcon GetParentTaskbarIcon(DependencyObject d) - { - return (TaskbarIcon) d.GetValue(ParentTaskbarIconProperty); - } - - /// - /// Sets the ParentTaskbarIcon property. This dependency property - /// indicates .... - /// - public static void SetParentTaskbarIcon(DependencyObject d, TaskbarIcon value) - { - d.SetValue(ParentTaskbarIconProperty, value); - } - - #endregion - - //BASE CLASS PROPERTY OVERRIDES - - /// - /// Registers properties. - /// - static TaskbarIcon() - { - //register change listener for the Visibility property - var md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); - VisibilityProperty.OverrideMetadata(typeof (TaskbarIcon), md); - - //register change listener for the DataContext property - md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged)); - DataContextProperty.OverrideMetadata(typeof (TaskbarIcon), md); - - //register change listener for the ContextMenu property - md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); - ContextMenuProperty.OverrideMetadata(typeof (TaskbarIcon), md); - } - } +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 - 2013 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using Hardcodet.Wpf.TaskbarNotification.Interop; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Contains declarations of WPF dependency properties + /// and events. + /// + partial class TaskbarIcon + { + /// + /// Category name that is set on designer properties. + /// + public const string CategoryName = "NotifyIcon"; + + + //POPUP CONTROLS + + #region TrayPopupResolved + + /// + /// TrayPopupResolved Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey TrayPopupResolvedPropertyKey + = DependencyProperty.RegisterReadOnly("TrayPopupResolved", typeof (Popup), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + + /// + /// A read-only dependency property that returns the + /// that is being displayed in the taskbar area based on a user action. + /// + public static readonly DependencyProperty TrayPopupResolvedProperty + = TrayPopupResolvedPropertyKey.DependencyProperty; + + /// + /// Gets the TrayPopupResolved property. Returns + /// a which is either the + /// control itself or a + /// control that contains the + /// . + /// + [Category(CategoryName)] + public Popup TrayPopupResolved + { + get { return (Popup) GetValue(TrayPopupResolvedProperty); } + } + + /// + /// Provides a secure method for setting the TrayPopupResolved property. + /// This dependency property indicates .... + /// + /// The new value for the property. + protected void SetTrayPopupResolved(Popup value) + { + SetValue(TrayPopupResolvedPropertyKey, value); + } + + #endregion + + #region TrayToolTipResolved + + /// + /// TrayToolTipResolved Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey TrayToolTipResolvedPropertyKey + = DependencyProperty.RegisterReadOnly("TrayToolTipResolved", typeof (ToolTip), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + + /// + /// A read-only dependency property that returns the + /// that is being displayed. + /// + public static readonly DependencyProperty TrayToolTipResolvedProperty + = TrayToolTipResolvedPropertyKey.DependencyProperty; + + /// + /// Gets the TrayToolTipResolved property. Returns + /// a control that was created + /// in order to display either + /// or . + /// + [Category(CategoryName)] + [Browsable(true)] + [Bindable(true)] + public ToolTip TrayToolTipResolved + { + get { return (ToolTip) GetValue(TrayToolTipResolvedProperty); } + } + + /// + /// Provides a secure method for setting the + /// property. + /// + /// The new value for the property. + protected void SetTrayToolTipResolved(ToolTip value) + { + SetValue(TrayToolTipResolvedPropertyKey, value); + } + + #endregion + + #region CustomBalloon + + /// + /// CustomBalloon Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey CustomBalloonPropertyKey + = DependencyProperty.RegisterReadOnly("CustomBalloon", typeof (Popup), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// Maintains a currently displayed custom balloon. + /// + public static readonly DependencyProperty CustomBalloonProperty + = CustomBalloonPropertyKey.DependencyProperty; + + /// + /// A custom popup that is being displayed in the tray area in order + /// to display messages to the user. + /// + public Popup CustomBalloon + { + get { return (Popup) GetValue(CustomBalloonProperty); } + } + + /// + /// Provides a secure method for setting the property. + /// + /// The new value for the property. + protected void SetCustomBalloon(Popup value) + { + SetValue(CustomBalloonPropertyKey, value); + } + + #endregion + + //DEPENDENCY PROPERTIES + + #region Icon property / IconSource dependency property + + private Icon icon; + + /// + /// Gets or sets the icon to be displayed. This is not a + /// dependency property - if you want to assign the property + /// through XAML, please use the + /// dependency property. + /// + [Browsable(false)] + public Icon Icon + { + get { return icon; } + set + { + icon = value; + iconData.IconHandle = value == null ? IntPtr.Zero : icon.Handle; + + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Icon); + } + } + + + /// + /// Resolves an image source and updates the property accordingly. + /// + public static readonly DependencyProperty IconSourceProperty = + DependencyProperty.Register("IconSource", + typeof (ImageSource), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, IconSourcePropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Resolves an image source and updates the property accordingly. + ///
+ [Category(CategoryName)] + [Description("Sets the displayed taskbar icon.")] + public ImageSource IconSource + { + get { return (ImageSource) GetValue(IconSourceProperty); } + set { SetValue(IconSourceProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnIconSourcePropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e) + { + ImageSource newValue = (ImageSource) e.NewValue; + + //resolving the ImageSource at design time is unlikely to work + if (!Util.IsDesignMode) Icon = newValue.ToIcon(); + } + + #endregion + + #region ToolTipText dependency property + + /// + /// A tooltip text that is being displayed if no custom + /// was set or if custom tooltips are not supported. + /// + public static readonly DependencyProperty ToolTipTextProperty = + DependencyProperty.Register("ToolTipText", + typeof (string), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(String.Empty, ToolTipTextPropertyChanged)); + + + /// + /// A property wrapper for the + /// dependency property:
+ /// A tooltip text that is being displayed if no custom + /// was set or if custom tooltips are not supported. + ///
+ [Category(CategoryName)] + [Description("Alternative to a fully blown ToolTip, which is only displayed on Vista and above.")] + public string ToolTipText + { + get { return (string) GetValue(ToolTipTextProperty); } + set { SetValue(ToolTipTextProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnToolTipTextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e) + { + //do not touch tooltips if we have a custom tooltip element + if (TrayToolTip == null) + { + ToolTip currentToolTip = TrayToolTipResolved; + if (currentToolTip == null) + { + //if we don't have a wrapper tooltip for the tooltip text, create it now + CreateCustomToolTip(); + } + else + { + //if we have a wrapper tooltip that shows the old tooltip text, just update content + currentToolTip.Content = e.NewValue; + } + } + + WriteToolTipSettings(); + } + + #endregion + + #region TrayToolTip dependency property + + /// + /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. + /// Works only with Vista and above. Accordingly, you should make sure that + /// the property is set as well. + /// + public static readonly DependencyProperty TrayToolTipProperty = + DependencyProperty.Register("TrayToolTip", + typeof (UIElement), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, TrayToolTipPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon. + /// Works only with Vista and above. Accordingly, you should make sure that + /// the property is set as well. + ///
+ [Category(CategoryName)] + [Description("Custom UI element that is displayed as a tooltip. Only on Vista and above")] + public UIElement TrayToolTip + { + get { return (UIElement) GetValue(TrayToolTipProperty); } + set { SetValue(TrayToolTipProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void TrayToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnTrayToolTipPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnTrayToolTipPropertyChanged(DependencyPropertyChangedEventArgs e) + { + //recreate tooltip control + CreateCustomToolTip(); + + if (e.OldValue != null) + { + //remove the taskbar icon reference from the previously used element + SetParentTaskbarIcon((DependencyObject) e.OldValue, null); + } + + if (e.NewValue != null) + { + //set this taskbar icon as a reference to the new tooltip element + SetParentTaskbarIcon((DependencyObject) e.NewValue, this); + } + + //update tooltip settings - needed to make sure a string is set, even + //if the ToolTipText property is not set. Otherwise, the event that + //triggers tooltip display is never fired. + WriteToolTipSettings(); + } + + #endregion + + #region TrayPopup dependency property + + /// + /// A control that is displayed as a popup when the taskbar icon is clicked. + /// + public static readonly DependencyProperty TrayPopupProperty = + DependencyProperty.Register("TrayPopup", + typeof (UIElement), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, TrayPopupPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// A control that is displayed as a popup when the taskbar icon is clicked. + ///
+ [Category(CategoryName)] + [Description("Displayed as a Popup if the user clicks on the taskbar icon.")] + public UIElement TrayPopup + { + get { return (UIElement) GetValue(TrayPopupProperty); } + set { SetValue(TrayPopupProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void TrayPopupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnTrayPopupPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnTrayPopupPropertyChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + { + //remove the taskbar icon reference from the previously used element + SetParentTaskbarIcon((DependencyObject) e.OldValue, null); + } + + + if (e.NewValue != null) + { + //set this taskbar icon as a reference to the new tooltip element + SetParentTaskbarIcon((DependencyObject) e.NewValue, this); + } + + //create a pop + CreatePopup(); + } + + #endregion + + #region MenuActivation dependency property + + /// + /// Defines what mouse events display the context menu. + /// Defaults to . + /// + public static readonly DependencyProperty MenuActivationProperty = + DependencyProperty.Register("MenuActivation", + typeof (PopupActivationMode), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(PopupActivationMode.RightClick)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Defines what mouse events display the context menu. + /// Defaults to . + ///
+ [Category(CategoryName)] + [Description("Defines what mouse events display the context menu.")] + public PopupActivationMode MenuActivation + { + get { return (PopupActivationMode) GetValue(MenuActivationProperty); } + set { SetValue(MenuActivationProperty, value); } + } + + #endregion + + #region PopupActivation dependency property + + /// + /// Defines what mouse events trigger the . + /// Default is . + /// + public static readonly DependencyProperty PopupActivationProperty = + DependencyProperty.Register("PopupActivation", + typeof (PopupActivationMode), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(PopupActivationMode.LeftClick)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Defines what mouse events trigger the . + /// Default is . + ///
+ [Category(CategoryName)] + [Description("Defines what mouse events display the TaskbarIconPopup.")] + public PopupActivationMode PopupActivation + { + get { return (PopupActivationMode) GetValue(PopupActivationProperty); } + set { SetValue(PopupActivationProperty, value); } + } + + #endregion + + #region Visibility dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnVisibilityPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnVisibilityPropertyChanged(DependencyPropertyChangedEventArgs e) + { + Visibility newValue = (Visibility) e.NewValue; + + //update + if (newValue == Visibility.Visible) + { + CreateTaskbarIcon(); + } + else + { + RemoveTaskbarIcon(); + } + } + + #endregion + + #region DataContext dependency property override / target update + + /// + /// Updates the of a given + /// . This method only updates target elements + /// that do not already have a data context of their own, and either assigns + /// the of the NotifyIcon, or the + /// NotifyIcon itself, if no data context was assigned at all. + /// + private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue) + { + //if there is no target or it's data context is determined through a binding + //of its own, keep it + if (target == null || target.IsDataContextDataBound()) return; + + //if the target's data context is the NotifyIcon's old DataContext or the NotifyIcon itself, + //update it + if (ReferenceEquals(this, target.DataContext) || Equals(oldDataContextValue, target.DataContext)) + { + //assign own data context, if available. If there is no data + //context at all, assign NotifyIcon itself. + target.DataContext = newDataContextValue ?? this; + } + } + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnDataContextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// + /// Provides information about the updated property. + private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e) + { + object newValue = e.NewValue; + object oldValue = e.OldValue; + + //replace custom data context for ToolTips, Popup, and + //ContextMenu + UpdateDataContext(TrayPopupResolved, oldValue, newValue); + UpdateDataContext(TrayToolTipResolved, oldValue, newValue); + UpdateDataContext(ContextMenu, oldValue, newValue); + } + + #endregion + + #region ContextMenu dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnContextMenuPropertyChanged(e); + } + + + /// + /// Releases the old and updates the new property + /// in order to reflect both the NotifyIcon's + /// property and have the assigned. + /// + /// Provides information about the updated property. + private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + { + //remove the taskbar icon reference from the previously used element + SetParentTaskbarIcon((DependencyObject) e.OldValue, null); + } + + if (e.NewValue != null) + { + //set this taskbar icon as a reference to the new tooltip element + SetParentTaskbarIcon((DependencyObject) e.NewValue, this); + } + + UpdateDataContext((ContextMenu) e.NewValue, null, DataContext); + } + + #endregion + + #region DoubleClickCommand dependency property + + /// + /// Associates a command that is being executed if the tray icon is being + /// double clicked. + /// + public static readonly DependencyProperty DoubleClickCommandProperty = + DependencyProperty.Register("DoubleClickCommand", + typeof (ICommand), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Associates a command that is being executed if the tray icon is being + /// double clicked. + ///
+ [Category(CategoryName)] + [Description("A command that is being executed if the tray icon is being double-clicked.")] + public ICommand DoubleClickCommand + { + get { return (ICommand) GetValue(DoubleClickCommandProperty); } + set { SetValue(DoubleClickCommandProperty, value); } + } + + #endregion + + #region DoubleClickCommandParameter dependency property + + /// + /// Command parameter for the . + /// + public static readonly DependencyProperty DoubleClickCommandParameterProperty = + DependencyProperty.Register("DoubleClickCommandParameter", + typeof (object), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Command parameter for the . + ///
+ [Category(CategoryName)] + [Description("Parameter to submit to the DoubleClickCommand when the user double clicks on the NotifyIcon.")] + public object DoubleClickCommandParameter + { + get { return GetValue(DoubleClickCommandParameterProperty); } + set { SetValue(DoubleClickCommandParameterProperty, value); } + } + + #endregion + + #region DoubleClickCommandTarget dependency property + + /// + /// The target of the command that is fired if the notify icon is double clicked. + /// + public static readonly DependencyProperty DoubleClickCommandTargetProperty = + DependencyProperty.Register("DoubleClickCommandTarget", + typeof (IInputElement), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The target of the command that is fired if the notify icon is double clicked. + ///
+ [Category(CategoryName)] + [Description("The target of the command that is fired if the notify icon is double clicked.")] + public IInputElement DoubleClickCommandTarget + { + get { return (IInputElement) GetValue(DoubleClickCommandTargetProperty); } + set { SetValue(DoubleClickCommandTargetProperty, value); } + } + + #endregion + + #region LeftClickCommand dependency property + + /// + /// Associates a command that is being executed if the tray icon is being + /// double clicked. + /// + public static readonly DependencyProperty LeftClickCommandProperty = + DependencyProperty.Register("LeftClickCommand", + typeof (ICommand), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Associates a command that is being executed if the tray icon is being + /// left-clicked. + ///
+ [Category(CategoryName)] + [Description("A command that is being executed if the tray icon is being left-clicked.")] + public ICommand LeftClickCommand + { + get { return (ICommand) GetValue(LeftClickCommandProperty); } + set { SetValue(LeftClickCommandProperty, value); } + } + + #endregion + + #region LeftClickCommandParameter dependency property + + /// + /// Command parameter for the . + /// + public static readonly DependencyProperty LeftClickCommandParameterProperty = + DependencyProperty.Register("LeftClickCommandParameter", + typeof (object), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Command parameter for the . + ///
+ [Category(CategoryName)] + [Description("The target of the command that is fired if the notify icon is clicked with the left mouse button." + )] + public object LeftClickCommandParameter + { + get { return GetValue(LeftClickCommandParameterProperty); } + set { SetValue(LeftClickCommandParameterProperty, value); } + } + + #endregion + + #region LeftClickCommandTarget dependency property + + /// + /// The target of the command that is fired if the notify icon is clicked. + /// + public static readonly DependencyProperty LeftClickCommandTargetProperty = + DependencyProperty.Register("LeftClickCommandTarget", + typeof (IInputElement), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The target of the command that is fired if the notify icon is clicked. + ///
+ [Category(CategoryName)] + [Description("The target of the command that is fired if the notify icon is clicked with the left mouse button." + )] + public IInputElement LeftClickCommandTarget + { + get { return (IInputElement) GetValue(LeftClickCommandTargetProperty); } + set { SetValue(LeftClickCommandTargetProperty, value); } + } + + #endregion + + //EVENTS + + #region TrayLeftMouseDown + + /// + /// TrayLeftMouseDown Routed Event + /// + public static readonly RoutedEvent TrayLeftMouseDownEvent = EventManager.RegisterRoutedEvent( + "TrayLeftMouseDown", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user presses the left mouse button. + /// + [Category(CategoryName)] + public event RoutedEventHandler TrayLeftMouseDown + { + add { AddHandler(TrayLeftMouseDownEvent, value); } + remove { RemoveHandler(TrayLeftMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TrayLeftMouseDown event. + /// + protected RoutedEventArgs RaiseTrayLeftMouseDownEvent() + { + RoutedEventArgs args = RaiseTrayLeftMouseDownEvent(this); + return args; + } + + /// + /// A static helper method to raise the TrayLeftMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayLeftMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayLeftMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayRightMouseDown + + /// + /// TrayRightMouseDown Routed Event + /// + public static readonly RoutedEvent TrayRightMouseDownEvent = + EventManager.RegisterRoutedEvent("TrayRightMouseDown", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the presses the right mouse button. + /// + public event RoutedEventHandler TrayRightMouseDown + { + add { AddHandler(TrayRightMouseDownEvent, value); } + remove { RemoveHandler(TrayRightMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TrayRightMouseDown event. + /// + protected RoutedEventArgs RaiseTrayRightMouseDownEvent() + { + return RaiseTrayRightMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TrayRightMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayRightMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayRightMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayMiddleMouseDown + + /// + /// TrayMiddleMouseDown Routed Event + /// + public static readonly RoutedEvent TrayMiddleMouseDownEvent = + EventManager.RegisterRoutedEvent("TrayMiddleMouseDown", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user presses the middle mouse button. + /// + public event RoutedEventHandler TrayMiddleMouseDown + { + add { AddHandler(TrayMiddleMouseDownEvent, value); } + remove { RemoveHandler(TrayMiddleMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TrayMiddleMouseDown event. + /// + protected RoutedEventArgs RaiseTrayMiddleMouseDownEvent() + { + return RaiseTrayMiddleMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TrayMiddleMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayMiddleMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayMiddleMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayLeftMouseUp + + /// + /// TrayLeftMouseUp Routed Event + /// + public static readonly RoutedEvent TrayLeftMouseUpEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseUp", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user releases the left mouse button. + /// + public event RoutedEventHandler TrayLeftMouseUp + { + add { AddHandler(TrayLeftMouseUpEvent, value); } + remove { RemoveHandler(TrayLeftMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TrayLeftMouseUp event. + /// + protected RoutedEventArgs RaiseTrayLeftMouseUpEvent() + { + return RaiseTrayLeftMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TrayLeftMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayLeftMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayLeftMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayRightMouseUp + + /// + /// TrayRightMouseUp Routed Event + /// + public static readonly RoutedEvent TrayRightMouseUpEvent = EventManager.RegisterRoutedEvent("TrayRightMouseUp", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user releases the right mouse button. + /// + public event RoutedEventHandler TrayRightMouseUp + { + add { AddHandler(TrayRightMouseUpEvent, value); } + remove { RemoveHandler(TrayRightMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TrayRightMouseUp event. + /// + protected RoutedEventArgs RaiseTrayRightMouseUpEvent() + { + return RaiseTrayRightMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TrayRightMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayRightMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayRightMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayMiddleMouseUp + + /// + /// TrayMiddleMouseUp Routed Event + /// + public static readonly RoutedEvent TrayMiddleMouseUpEvent = EventManager.RegisterRoutedEvent( + "TrayMiddleMouseUp", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user releases the middle mouse button. + /// + public event RoutedEventHandler TrayMiddleMouseUp + { + add { AddHandler(TrayMiddleMouseUpEvent, value); } + remove { RemoveHandler(TrayMiddleMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TrayMiddleMouseUp event. + /// + protected RoutedEventArgs RaiseTrayMiddleMouseUpEvent() + { + return RaiseTrayMiddleMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TrayMiddleMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayMiddleMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayMiddleMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayMouseDoubleClick + + /// + /// TrayMouseDoubleClick Routed Event + /// + public static readonly RoutedEvent TrayMouseDoubleClickEvent = + EventManager.RegisterRoutedEvent("TrayMouseDoubleClick", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user double-clicks the taskbar icon. + /// + public event RoutedEventHandler TrayMouseDoubleClick + { + add { AddHandler(TrayMouseDoubleClickEvent, value); } + remove { RemoveHandler(TrayMouseDoubleClickEvent, value); } + } + + /// + /// A helper method to raise the TrayMouseDoubleClick event. + /// + protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent() + { + RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this); + DoubleClickCommand.ExecuteIfEnabled(DoubleClickCommandParameter, DoubleClickCommandTarget ?? this); + return args; + } + + /// + /// A static helper method to raise the TrayMouseDoubleClick event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayMouseDoubleClickEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayMouseDoubleClickEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayMouseMove + + /// + /// TrayMouseMove Routed Event + /// + public static readonly RoutedEvent TrayMouseMoveEvent = EventManager.RegisterRoutedEvent("TrayMouseMove", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user moves the mouse over the taskbar icon. + /// + public event RoutedEventHandler TrayMouseMove + { + add { AddHandler(TrayMouseMoveEvent, value); } + remove { RemoveHandler(TrayMouseMoveEvent, value); } + } + + /// + /// A helper method to raise the TrayMouseMove event. + /// + protected RoutedEventArgs RaiseTrayMouseMoveEvent() + { + return RaiseTrayMouseMoveEvent(this); + } + + /// + /// A static helper method to raise the TrayMouseMove event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayMouseMoveEvent(DependencyObject target) + { + if (target == null) return null; + + var args = new RoutedEventArgs(); + args.RoutedEvent = TrayMouseMoveEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayBalloonTipShown + + /// + /// TrayBalloonTipShown Routed Event + /// + public static readonly RoutedEvent TrayBalloonTipShownEvent = + EventManager.RegisterRoutedEvent("TrayBalloonTipShown", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when a balloon ToolTip is displayed. + /// + public event RoutedEventHandler TrayBalloonTipShown + { + add { AddHandler(TrayBalloonTipShownEvent, value); } + remove { RemoveHandler(TrayBalloonTipShownEvent, value); } + } + + /// + /// A helper method to raise the TrayBalloonTipShown event. + /// + protected RoutedEventArgs RaiseTrayBalloonTipShownEvent() + { + return RaiseTrayBalloonTipShownEvent(this); + } + + /// + /// A static helper method to raise the TrayBalloonTipShown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayBalloonTipShownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayBalloonTipShownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayBalloonTipClosed + + /// + /// TrayBalloonTipClosed Routed Event + /// + public static readonly RoutedEvent TrayBalloonTipClosedEvent = + EventManager.RegisterRoutedEvent("TrayBalloonTipClosed", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when a balloon ToolTip was closed. + /// + public event RoutedEventHandler TrayBalloonTipClosed + { + add { AddHandler(TrayBalloonTipClosedEvent, value); } + remove { RemoveHandler(TrayBalloonTipClosedEvent, value); } + } + + /// + /// A helper method to raise the TrayBalloonTipClosed event. + /// + protected RoutedEventArgs RaiseTrayBalloonTipClosedEvent() + { + return RaiseTrayBalloonTipClosedEvent(this); + } + + /// + /// A static helper method to raise the TrayBalloonTipClosed event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayBalloonTipClosedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayBalloonTipClosedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayBalloonTipClicked + + /// + /// TrayBalloonTipClicked Routed Event + /// + public static readonly RoutedEvent TrayBalloonTipClickedEvent = + EventManager.RegisterRoutedEvent("TrayBalloonTipClicked", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Occurs when the user clicks on a balloon ToolTip. + /// + public event RoutedEventHandler TrayBalloonTipClicked + { + add { AddHandler(TrayBalloonTipClickedEvent, value); } + remove { RemoveHandler(TrayBalloonTipClickedEvent, value); } + } + + /// + /// A helper method to raise the TrayBalloonTipClicked event. + /// + protected RoutedEventArgs RaiseTrayBalloonTipClickedEvent() + { + return RaiseTrayBalloonTipClickedEvent(this); + } + + /// + /// A static helper method to raise the TrayBalloonTipClicked event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayBalloonTipClickedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayBalloonTipClickedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayContextMenuOpen (and PreviewTrayContextMenuOpen) + + /// + /// TrayContextMenuOpen Routed Event + /// + public static readonly RoutedEvent TrayContextMenuOpenEvent = + EventManager.RegisterRoutedEvent("TrayContextMenuOpen", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Bubbled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler TrayContextMenuOpen + { + add { AddHandler(TrayContextMenuOpenEvent, value); } + remove { RemoveHandler(TrayContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the TrayContextMenuOpen event. + /// + protected RoutedEventArgs RaiseTrayContextMenuOpenEvent() + { + return RaiseTrayContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the TrayContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTrayContextMenuOpen Routed Event + /// + public static readonly RoutedEvent PreviewTrayContextMenuOpenEvent = + EventManager.RegisterRoutedEvent("PreviewTrayContextMenuOpen", + RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Tunneled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler PreviewTrayContextMenuOpen + { + add { AddHandler(PreviewTrayContextMenuOpenEvent, value); } + remove { RemoveHandler(PreviewTrayContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTrayContextMenuOpen event. + /// + protected RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent() + { + return RaisePreviewTrayContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTrayContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTrayContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayPopupOpen (and PreviewTrayPopupOpen) + + /// + /// TrayPopupOpen Routed Event + /// + public static readonly RoutedEvent TrayPopupOpenEvent = EventManager.RegisterRoutedEvent("TrayPopupOpen", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Bubbled event that occurs when the custom popup is being opened. + /// + public event RoutedEventHandler TrayPopupOpen + { + add { AddHandler(TrayPopupOpenEvent, value); } + remove { RemoveHandler(TrayPopupOpenEvent, value); } + } + + /// + /// A helper method to raise the TrayPopupOpen event. + /// + protected RoutedEventArgs RaiseTrayPopupOpenEvent() + { + return RaiseTrayPopupOpenEvent(this); + } + + /// + /// A static helper method to raise the TrayPopupOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayPopupOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayPopupOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTrayPopupOpen Routed Event + /// + public static readonly RoutedEvent PreviewTrayPopupOpenEvent = + EventManager.RegisterRoutedEvent("PreviewTrayPopupOpen", + RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Tunneled event that occurs when the custom popup is being opened. + /// + public event RoutedEventHandler PreviewTrayPopupOpen + { + add { AddHandler(PreviewTrayPopupOpenEvent, value); } + remove { RemoveHandler(PreviewTrayPopupOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTrayPopupOpen event. + /// + protected RoutedEventArgs RaisePreviewTrayPopupOpenEvent() + { + return RaisePreviewTrayPopupOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTrayPopupOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTrayPopupOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTrayPopupOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayToolTipOpen (and PreviewTrayToolTipOpen) + + /// + /// TrayToolTipOpen Routed Event + /// + public static readonly RoutedEvent TrayToolTipOpenEvent = EventManager.RegisterRoutedEvent("TrayToolTipOpen", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Bubbled event that occurs when the custom ToolTip is being displayed. + /// + public event RoutedEventHandler TrayToolTipOpen + { + add { AddHandler(TrayToolTipOpenEvent, value); } + remove { RemoveHandler(TrayToolTipOpenEvent, value); } + } + + /// + /// A helper method to raise the TrayToolTipOpen event. + /// + protected RoutedEventArgs RaiseTrayToolTipOpenEvent() + { + return RaiseTrayToolTipOpenEvent(this); + } + + /// + /// A static helper method to raise the TrayToolTipOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayToolTipOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayToolTipOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTrayToolTipOpen Routed Event + /// + public static readonly RoutedEvent PreviewTrayToolTipOpenEvent = + EventManager.RegisterRoutedEvent("PreviewTrayToolTipOpen", + RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Tunneled event that occurs when the custom ToolTip is being displayed. + /// + public event RoutedEventHandler PreviewTrayToolTipOpen + { + add { AddHandler(PreviewTrayToolTipOpenEvent, value); } + remove { RemoveHandler(PreviewTrayToolTipOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTrayToolTipOpen event. + /// + protected RoutedEventArgs RaisePreviewTrayToolTipOpenEvent() + { + return RaisePreviewTrayToolTipOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTrayToolTipOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTrayToolTipOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTrayToolTipOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TrayToolTipClose (and PreviewTrayToolTipClose) + + /// + /// TrayToolTipClose Routed Event + /// + public static readonly RoutedEvent TrayToolTipCloseEvent = EventManager.RegisterRoutedEvent("TrayToolTipClose", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Bubbled event that occurs when a custom tooltip is being closed. + /// + public event RoutedEventHandler TrayToolTipClose + { + add { AddHandler(TrayToolTipCloseEvent, value); } + remove { RemoveHandler(TrayToolTipCloseEvent, value); } + } + + /// + /// A helper method to raise the TrayToolTipClose event. + /// + protected RoutedEventArgs RaiseTrayToolTipCloseEvent() + { + return RaiseTrayToolTipCloseEvent(this); + } + + /// + /// A static helper method to raise the TrayToolTipClose event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTrayToolTipCloseEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TrayToolTipCloseEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTrayToolTipClose Routed Event + /// + public static readonly RoutedEvent PreviewTrayToolTipCloseEvent = + EventManager.RegisterRoutedEvent("PreviewTrayToolTipClose", + RoutingStrategy.Tunnel, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Tunneled event that occurs when a custom tooltip is being closed. + /// + public event RoutedEventHandler PreviewTrayToolTipClose + { + add { AddHandler(PreviewTrayToolTipCloseEvent, value); } + remove { RemoveHandler(PreviewTrayToolTipCloseEvent, value); } + } + + /// + /// A helper method to raise the PreviewTrayToolTipClose event. + /// + protected RoutedEventArgs RaisePreviewTrayToolTipCloseEvent() + { + return RaisePreviewTrayToolTipCloseEvent(this); + } + + /// + /// A static helper method to raise the PreviewTrayToolTipClose event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTrayToolTipCloseEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTrayToolTipCloseEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + //ATTACHED EVENTS + + #region PopupOpened + + /// + /// PopupOpened Attached Routed Event + /// + public static readonly RoutedEvent PopupOpenedEvent = EventManager.RegisterRoutedEvent("PopupOpened", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the PopupOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddPopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, PopupOpenedEvent, handler); + } + + /// + /// Removes a handler for the PopupOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemovePopupOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, PopupOpenedEvent, handler); + } + + /// + /// A static helper method to raise the PopupOpened event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePopupOpenedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PopupOpenedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region ToolTipOpened + + /// + /// ToolTipOpened Attached Routed Event + /// + public static readonly RoutedEvent ToolTipOpenedEvent = EventManager.RegisterRoutedEvent("ToolTipOpened", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the ToolTipOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, ToolTipOpenedEvent, handler); + } + + /// + /// Removes a handler for the ToolTipOpened attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, ToolTipOpenedEvent, handler); + } + + /// + /// A static helper method to raise the ToolTipOpened event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseToolTipOpenedEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = ToolTipOpenedEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region ToolTipClose + + /// + /// ToolTipClose Attached Routed Event + /// + public static readonly RoutedEvent ToolTipCloseEvent = EventManager.RegisterRoutedEvent("ToolTipClose", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the ToolTipClose attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, ToolTipCloseEvent, handler); + } + + /// + /// Removes a handler for the ToolTipClose attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, ToolTipCloseEvent, handler); + } + + /// + /// A static helper method to raise the ToolTipClose event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseToolTipCloseEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = ToolTipCloseEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region BalloonShowing + + /// + /// BalloonShowing Attached Routed Event + /// + public static readonly RoutedEvent BalloonShowingEvent = EventManager.RegisterRoutedEvent("BalloonShowing", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the BalloonShowing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, BalloonShowingEvent, handler); + } + + /// + /// Removes a handler for the BalloonShowing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, BalloonShowingEvent, handler); + } + + /// + /// A static helper method to raise the BalloonShowing event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + /// The instance that manages the balloon. + internal static RoutedEventArgs RaiseBalloonShowingEvent(DependencyObject target, TaskbarIcon source) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(BalloonShowingEvent, source); + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region BalloonClosing + + /// + /// BalloonClosing Attached Routed Event + /// + public static readonly RoutedEvent BalloonClosingEvent = EventManager.RegisterRoutedEvent("BalloonClosing", + RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (TaskbarIcon)); + + /// + /// Adds a handler for the BalloonClosing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be added + public static void AddBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.AddHandler(element, BalloonClosingEvent, handler); + } + + /// + /// Removes a handler for the BalloonClosing attached event + /// + /// UIElement or ContentElement that listens to the event + /// Event handler to be removed + public static void RemoveBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler) + { + RoutedEventHelper.RemoveHandler(element, BalloonClosingEvent, handler); + } + + /// + /// A static helper method to raise the BalloonClosing event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + /// The instance that manages the balloon. + internal static RoutedEventArgs RaiseBalloonClosingEvent(DependencyObject target, TaskbarIcon source) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(BalloonClosingEvent, source); + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + //ATTACHED PROPERTIES + + #region ParentTaskbarIcon + + /// + /// An attached property that is assigned to displayed UI elements (balloos, tooltips, context menus), and + /// that can be used to bind to this control. The attached property is being derived, so binding is + /// quite straightforward: + /// + /// + /// + /// + public static readonly DependencyProperty ParentTaskbarIconProperty = + DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof (TaskbarIcon), typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); + + /// + /// Gets the ParentTaskbarIcon property. This dependency property + /// indicates .... + /// + public static TaskbarIcon GetParentTaskbarIcon(DependencyObject d) + { + return (TaskbarIcon) d.GetValue(ParentTaskbarIconProperty); + } + + /// + /// Sets the ParentTaskbarIcon property. This dependency property + /// indicates .... + /// + public static void SetParentTaskbarIcon(DependencyObject d, TaskbarIcon value) + { + d.SetValue(ParentTaskbarIconProperty, value); + } + + #endregion + + //BASE CLASS PROPERTY OVERRIDES + + /// + /// Registers properties. + /// + static TaskbarIcon() + { + //register change listener for the Visibility property + var md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); + VisibilityProperty.OverrideMetadata(typeof (TaskbarIcon), md); + + //register change listener for the DataContext property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged)); + DataContextProperty.OverrideMetadata(typeof (TaskbarIcon), md); + + //register change listener for the ContextMenu property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); + ContextMenuProperty.OverrideMetadata(typeof (TaskbarIcon), md); + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.cs index 0ce67de..884eedc 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/TaskbarIcon.cs @@ -1,1092 +1,1092 @@ -// hardcodet.net NotifyIcon for WPF -// Copyright (c) 2009 - 2013 Philipp Sumi -// Contact and Information: http://www.hardcodet.net -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the Code Project Open License (CPOL); -// either version 1.0 of the License, or (at your option) any later -// version. -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE - - -using System; -using System.Diagnostics; -using System.Drawing; -using System.Threading; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Interop; -using System.Windows.Threading; -using Hardcodet.Wpf.TaskbarNotification.Interop; -using Point = Hardcodet.Wpf.TaskbarNotification.Interop.Point; - - -namespace Hardcodet.Wpf.TaskbarNotification -{ - /// - /// A WPF proxy to for a taskbar icon (NotifyIcon) that sits in the system's - /// taskbar notification area ("system tray"). - /// - public partial class TaskbarIcon : FrameworkElement, IDisposable - { - #region Members - - /// - /// Represents the current icon data. - /// - private NotifyIconData iconData; - - /// - /// Receives messages from the taskbar icon. - /// - private readonly WindowMessageSink messageSink; - - /// - /// An action that is being invoked if the - /// fires. - /// - private Action singleClickTimerAction; - - /// - /// A timer that is used to differentiate between single - /// and double clicks. - /// - private readonly Timer singleClickTimer; - - /// - /// A timer that is used to close open balloon tooltips. - /// - private readonly Timer balloonCloseTimer; - - /// - /// Indicates whether the taskbar icon has been created or not. - /// - public bool IsTaskbarIconCreated { get; private set; } - - /// - /// Indicates whether custom tooltips are supported, which depends - /// on the OS. Windows Vista or higher is required in order to - /// support this feature. - /// - public bool SupportsCustomToolTips - { - get { return messageSink.Version == NotifyIconVersion.Vista; } - } - - - /// - /// Checks whether a non-tooltip popup is currently opened. - /// - private bool IsPopupOpen - { - get - { - var popup = TrayPopupResolved; - var menu = ContextMenu; - var balloon = CustomBalloon; - - return popup != null && popup.IsOpen || - menu != null && menu.IsOpen || - balloon != null && balloon.IsOpen; - } - } - - private double scalingFactor = double.NaN; - - #endregion - - #region Construction - - /// - /// Inits the taskbar icon and registers a message listener - /// in order to receive events from the taskbar area. - /// - public TaskbarIcon() - { - //using dummy sink in design mode - messageSink = Util.IsDesignMode - ? WindowMessageSink.CreateEmpty() - : new WindowMessageSink(NotifyIconVersion.Win95); - - //init icon data structure - iconData = NotifyIconData.CreateDefault(messageSink.MessageWindowHandle); - - //create the taskbar icon - CreateTaskbarIcon(); - - //register event listeners - messageSink.MouseEventReceived += OnMouseEvent; - messageSink.TaskbarCreated += OnTaskbarCreated; - messageSink.ChangeToolTipStateRequest += OnToolTipChange; - messageSink.BalloonToolTipChanged += OnBalloonToolTipChanged; - - //init single click / balloon timers - singleClickTimer = new Timer(DoSingleClickAction); - balloonCloseTimer = new Timer(CloseBalloonCallback); - - //register listener in order to get notified when the application closes - if (Application.Current != null) Application.Current.Exit += OnExit; - } - - #endregion - - #region Custom Balloons - - /// - /// Shows a custom control as a tooltip in the tray location. - /// - /// - /// An optional animation for the popup. - /// The time after which the popup is being closed. - /// Submit null in order to keep the balloon open inde - /// - /// If - /// is a null reference. - public void ShowCustomBalloon(UIElement balloon, PopupAnimation animation, int? timeout) - { - Dispatcher dispatcher = this.GetDispatcher(); - if (!dispatcher.CheckAccess()) - { - var action = new Action(() => ShowCustomBalloon(balloon, animation, timeout)); - dispatcher.Invoke(DispatcherPriority.Normal, action); - return; - } - - if (balloon == null) throw new ArgumentNullException("balloon"); - if (timeout.HasValue && timeout < 500) - { - string msg = "Invalid timeout of {0} milliseconds. Timeout must be at least 500 ms"; - msg = String.Format(msg, timeout); - throw new ArgumentOutOfRangeException("timeout", msg); - } - - EnsureNotDisposed(); - - //make sure we don't have an open balloon - lock (this) - { - CloseBalloon(); - } - - //create an invisible popup that hosts the UIElement - Popup popup = new Popup(); - popup.AllowsTransparency = true; - - //provide the popup with the taskbar icon's data context - UpdateDataContext(popup, null, DataContext); - - //don't animate by default - devs can use attached - //events or override - popup.PopupAnimation = animation; - - //in case the balloon is cleaned up through routed events, the - //control didn't remove the balloon from its parent popup when - //if was closed the last time - just make sure it doesn't have - //a parent that is a popup - var parent = LogicalTreeHelper.GetParent(balloon) as Popup; - if (parent != null) parent.Child = null; - - if (parent != null) - { - string msg = - "Cannot display control [{0}] in a new balloon popup - that control already has a parent. You may consider creating new balloons every time you want to show one."; - msg = String.Format(msg, balloon); - throw new InvalidOperationException(msg); - } - - popup.Child = balloon; - - //don't set the PlacementTarget as it causes the popup to become hidden if the - //TaskbarIcon's parent is hidden, too... - //popup.PlacementTarget = this; - - popup.Placement = PlacementMode.AbsolutePoint; - popup.StaysOpen = true; - - Point position = TrayInfo.GetTrayLocation(); - position = GetDeviceCoordinates(position); - popup.HorizontalOffset = position.X - 1; - popup.VerticalOffset = position.Y - 1; - - //store reference - lock (this) - { - SetCustomBalloon(popup); - } - - //assign this instance as an attached property - SetParentTaskbarIcon(balloon, this); - - //fire attached event - RaiseBalloonShowingEvent(balloon, this); - - //display item - popup.IsOpen = true; - - if (timeout.HasValue) - { - //register timer to close the popup - balloonCloseTimer.Change(timeout.Value, Timeout.Infinite); - } - } - - - /// - /// Resets the closing timeout, which effectively - /// keeps a displayed balloon message open until - /// it is either closed programmatically through - /// or due to a new - /// message being displayed. - /// - public void ResetBalloonCloseTimer() - { - if (IsDisposed) return; - - lock (this) - { - //reset timer in any case - balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); - } - } - - - /// - /// Closes the current , if the - /// property is set. - /// - public void CloseBalloon() - { - if (IsDisposed) return; - - Dispatcher dispatcher = this.GetDispatcher(); - if (!dispatcher.CheckAccess()) - { - Action action = CloseBalloon; - dispatcher.Invoke(DispatcherPriority.Normal, action); - return; - } - - lock (this) - { - //reset timer in any case - balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); - - //reset old popup, if we still have one - Popup popup = CustomBalloon; - if (popup != null) - { - UIElement element = popup.Child; - - //announce closing - RoutedEventArgs eventArgs = RaiseBalloonClosingEvent(element, this); - if (!eventArgs.Handled) - { - //if the event was handled, clear the reference to the popup, - //but don't close it - the handling code has to manage this stuff now - - //close the popup - popup.IsOpen = false; - - //remove the reference of the popup to the balloon in case we want to reuse - //the balloon (then added to a new popup) - popup.Child = null; - - //reset attached property - if (element != null) SetParentTaskbarIcon(element, null); - } - - //remove custom balloon anyway - SetCustomBalloon(null); - } - } - } - - - /// - /// Timer-invoke event which closes the currently open balloon and - /// resets the dependency property. - /// - private void CloseBalloonCallback(object state) - { - if (IsDisposed) return; - - //switch to UI thread - Action action = CloseBalloon; - this.GetDispatcher().Invoke(action); - } - - #endregion - - #region Process Incoming Mouse Events - - /// - /// Processes mouse events, which are bubbled - /// through the class' routed events, trigger - /// certain actions (e.g. show a popup), or - /// both. - /// - /// Event flag. - private void OnMouseEvent(MouseEvent me) - { - if (IsDisposed) return; - - switch (me) - { - case MouseEvent.MouseMove: - RaiseTrayMouseMoveEvent(); - //immediately return - there's nothing left to evaluate - return; - case MouseEvent.IconRightMouseDown: - RaiseTrayRightMouseDownEvent(); - break; - case MouseEvent.IconLeftMouseDown: - RaiseTrayLeftMouseDownEvent(); - break; - case MouseEvent.IconRightMouseUp: - RaiseTrayRightMouseUpEvent(); - break; - case MouseEvent.IconLeftMouseUp: - RaiseTrayLeftMouseUpEvent(); - break; - case MouseEvent.IconMiddleMouseDown: - RaiseTrayMiddleMouseDownEvent(); - break; - case MouseEvent.IconMiddleMouseUp: - RaiseTrayMiddleMouseUpEvent(); - break; - case MouseEvent.IconDoubleClick: - //cancel single click timer - singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); - //bubble event - RaiseTrayMouseDoubleClickEvent(); - break; - case MouseEvent.BalloonToolTipClicked: - RaiseTrayBalloonTipClickedEvent(); - break; - default: - throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); - } - - - //get mouse coordinates - Point cursorPosition = new Point(); - 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; - - //show popup, if requested - if (me.IsMatch(PopupActivation)) - { - if (me == MouseEvent.IconLeftMouseUp) - { - //show popup once we are sure it's not a double click - singleClickTimerAction = () => - { - LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); - ShowTrayPopup(cursorPosition); - }; - singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); - isLeftClickCommandInvoked = true; - } - else - { - //show popup immediately - ShowTrayPopup(cursorPosition); - } - } - - - //show context menu, if requested - if (me.IsMatch(MenuActivation)) - { - if (me == MouseEvent.IconLeftMouseUp) - { - //show context menu once we are sure it's not a double click - singleClickTimerAction = () => - { - LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); - ShowContextMenu(cursorPosition); - }; - singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); - isLeftClickCommandInvoked = true; - } - else - { - //show context menu immediately - ShowContextMenu(cursorPosition); - } - } - - //make sure the left click command is invoked on mouse clicks - if (me == MouseEvent.IconLeftMouseUp && !isLeftClickCommandInvoked) - { - //show context menu once we are sure it's not a double click - singleClickTimerAction = - () => - { - LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); - }; - singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); - } - } - - #endregion - - #region ToolTips - - /// - /// Displays a custom tooltip, if available. This method is only - /// invoked for Windows Vista and above. - /// - /// Whether to show or hide the tooltip. - private void OnToolTipChange(bool visible) - { - //if we don't have a tooltip, there's nothing to do here... - if (TrayToolTipResolved == null) return; - - if (visible) - { - if (IsPopupOpen) - { - //ignore if we are already displaying something down there - return; - } - - var args = RaisePreviewTrayToolTipOpenEvent(); - if (args.Handled) return; - - TrayToolTipResolved.IsOpen = true; - - //raise attached event first - if (TrayToolTip != null) RaiseToolTipOpenedEvent(TrayToolTip); - - //bubble routed event - RaiseTrayToolTipOpenEvent(); - } - else - { - var args = RaisePreviewTrayToolTipCloseEvent(); - if (args.Handled) return; - - //raise attached event first - if (TrayToolTip != null) RaiseToolTipCloseEvent(TrayToolTip); - - TrayToolTipResolved.IsOpen = false; - - //bubble event - RaiseTrayToolTipCloseEvent(); - } - } - - - /// - /// Creates a control that either - /// wraps the currently set - /// control or the string.
- /// If itself is already - /// a instance, it will be used directly. - ///
- /// We use a rather than - /// because there was no way to prevent a - /// popup from causing cyclic open/close commands if it was - /// placed under the mouse. ToolTip internally uses a Popup of - /// its own, but takes advance of Popup's internal - /// property which prevents this issue. - private void CreateCustomToolTip() - { - //check if the item itself is a tooltip - ToolTip tt = TrayToolTip as ToolTip; - - if (tt == null && TrayToolTip != null) - { - //create an invisible wrapper tooltip that hosts the UIElement - tt = new ToolTip(); - tt.Placement = PlacementMode.Mouse; - - //do *not* set the placement target, as it causes the popup to become hidden if the - //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through - //the ParentTaskbarIcon attached dependency property: - //tt.PlacementTarget = this; - - //make sure the tooltip is invisible - tt.HasDropShadow = false; - tt.BorderThickness = new Thickness(0); - tt.Background = System.Windows.Media.Brushes.Transparent; - - //setting the - tt.StaysOpen = true; - tt.Content = TrayToolTip; - } - else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) - { - //create a simple tooltip for the ToolTipText string - tt = new ToolTip(); - tt.Content = ToolTipText; - } - - //the tooltip explicitly gets the DataContext of this instance. - //If there is no DataContext, the TaskbarIcon assigns itself - if (tt != null) - { - UpdateDataContext(tt, null, DataContext); - } - - //store a reference to the used tooltip - SetTrayToolTipResolved(tt); - } - - - /// - /// Sets tooltip settings for the class depending on defined - /// dependency properties and OS support. - /// - private void WriteToolTipSettings() - { - const IconDataMembers flags = IconDataMembers.Tip; - iconData.ToolTipText = ToolTipText; - - if (messageSink.Version == NotifyIconVersion.Vista) - { - //we need to set a tooltip text to get tooltip events from the - //taskbar icon - if (String.IsNullOrEmpty(iconData.ToolTipText) && TrayToolTipResolved != null) - { - //if we have not tooltip text but a custom tooltip, we - //need to set a dummy value (we're displaying the ToolTip control, not the string) - iconData.ToolTipText = "ToolTip"; - } - } - - //update the tooltip text - Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); - } - - #endregion - - #region Custom Popup - - /// - /// Creates a control that either - /// wraps the currently set - /// control or the string.
- /// If itself is already - /// a instance, it will be used directly. - ///
- /// We use a rather than - /// because there was no way to prevent a - /// popup from causing cyclic open/close commands if it was - /// placed under the mouse. ToolTip internally uses a Popup of - /// its own, but takes advance of Popup's internal - /// property which prevents this issue. - private void CreatePopup() - { - //check if the item itself is a popup - Popup popup = TrayPopup as Popup; - - if (popup == null && TrayPopup != null) - { - //create an invisible popup that hosts the UIElement - popup = new Popup(); - popup.AllowsTransparency = true; - - //don't animate by default - devs can use attached - //events or override - popup.PopupAnimation = PopupAnimation.None; - - //the CreateRootPopup method outputs binding errors in the debug window because - //it tries to bind to "Popup-specific" properties in case they are provided by the child. - //We don't need that so just assign the control as the child. - popup.Child = TrayPopup; - - //do *not* set the placement target, as it causes the popup to become hidden if the - //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through - //the ParentTaskbarIcon attached dependency property: - //popup.PlacementTarget = this; - - popup.Placement = PlacementMode.AbsolutePoint; - popup.StaysOpen = false; - } - - //the popup explicitly gets the DataContext of this instance. - //If there is no DataContext, the TaskbarIcon assigns itself - if (popup != null) - { - UpdateDataContext(popup, null, DataContext); - } - - //store a reference to the used tooltip - SetTrayPopupResolved(popup); - } - - - /// - /// Displays the control if - /// it was set. - /// - private void ShowTrayPopup(Point cursorPosition) - { - if (IsDisposed) return; - - //raise preview event no matter whether popup is currently set - //or not (enables client to set it on demand) - var args = RaisePreviewTrayPopupOpenEvent(); - if (args.Handled) return; - - if (TrayPopup != null) - { - //use absolute position, but place the popup centered above the icon - TrayPopupResolved.Placement = PlacementMode.AbsolutePoint; - TrayPopupResolved.HorizontalOffset = cursorPosition.X; - TrayPopupResolved.VerticalOffset = cursorPosition.Y; - - //open popup - TrayPopupResolved.IsOpen = true; - - IntPtr handle = IntPtr.Zero; - if (TrayPopupResolved.Child != null) - { - //try to get a handle on the popup itself (via its child) - HwndSource source = (HwndSource) PresentationSource.FromVisual(TrayPopupResolved.Child); - if (source != null) handle = source.Handle; - } - - //if we don't have a handle for the popup, fall back to the message sink - if (handle == IntPtr.Zero) handle = messageSink.MessageWindowHandle; - - //activate either popup or message sink to track deactivation. - //otherwise, the popup does not close if the user clicks somewhere else - WinApi.SetForegroundWindow(handle); - - //raise attached event - item should never be null unless developers - //changed the CustomPopup directly... - if (TrayPopup != null) RaisePopupOpenedEvent(TrayPopup); - - //bubble routed event - RaiseTrayPopupOpenEvent(); - } - } - - #endregion - - #region Context Menu - - /// - /// Displays the if - /// it was set. - /// - private void ShowContextMenu(Point cursorPosition) - { - if (IsDisposed) return; - - //raise preview event no matter whether context menu is currently set - //or not (enables client to set it on demand) - var args = RaisePreviewTrayContextMenuOpenEvent(); - if (args.Handled) return; - - if (ContextMenu != null) - { - //use absolute positioning. We need to set the coordinates, or a delayed opening - //(e.g. when left-clicked) opens the context menu at the wrong place if the mouse - //is moved! - ContextMenu.Placement = PlacementMode.AbsolutePoint; - ContextMenu.HorizontalOffset = cursorPosition.X; - ContextMenu.VerticalOffset = cursorPosition.Y; - 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) - { - handle = source.Handle; - } - - //if we don't have a handle for the popup, fall back to the message sink - if (handle == IntPtr.Zero) handle = messageSink.MessageWindowHandle; - - //activate the context menu or the message window to track deactivation - otherwise, the context menu - //does not close if the user clicks somewhere else. With the message window - //fallback, the context menu can't receive keyboard events - should not happen though - WinApi.SetForegroundWindow(handle); - - //bubble event - RaiseTrayContextMenuOpenEvent(); - } - } - - #endregion - - #region Balloon Tips - - /// - /// Bubbles events if a balloon ToolTip was displayed - /// or removed. - /// - /// Whether the ToolTip was just displayed - /// or removed. - private void OnBalloonToolTipChanged(bool visible) - { - if (visible) - { - RaiseTrayBalloonTipShownEvent(); - } - else - { - RaiseTrayBalloonTipClosedEvent(); - } - } - - /// - /// Displays a balloon tip with the specified title, - /// text, and icon in the taskbar for the specified time period. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// A symbol that indicates the severity. - public void ShowBalloonTip(string title, string message, BalloonIcon symbol) - { - lock (this) - { - ShowBalloonTip(title, message, symbol.GetBalloonFlag(), IntPtr.Zero); - } - } - - - /// - /// Displays a balloon tip with the specified title, - /// text, and a custom icon in the taskbar for the specified time period. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// A custom icon. - /// If - /// is a null reference. - public void ShowBalloonTip(string title, string message, Icon customIcon) - { - if (customIcon == null) throw new ArgumentNullException("customIcon"); - - lock (this) - { - ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); - } - } - - - /// - /// Invokes in order to display - /// a given balloon ToolTip. - /// - /// The title to display on the balloon tip. - /// The text to display on the balloon tip. - /// Indicates what icon to use. - /// A handle to a custom icon, if any, or - /// . - private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) - { - EnsureNotDisposed(); - - iconData.BalloonText = message ?? String.Empty; - iconData.BalloonTitle = title ?? String.Empty; - - iconData.BalloonFlags = flags; - iconData.CustomBalloonIconHandle = balloonIconHandle; - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info | IconDataMembers.Icon); - } - - - /// - /// Hides a balloon ToolTip, if any is displayed. - /// - public void HideBalloonTip() - { - EnsureNotDisposed(); - - //reset balloon by just setting the info to an empty string - iconData.BalloonText = iconData.BalloonTitle = String.Empty; - Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); - } - - #endregion - - #region Single Click Timer event - - /// - /// Performs a delayed action if the user requested an action - /// based on a single click of the left mouse.
- /// This method is invoked by the . - ///
- private void DoSingleClickAction(object state) - { - if (IsDisposed) return; - - //run action - Action action = singleClickTimerAction; - if (action != null) - { - //cleanup action - singleClickTimerAction = null; - - //switch to UI thread - this.GetDispatcher().Invoke(action); - } - } - - #endregion - - #region Set Version (API) - - /// - /// Sets the version flag for the . - /// - private void SetVersion() - { - iconData.VersionOrTimeout = (uint) NotifyIconVersion.Vista; - bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); - - if (!status) - { - iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win2000; - status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); - } - - if (!status) - { - iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win95; - status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); - } - - if (!status) - { - Debug.Fail("Could not set version"); - } - } - - #endregion - - #region Create / Remove Taskbar Icon - - /// - /// Recreates the taskbar icon if the whole taskbar was - /// recreated (e.g. because Explorer was shut down). - /// - private void OnTaskbarCreated() - { - IsTaskbarIconCreated = false; - CreateTaskbarIcon(); - } - - - /// - /// Creates the taskbar icon. This message is invoked during initialization, - /// if the taskbar is restarted, and whenever the icon is displayed. - /// - private void CreateTaskbarIcon() - { - lock (this) - { - if (!IsTaskbarIconCreated) - { - const IconDataMembers members = IconDataMembers.Message - | IconDataMembers.Icon - | IconDataMembers.Tip; - - //write initial configuration - var status = Util.WriteIconData(ref iconData, NotifyCommand.Add, members); - if (!status) - { - //couldn't create the icon - we can assume this is because explorer is not running (yet!) - //-> try a bit later again rather than throwing an exception. Typically, if the windows - // shell is being loaded later, this method is being reinvoked from OnTaskbarCreated - // (we could also retry after a delay, but that's currently YAGNI) - return; - } - - //set to most recent version - SetVersion(); - messageSink.Version = (NotifyIconVersion) iconData.VersionOrTimeout; - - IsTaskbarIconCreated = true; - } - } - } - - /// - /// Closes the taskbar icon if required. - /// - private void RemoveTaskbarIcon() - { - lock (this) - { - //make sure we didn't schedule a creation - - if (IsTaskbarIconCreated) - { - Util.WriteIconData(ref iconData, NotifyCommand.Delete, IconDataMembers.Message); - IsTaskbarIconCreated = false; - } - } - } - - #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 - - /// - /// Set to true as soon as Dispose has been invoked. - /// - public bool IsDisposed { get; private set; } - - - /// - /// Checks if the object has been disposed and - /// raises a in case - /// the flag is true. - /// - private void EnsureNotDisposed() - { - if (IsDisposed) throw new ObjectDisposedException(Name ?? GetType().FullName); - } - - - /// - /// Disposes the class if the application exits. - /// - private void OnExit(object sender, EventArgs e) - { - Dispose(); - } - - - /// - /// This destructor will run only if the - /// method does not get called. This gives this base class the - /// opportunity to finalize. - /// - /// Important: Do not provide destructors in types derived from - /// this class. - /// - /// - ~TaskbarIcon() - { - Dispose(false); - } - - - /// - /// Disposes the object. - /// - /// This method is not virtual by design. Derived classes - /// should override . - /// - public void Dispose() - { - Dispose(true); - - // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SupressFinalize to - // take this object off the finalization queue - // and prevent finalization code for this object - // from executing a second time. - GC.SuppressFinalize(this); - } - - - /// - /// Closes the tray and releases all resources. - /// - /// - /// Dispose(bool disposing) executes in two distinct scenarios. - /// If disposing equals true, the method has been called directly - /// or indirectly by a user's code. Managed and unmanaged resources - /// can be disposed. - /// - /// If disposing equals false, the method - /// has been called by the runtime from inside the finalizer and you - /// should not reference other objects. Only unmanaged resources can - /// be disposed. - /// Check the property to determine whether - /// the method has already been called. - private void Dispose(bool disposing) - { - //don't do anything if the component is already disposed - if (IsDisposed || !disposing) return; - - lock (this) - { - IsDisposed = true; - - //deregister application event listener - if (Application.Current != null) - { - Application.Current.Exit -= OnExit; - } - - //stop timers - singleClickTimer.Dispose(); - balloonCloseTimer.Dispose(); - - //dispose message sink - messageSink.Dispose(); - - //remove icon - RemoveTaskbarIcon(); - } - } - - #endregion - } +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 - 2013 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + +using System; +using System.Diagnostics; +using System.Drawing; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Interop; +using System.Windows.Threading; +using Hardcodet.Wpf.TaskbarNotification.Interop; +using Point = Hardcodet.Wpf.TaskbarNotification.Interop.Point; + + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// A WPF proxy to for a taskbar icon (NotifyIcon) that sits in the system's + /// taskbar notification area ("system tray"). + /// + public partial class TaskbarIcon : FrameworkElement, IDisposable + { + #region Members + + /// + /// Represents the current icon data. + /// + private NotifyIconData iconData; + + /// + /// Receives messages from the taskbar icon. + /// + private readonly WindowMessageSink messageSink; + + /// + /// An action that is being invoked if the + /// fires. + /// + private Action singleClickTimerAction; + + /// + /// A timer that is used to differentiate between single + /// and double clicks. + /// + private readonly Timer singleClickTimer; + + /// + /// A timer that is used to close open balloon tooltips. + /// + private readonly Timer balloonCloseTimer; + + /// + /// Indicates whether the taskbar icon has been created or not. + /// + public bool IsTaskbarIconCreated { get; private set; } + + /// + /// Indicates whether custom tooltips are supported, which depends + /// on the OS. Windows Vista or higher is required in order to + /// support this feature. + /// + public bool SupportsCustomToolTips + { + get { return messageSink.Version == NotifyIconVersion.Vista; } + } + + + /// + /// Checks whether a non-tooltip popup is currently opened. + /// + private bool IsPopupOpen + { + get + { + var popup = TrayPopupResolved; + var menu = ContextMenu; + var balloon = CustomBalloon; + + return popup != null && popup.IsOpen || + menu != null && menu.IsOpen || + balloon != null && balloon.IsOpen; + } + } + + private double scalingFactor = double.NaN; + + #endregion + + #region Construction + + /// + /// Inits the taskbar icon and registers a message listener + /// in order to receive events from the taskbar area. + /// + public TaskbarIcon() + { + //using dummy sink in design mode + messageSink = Util.IsDesignMode + ? WindowMessageSink.CreateEmpty() + : new WindowMessageSink(NotifyIconVersion.Win95); + + //init icon data structure + iconData = NotifyIconData.CreateDefault(messageSink.MessageWindowHandle); + + //create the taskbar icon + CreateTaskbarIcon(); + + //register event listeners + messageSink.MouseEventReceived += OnMouseEvent; + messageSink.TaskbarCreated += OnTaskbarCreated; + messageSink.ChangeToolTipStateRequest += OnToolTipChange; + messageSink.BalloonToolTipChanged += OnBalloonToolTipChanged; + + //init single click / balloon timers + singleClickTimer = new Timer(DoSingleClickAction); + balloonCloseTimer = new Timer(CloseBalloonCallback); + + //register listener in order to get notified when the application closes + if (Application.Current != null) Application.Current.Exit += OnExit; + } + + #endregion + + #region Custom Balloons + + /// + /// Shows a custom control as a tooltip in the tray location. + /// + /// + /// An optional animation for the popup. + /// The time after which the popup is being closed. + /// Submit null in order to keep the balloon open inde + /// + /// If + /// is a null reference. + public void ShowCustomBalloon(UIElement balloon, PopupAnimation animation, int? timeout) + { + Dispatcher dispatcher = this.GetDispatcher(); + if (!dispatcher.CheckAccess()) + { + var action = new Action(() => ShowCustomBalloon(balloon, animation, timeout)); + dispatcher.Invoke(DispatcherPriority.Normal, action); + return; + } + + if (balloon == null) throw new ArgumentNullException("balloon"); + if (timeout.HasValue && timeout < 500) + { + string msg = "Invalid timeout of {0} milliseconds. Timeout must be at least 500 ms"; + msg = String.Format(msg, timeout); + throw new ArgumentOutOfRangeException("timeout", msg); + } + + EnsureNotDisposed(); + + //make sure we don't have an open balloon + lock (this) + { + CloseBalloon(); + } + + //create an invisible popup that hosts the UIElement + Popup popup = new Popup(); + popup.AllowsTransparency = true; + + //provide the popup with the taskbar icon's data context + UpdateDataContext(popup, null, DataContext); + + //don't animate by default - devs can use attached + //events or override + popup.PopupAnimation = animation; + + //in case the balloon is cleaned up through routed events, the + //control didn't remove the balloon from its parent popup when + //if was closed the last time - just make sure it doesn't have + //a parent that is a popup + var parent = LogicalTreeHelper.GetParent(balloon) as Popup; + if (parent != null) parent.Child = null; + + if (parent != null) + { + string msg = + "Cannot display control [{0}] in a new balloon popup - that control already has a parent. You may consider creating new balloons every time you want to show one."; + msg = String.Format(msg, balloon); + throw new InvalidOperationException(msg); + } + + popup.Child = balloon; + + //don't set the PlacementTarget as it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too... + //popup.PlacementTarget = this; + + popup.Placement = PlacementMode.AbsolutePoint; + popup.StaysOpen = true; + + Point position = TrayInfo.GetTrayLocation(); + position = GetDeviceCoordinates(position); + popup.HorizontalOffset = position.X - 1; + popup.VerticalOffset = position.Y - 1; + + //store reference + lock (this) + { + SetCustomBalloon(popup); + } + + //assign this instance as an attached property + SetParentTaskbarIcon(balloon, this); + + //fire attached event + RaiseBalloonShowingEvent(balloon, this); + + //display item + popup.IsOpen = true; + + if (timeout.HasValue) + { + //register timer to close the popup + balloonCloseTimer.Change(timeout.Value, Timeout.Infinite); + } + } + + + /// + /// Resets the closing timeout, which effectively + /// keeps a displayed balloon message open until + /// it is either closed programmatically through + /// or due to a new + /// message being displayed. + /// + public void ResetBalloonCloseTimer() + { + if (IsDisposed) return; + + lock (this) + { + //reset timer in any case + balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + } + + + /// + /// Closes the current , if the + /// property is set. + /// + public void CloseBalloon() + { + if (IsDisposed) return; + + Dispatcher dispatcher = this.GetDispatcher(); + if (!dispatcher.CheckAccess()) + { + Action action = CloseBalloon; + dispatcher.Invoke(DispatcherPriority.Normal, action); + return; + } + + lock (this) + { + //reset timer in any case + balloonCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); + + //reset old popup, if we still have one + Popup popup = CustomBalloon; + if (popup != null) + { + UIElement element = popup.Child; + + //announce closing + RoutedEventArgs eventArgs = RaiseBalloonClosingEvent(element, this); + if (!eventArgs.Handled) + { + //if the event was handled, clear the reference to the popup, + //but don't close it - the handling code has to manage this stuff now + + //close the popup + popup.IsOpen = false; + + //remove the reference of the popup to the balloon in case we want to reuse + //the balloon (then added to a new popup) + popup.Child = null; + + //reset attached property + if (element != null) SetParentTaskbarIcon(element, null); + } + + //remove custom balloon anyway + SetCustomBalloon(null); + } + } + } + + + /// + /// Timer-invoke event which closes the currently open balloon and + /// resets the dependency property. + /// + private void CloseBalloonCallback(object state) + { + if (IsDisposed) return; + + //switch to UI thread + Action action = CloseBalloon; + this.GetDispatcher().Invoke(action); + } + + #endregion + + #region Process Incoming Mouse Events + + /// + /// Processes mouse events, which are bubbled + /// through the class' routed events, trigger + /// certain actions (e.g. show a popup), or + /// both. + /// + /// Event flag. + private void OnMouseEvent(MouseEvent me) + { + if (IsDisposed) return; + + switch (me) + { + case MouseEvent.MouseMove: + RaiseTrayMouseMoveEvent(); + //immediately return - there's nothing left to evaluate + return; + case MouseEvent.IconRightMouseDown: + RaiseTrayRightMouseDownEvent(); + break; + case MouseEvent.IconLeftMouseDown: + RaiseTrayLeftMouseDownEvent(); + break; + case MouseEvent.IconRightMouseUp: + RaiseTrayRightMouseUpEvent(); + break; + case MouseEvent.IconLeftMouseUp: + RaiseTrayLeftMouseUpEvent(); + break; + case MouseEvent.IconMiddleMouseDown: + RaiseTrayMiddleMouseDownEvent(); + break; + case MouseEvent.IconMiddleMouseUp: + RaiseTrayMiddleMouseUpEvent(); + break; + case MouseEvent.IconDoubleClick: + //cancel single click timer + singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); + //bubble event + RaiseTrayMouseDoubleClickEvent(); + break; + case MouseEvent.BalloonToolTipClicked: + RaiseTrayBalloonTipClickedEvent(); + break; + default: + throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); + } + + + //get mouse coordinates + Point cursorPosition = new Point(); + 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; + + //show popup, if requested + if (me.IsMatch(PopupActivation)) + { + if (me == MouseEvent.IconLeftMouseUp) + { + //show popup once we are sure it's not a double click + singleClickTimerAction = () => + { + LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); + ShowTrayPopup(cursorPosition); + }; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + isLeftClickCommandInvoked = true; + } + else + { + //show popup immediately + ShowTrayPopup(cursorPosition); + } + } + + + //show context menu, if requested + if (me.IsMatch(MenuActivation)) + { + if (me == MouseEvent.IconLeftMouseUp) + { + //show context menu once we are sure it's not a double click + singleClickTimerAction = () => + { + LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); + ShowContextMenu(cursorPosition); + }; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + isLeftClickCommandInvoked = true; + } + else + { + //show context menu immediately + ShowContextMenu(cursorPosition); + } + } + + //make sure the left click command is invoked on mouse clicks + if (me == MouseEvent.IconLeftMouseUp && !isLeftClickCommandInvoked) + { + //show context menu once we are sure it's not a double click + singleClickTimerAction = + () => + { + LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); + }; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + } + } + + #endregion + + #region ToolTips + + /// + /// Displays a custom tooltip, if available. This method is only + /// invoked for Windows Vista and above. + /// + /// Whether to show or hide the tooltip. + private void OnToolTipChange(bool visible) + { + //if we don't have a tooltip, there's nothing to do here... + if (TrayToolTipResolved == null) return; + + if (visible) + { + if (IsPopupOpen) + { + //ignore if we are already displaying something down there + return; + } + + var args = RaisePreviewTrayToolTipOpenEvent(); + if (args.Handled) return; + + TrayToolTipResolved.IsOpen = true; + + //raise attached event first + if (TrayToolTip != null) RaiseToolTipOpenedEvent(TrayToolTip); + + //bubble routed event + RaiseTrayToolTipOpenEvent(); + } + else + { + var args = RaisePreviewTrayToolTipCloseEvent(); + if (args.Handled) return; + + //raise attached event first + if (TrayToolTip != null) RaiseToolTipCloseEvent(TrayToolTip); + + TrayToolTipResolved.IsOpen = false; + + //bubble event + RaiseTrayToolTipCloseEvent(); + } + } + + + /// + /// Creates a control that either + /// wraps the currently set + /// control or the string.
+ /// If itself is already + /// a instance, it will be used directly. + ///
+ /// We use a rather than + /// because there was no way to prevent a + /// popup from causing cyclic open/close commands if it was + /// placed under the mouse. ToolTip internally uses a Popup of + /// its own, but takes advance of Popup's internal + /// property which prevents this issue. + private void CreateCustomToolTip() + { + //check if the item itself is a tooltip + ToolTip tt = TrayToolTip as ToolTip; + + if (tt == null && TrayToolTip != null) + { + //create an invisible wrapper tooltip that hosts the UIElement + tt = new ToolTip(); + tt.Placement = PlacementMode.Mouse; + + //do *not* set the placement target, as it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through + //the ParentTaskbarIcon attached dependency property: + //tt.PlacementTarget = this; + + //make sure the tooltip is invisible + tt.HasDropShadow = false; + tt.BorderThickness = new Thickness(0); + tt.Background = System.Windows.Media.Brushes.Transparent; + + //setting the + tt.StaysOpen = true; + tt.Content = TrayToolTip; + } + else if (tt == null && !String.IsNullOrEmpty(ToolTipText)) + { + //create a simple tooltip for the ToolTipText string + tt = new ToolTip(); + tt.Content = ToolTipText; + } + + //the tooltip explicitly gets the DataContext of this instance. + //If there is no DataContext, the TaskbarIcon assigns itself + if (tt != null) + { + UpdateDataContext(tt, null, DataContext); + } + + //store a reference to the used tooltip + SetTrayToolTipResolved(tt); + } + + + /// + /// Sets tooltip settings for the class depending on defined + /// dependency properties and OS support. + /// + private void WriteToolTipSettings() + { + const IconDataMembers flags = IconDataMembers.Tip; + iconData.ToolTipText = ToolTipText; + + if (messageSink.Version == NotifyIconVersion.Vista) + { + //we need to set a tooltip text to get tooltip events from the + //taskbar icon + if (String.IsNullOrEmpty(iconData.ToolTipText) && TrayToolTipResolved != null) + { + //if we have not tooltip text but a custom tooltip, we + //need to set a dummy value (we're displaying the ToolTip control, not the string) + iconData.ToolTipText = "ToolTip"; + } + } + + //update the tooltip text + Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); + } + + #endregion + + #region Custom Popup + + /// + /// Creates a control that either + /// wraps the currently set + /// control or the string.
+ /// If itself is already + /// a instance, it will be used directly. + ///
+ /// We use a rather than + /// because there was no way to prevent a + /// popup from causing cyclic open/close commands if it was + /// placed under the mouse. ToolTip internally uses a Popup of + /// its own, but takes advance of Popup's internal + /// property which prevents this issue. + private void CreatePopup() + { + //check if the item itself is a popup + Popup popup = TrayPopup as Popup; + + if (popup == null && TrayPopup != null) + { + //create an invisible popup that hosts the UIElement + popup = new Popup(); + popup.AllowsTransparency = true; + + //don't animate by default - devs can use attached + //events or override + popup.PopupAnimation = PopupAnimation.None; + + //the CreateRootPopup method outputs binding errors in the debug window because + //it tries to bind to "Popup-specific" properties in case they are provided by the child. + //We don't need that so just assign the control as the child. + popup.Child = TrayPopup; + + //do *not* set the placement target, as it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through + //the ParentTaskbarIcon attached dependency property: + //popup.PlacementTarget = this; + + popup.Placement = PlacementMode.AbsolutePoint; + popup.StaysOpen = false; + } + + //the popup explicitly gets the DataContext of this instance. + //If there is no DataContext, the TaskbarIcon assigns itself + if (popup != null) + { + UpdateDataContext(popup, null, DataContext); + } + + //store a reference to the used tooltip + SetTrayPopupResolved(popup); + } + + + /// + /// Displays the control if + /// it was set. + /// + private void ShowTrayPopup(Point cursorPosition) + { + if (IsDisposed) return; + + //raise preview event no matter whether popup is currently set + //or not (enables client to set it on demand) + var args = RaisePreviewTrayPopupOpenEvent(); + if (args.Handled) return; + + if (TrayPopup != null) + { + //use absolute position, but place the popup centered above the icon + TrayPopupResolved.Placement = PlacementMode.AbsolutePoint; + TrayPopupResolved.HorizontalOffset = cursorPosition.X; + TrayPopupResolved.VerticalOffset = cursorPosition.Y; + + //open popup + TrayPopupResolved.IsOpen = true; + + IntPtr handle = IntPtr.Zero; + if (TrayPopupResolved.Child != null) + { + //try to get a handle on the popup itself (via its child) + HwndSource source = (HwndSource) PresentationSource.FromVisual(TrayPopupResolved.Child); + if (source != null) handle = source.Handle; + } + + //if we don't have a handle for the popup, fall back to the message sink + if (handle == IntPtr.Zero) handle = messageSink.MessageWindowHandle; + + //activate either popup or message sink to track deactivation. + //otherwise, the popup does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(handle); + + //raise attached event - item should never be null unless developers + //changed the CustomPopup directly... + if (TrayPopup != null) RaisePopupOpenedEvent(TrayPopup); + + //bubble routed event + RaiseTrayPopupOpenEvent(); + } + } + + #endregion + + #region Context Menu + + /// + /// Displays the if + /// it was set. + /// + private void ShowContextMenu(Point cursorPosition) + { + if (IsDisposed) return; + + //raise preview event no matter whether context menu is currently set + //or not (enables client to set it on demand) + var args = RaisePreviewTrayContextMenuOpenEvent(); + if (args.Handled) return; + + if (ContextMenu != null) + { + //use absolute positioning. We need to set the coordinates, or a delayed opening + //(e.g. when left-clicked) opens the context menu at the wrong place if the mouse + //is moved! + ContextMenu.Placement = PlacementMode.AbsolutePoint; + ContextMenu.HorizontalOffset = cursorPosition.X; + ContextMenu.VerticalOffset = cursorPosition.Y; + 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) + { + handle = source.Handle; + } + + //if we don't have a handle for the popup, fall back to the message sink + if (handle == IntPtr.Zero) handle = messageSink.MessageWindowHandle; + + //activate the context menu or the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else. With the message window + //fallback, the context menu can't receive keyboard events - should not happen though + WinApi.SetForegroundWindow(handle); + + //bubble event + RaiseTrayContextMenuOpenEvent(); + } + } + + #endregion + + #region Balloon Tips + + /// + /// Bubbles events if a balloon ToolTip was displayed + /// or removed. + /// + /// Whether the ToolTip was just displayed + /// or removed. + private void OnBalloonToolTipChanged(bool visible) + { + if (visible) + { + RaiseTrayBalloonTipShownEvent(); + } + else + { + RaiseTrayBalloonTipClosedEvent(); + } + } + + /// + /// Displays a balloon tip with the specified title, + /// text, and icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A symbol that indicates the severity. + public void ShowBalloonTip(string title, string message, BalloonIcon symbol) + { + lock (this) + { + ShowBalloonTip(title, message, symbol.GetBalloonFlag(), IntPtr.Zero); + } + } + + + /// + /// Displays a balloon tip with the specified title, + /// text, and a custom icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A custom icon. + /// If + /// is a null reference. + public void ShowBalloonTip(string title, string message, Icon customIcon) + { + if (customIcon == null) throw new ArgumentNullException("customIcon"); + + lock (this) + { + ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); + } + } + + + /// + /// Invokes in order to display + /// a given balloon ToolTip. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// Indicates what icon to use. + /// A handle to a custom icon, if any, or + /// . + private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) + { + EnsureNotDisposed(); + + iconData.BalloonText = message ?? String.Empty; + iconData.BalloonTitle = title ?? String.Empty; + + iconData.BalloonFlags = flags; + iconData.CustomBalloonIconHandle = balloonIconHandle; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info | IconDataMembers.Icon); + } + + + /// + /// Hides a balloon ToolTip, if any is displayed. + /// + public void HideBalloonTip() + { + EnsureNotDisposed(); + + //reset balloon by just setting the info to an empty string + iconData.BalloonText = iconData.BalloonTitle = String.Empty; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + } + + #endregion + + #region Single Click Timer event + + /// + /// Performs a delayed action if the user requested an action + /// based on a single click of the left mouse.
+ /// This method is invoked by the . + ///
+ private void DoSingleClickAction(object state) + { + if (IsDisposed) return; + + //run action + Action action = singleClickTimerAction; + if (action != null) + { + //cleanup action + singleClickTimerAction = null; + + //switch to UI thread + this.GetDispatcher().Invoke(action); + } + } + + #endregion + + #region Set Version (API) + + /// + /// Sets the version flag for the . + /// + private void SetVersion() + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Vista; + bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); + + if (!status) + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win2000; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win95; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + Debug.Fail("Could not set version"); + } + } + + #endregion + + #region Create / Remove Taskbar Icon + + /// + /// Recreates the taskbar icon if the whole taskbar was + /// recreated (e.g. because Explorer was shut down). + /// + private void OnTaskbarCreated() + { + IsTaskbarIconCreated = false; + CreateTaskbarIcon(); + } + + + /// + /// Creates the taskbar icon. This message is invoked during initialization, + /// if the taskbar is restarted, and whenever the icon is displayed. + /// + private void CreateTaskbarIcon() + { + lock (this) + { + if (!IsTaskbarIconCreated) + { + const IconDataMembers members = IconDataMembers.Message + | IconDataMembers.Icon + | IconDataMembers.Tip; + + //write initial configuration + var status = Util.WriteIconData(ref iconData, NotifyCommand.Add, members); + if (!status) + { + //couldn't create the icon - we can assume this is because explorer is not running (yet!) + //-> try a bit later again rather than throwing an exception. Typically, if the windows + // shell is being loaded later, this method is being reinvoked from OnTaskbarCreated + // (we could also retry after a delay, but that's currently YAGNI) + return; + } + + //set to most recent version + SetVersion(); + messageSink.Version = (NotifyIconVersion) iconData.VersionOrTimeout; + + IsTaskbarIconCreated = true; + } + } + } + + /// + /// Closes the taskbar icon if required. + /// + private void RemoveTaskbarIcon() + { + lock (this) + { + //make sure we didn't schedule a creation + + if (IsTaskbarIconCreated) + { + Util.WriteIconData(ref iconData, NotifyCommand.Delete, IconDataMembers.Message); + IsTaskbarIconCreated = false; + } + } + } + + #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 + + /// + /// Set to true as soon as Dispose has been invoked. + /// + public bool IsDisposed { get; private set; } + + + /// + /// Checks if the object has been disposed and + /// raises a in case + /// the flag is true. + /// + private void EnsureNotDisposed() + { + if (IsDisposed) throw new ObjectDisposedException(Name ?? GetType().FullName); + } + + + /// + /// Disposes the class if the application exits. + /// + private void OnExit(object sender, EventArgs e) + { + Dispose(); + } + + + /// + /// This destructor will run only if the + /// method does not get called. This gives this base class the + /// opportunity to finalize. + /// + /// Important: Do not provide destructors in types derived from + /// this class. + /// + /// + ~TaskbarIcon() + { + Dispose(false); + } + + + /// + /// Disposes the object. + /// + /// This method is not virtual by design. Derived classes + /// should override . + /// + public void Dispose() + { + Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + + /// + /// Closes the tray and releases all resources. + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// + /// If disposing equals false, the method + /// has been called by the runtime from inside the finalizer and you + /// should not reference other objects. Only unmanaged resources can + /// be disposed. + /// Check the property to determine whether + /// the method has already been called. + private void Dispose(bool disposing) + { + //don't do anything if the component is already disposed + if (IsDisposed || !disposing) return; + + lock (this) + { + IsDisposed = true; + + //deregister application event listener + if (Application.Current != null) + { + Application.Current.Exit -= OnExit; + } + + //stop timers + singleClickTimer.Dispose(); + balloonCloseTimer.Dispose(); + + //dispose message sink + messageSink.Dispose(); + + //remove icon + RemoveTaskbarIcon(); + } + } + + #endregion + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Util.cs b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Util.cs index 3d5327a..b7db32a 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Util.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/NotifyIconWpf/Util.cs @@ -1,309 +1,309 @@ -// hardcodet.net NotifyIcon for WPF -// Copyright (c) 2009 - 2013 Philipp Sumi -// Contact and Information: http://www.hardcodet.net -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the Code Project Open License (CPOL); -// either version 1.0 of the License, or (at your option) any later -// version. -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE - - -using System; -using System.ComponentModel; -using System.Drawing; -using System.Windows; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Resources; -using System.Windows.Threading; -using Hardcodet.Wpf.TaskbarNotification.Interop; - -namespace Hardcodet.Wpf.TaskbarNotification -{ - /// - /// Util and extension methods. - /// - internal static class Util - { - public static readonly object SyncRoot = new object(); - - #region IsDesignMode - - private static readonly bool isDesignMode; - - /// - /// Checks whether the application is currently in design mode. - /// - public static bool IsDesignMode - { - get { return isDesignMode; } - } - - #endregion - - #region construction - - static Util() - { - isDesignMode = - (bool) - DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, - typeof (FrameworkElement)) - .Metadata.DefaultValue; - } - - #endregion - - #region CreateHelperWindow - - /// - /// Creates an transparent window without dimension that - /// can be used to temporarily obtain focus and/or - /// be used as a window message sink. - /// - /// Empty window. - public static Window CreateHelperWindow() - { - return new Window - { - Width = 0, - Height = 0, - ShowInTaskbar = false, - WindowStyle = WindowStyle.None, - AllowsTransparency = true, - Opacity = 0 - }; - } - - #endregion - - #region WriteIconData - - /// - /// Updates the taskbar icons with data provided by a given - /// instance. - /// - /// Configuration settings for the NotifyIcon. - /// Operation on the icon (e.g. delete the icon). - /// True if the data was successfully written. - /// See Shell_NotifyIcon documentation on MSDN for details. - public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command) - { - return WriteIconData(ref data, command, data.ValidMembers); - } - - - /// - /// Updates the taskbar icons with data provided by a given - /// instance. - /// - /// Configuration settings for the NotifyIcon. - /// Operation on the icon (e.g. delete the icon). - /// Defines which members of the - /// structure are set. - /// True if the data was successfully written. - /// See Shell_NotifyIcon documentation on MSDN for details. - public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command, IconDataMembers flags) - { - //do nothing if in design mode - if (IsDesignMode) return true; - - data.ValidMembers = flags; - lock (SyncRoot) - { - return WinApi.Shell_NotifyIcon(command, ref data); - } - } - - #endregion - - #region GetBalloonFlag - - /// - /// Gets a enum value that - /// matches a given . - /// - public static BalloonFlags GetBalloonFlag(this BalloonIcon icon) - { - switch (icon) - { - case BalloonIcon.None: - return BalloonFlags.None; - case BalloonIcon.Info: - return BalloonFlags.Info; - case BalloonIcon.Warning: - return BalloonFlags.Warning; - case BalloonIcon.Error: - return BalloonFlags.Error; - default: - throw new ArgumentOutOfRangeException("icon"); - } - } - - #endregion - - #region ImageSource to Icon - - /// - /// Reads a given image resource into a WinForms icon. - /// - /// Image source pointing to - /// an icon file (*.ico). - /// An icon object that can be used with the - /// taskbar area. - public static Icon ToIcon(this ImageSource imageSource) - { - if (imageSource == null) return null; - - Uri uri = new Uri(imageSource.ToString()); - StreamResourceInfo streamInfo = Application.GetResourceStream(uri); - - if (streamInfo == null) - { - string msg = "The supplied image source '{0}' could not be resolved."; - msg = String.Format(msg, imageSource); - throw new ArgumentException(msg); - } - - return new Icon(streamInfo.Stream); - } - - #endregion - - #region evaluate listings - - /// - /// Checks a list of candidates for equality to a given - /// reference value. - /// - /// - /// The evaluated value. - /// A liste of possible values that are - /// regarded valid. - /// True if one of the submitted - /// matches the evaluated value. If the - /// parameter itself is null, too, the method returns false as well, - /// which allows to check with null values, too. - /// If - /// is a null reference. - public static bool Is(this T value, params T[] candidates) - { - if (candidates == null) return false; - - foreach (var t in candidates) - { - if (value.Equals(t)) return true; - } - - return false; - } - - #endregion - - #region match MouseEvent to PopupActivation - - /// - /// Checks if a given is a match for - /// an effectively pressed mouse button. - /// - public static bool IsMatch(this MouseEvent me, PopupActivationMode activationMode) - { - switch (activationMode) - { - case PopupActivationMode.LeftClick: - return me == MouseEvent.IconLeftMouseUp; - case PopupActivationMode.RightClick: - return me == MouseEvent.IconRightMouseUp; - case PopupActivationMode.LeftOrRightClick: - return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconRightMouseUp); - case PopupActivationMode.LeftOrDoubleClick: - return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconDoubleClick); - case PopupActivationMode.DoubleClick: - return me.Is(MouseEvent.IconDoubleClick); - case PopupActivationMode.MiddleClick: - return me == MouseEvent.IconMiddleMouseUp; - case PopupActivationMode.All: - //return true for everything except mouse movements - return me != MouseEvent.MouseMove; - default: - throw new ArgumentOutOfRangeException("activationMode"); - } - } - - #endregion - - #region execute command - - /// - /// Executes a given command if its method - /// indicates it can run. - /// - /// The command to be executed, or a null reference. - /// An optional parameter that is associated with - /// the command. - /// The target element on which to raise the command. - public static void ExecuteIfEnabled(this ICommand command, object commandParameter, IInputElement target) - { - if (command == null) return; - - RoutedCommand rc = command as RoutedCommand; - if (rc != null) - { - //routed commands work on a target - if (rc.CanExecute(commandParameter, target)) rc.Execute(commandParameter, target); - } - else if (command.CanExecute(commandParameter)) - { - command.Execute(commandParameter); - } - } - - #endregion - - /// - /// Returns a dispatcher for multi-threaded scenarios - /// - /// - internal static Dispatcher GetDispatcher(this DispatcherObject source) - { - //use the application's dispatcher by default - if (Application.Current != null) return Application.Current.Dispatcher; - - //fallback for WinForms environments - if (source.Dispatcher != null) return source.Dispatcher; - - //ultimatively use the thread's dispatcher - return Dispatcher.CurrentDispatcher; - } - - - /// - /// Checks whether the - /// is bound or not. - /// - /// The element to be checked. - /// True if the data context property is being managed by a - /// binding expression. - /// If - /// is a null reference. - public static bool IsDataContextDataBound(this FrameworkElement element) - { - if (element == null) throw new ArgumentNullException("element"); - return element.GetBindingExpression(FrameworkElement.DataContextProperty) != null; - } - } +// hardcodet.net NotifyIcon for WPF +// Copyright (c) 2009 - 2013 Philipp Sumi +// Contact and Information: http://www.hardcodet.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the Code Project Open License (CPOL); +// either version 1.0 of the License, or (at your option) any later +// version. +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE + + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Resources; +using System.Windows.Threading; +using Hardcodet.Wpf.TaskbarNotification.Interop; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Util and extension methods. + /// + internal static class Util + { + public static readonly object SyncRoot = new object(); + + #region IsDesignMode + + private static readonly bool isDesignMode; + + /// + /// Checks whether the application is currently in design mode. + /// + public static bool IsDesignMode + { + get { return isDesignMode; } + } + + #endregion + + #region construction + + static Util() + { + isDesignMode = + (bool) + DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, + typeof (FrameworkElement)) + .Metadata.DefaultValue; + } + + #endregion + + #region CreateHelperWindow + + /// + /// Creates an transparent window without dimension that + /// can be used to temporarily obtain focus and/or + /// be used as a window message sink. + /// + /// Empty window. + public static Window CreateHelperWindow() + { + return new Window + { + Width = 0, + Height = 0, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None, + AllowsTransparency = true, + Opacity = 0 + }; + } + + #endregion + + #region WriteIconData + + /// + /// Updates the taskbar icons with data provided by a given + /// instance. + /// + /// Configuration settings for the NotifyIcon. + /// Operation on the icon (e.g. delete the icon). + /// True if the data was successfully written. + /// See Shell_NotifyIcon documentation on MSDN for details. + public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command) + { + return WriteIconData(ref data, command, data.ValidMembers); + } + + + /// + /// Updates the taskbar icons with data provided by a given + /// instance. + /// + /// Configuration settings for the NotifyIcon. + /// Operation on the icon (e.g. delete the icon). + /// Defines which members of the + /// structure are set. + /// True if the data was successfully written. + /// See Shell_NotifyIcon documentation on MSDN for details. + public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command, IconDataMembers flags) + { + //do nothing if in design mode + if (IsDesignMode) return true; + + data.ValidMembers = flags; + lock (SyncRoot) + { + return WinApi.Shell_NotifyIcon(command, ref data); + } + } + + #endregion + + #region GetBalloonFlag + + /// + /// Gets a enum value that + /// matches a given . + /// + public static BalloonFlags GetBalloonFlag(this BalloonIcon icon) + { + switch (icon) + { + case BalloonIcon.None: + return BalloonFlags.None; + case BalloonIcon.Info: + return BalloonFlags.Info; + case BalloonIcon.Warning: + return BalloonFlags.Warning; + case BalloonIcon.Error: + return BalloonFlags.Error; + default: + throw new ArgumentOutOfRangeException("icon"); + } + } + + #endregion + + #region ImageSource to Icon + + /// + /// Reads a given image resource into a WinForms icon. + /// + /// Image source pointing to + /// an icon file (*.ico). + /// An icon object that can be used with the + /// taskbar area. + public static Icon ToIcon(this ImageSource imageSource) + { + if (imageSource == null) return null; + + Uri uri = new Uri(imageSource.ToString()); + StreamResourceInfo streamInfo = Application.GetResourceStream(uri); + + if (streamInfo == null) + { + string msg = "The supplied image source '{0}' could not be resolved."; + msg = String.Format(msg, imageSource); + throw new ArgumentException(msg); + } + + return new Icon(streamInfo.Stream); + } + + #endregion + + #region evaluate listings + + /// + /// Checks a list of candidates for equality to a given + /// reference value. + /// + /// + /// The evaluated value. + /// A liste of possible values that are + /// regarded valid. + /// True if one of the submitted + /// matches the evaluated value. If the + /// parameter itself is null, too, the method returns false as well, + /// which allows to check with null values, too. + /// If + /// is a null reference. + public static bool Is(this T value, params T[] candidates) + { + if (candidates == null) return false; + + foreach (var t in candidates) + { + if (value.Equals(t)) return true; + } + + return false; + } + + #endregion + + #region match MouseEvent to PopupActivation + + /// + /// Checks if a given is a match for + /// an effectively pressed mouse button. + /// + public static bool IsMatch(this MouseEvent me, PopupActivationMode activationMode) + { + switch (activationMode) + { + case PopupActivationMode.LeftClick: + return me == MouseEvent.IconLeftMouseUp; + case PopupActivationMode.RightClick: + return me == MouseEvent.IconRightMouseUp; + case PopupActivationMode.LeftOrRightClick: + return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconRightMouseUp); + case PopupActivationMode.LeftOrDoubleClick: + return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconDoubleClick); + case PopupActivationMode.DoubleClick: + return me.Is(MouseEvent.IconDoubleClick); + case PopupActivationMode.MiddleClick: + return me == MouseEvent.IconMiddleMouseUp; + case PopupActivationMode.All: + //return true for everything except mouse movements + return me != MouseEvent.MouseMove; + default: + throw new ArgumentOutOfRangeException("activationMode"); + } + } + + #endregion + + #region execute command + + /// + /// Executes a given command if its method + /// indicates it can run. + /// + /// The command to be executed, or a null reference. + /// An optional parameter that is associated with + /// the command. + /// The target element on which to raise the command. + public static void ExecuteIfEnabled(this ICommand command, object commandParameter, IInputElement target) + { + if (command == null) return; + + RoutedCommand rc = command as RoutedCommand; + if (rc != null) + { + //routed commands work on a target + if (rc.CanExecute(commandParameter, target)) rc.Execute(commandParameter, target); + } + else if (command.CanExecute(commandParameter)) + { + command.Execute(commandParameter); + } + } + + #endregion + + /// + /// Returns a dispatcher for multi-threaded scenarios + /// + /// + internal static Dispatcher GetDispatcher(this DispatcherObject source) + { + //use the application's dispatcher by default + if (Application.Current != null) return Application.Current.Dispatcher; + + //fallback for WinForms environments + if (source.Dispatcher != null) return source.Dispatcher; + + //ultimatively use the thread's dispatcher + return Dispatcher.CurrentDispatcher; + } + + + /// + /// Checks whether the + /// is bound or not. + /// + /// The element to be checked. + /// True if the data context property is being managed by a + /// binding expression. + /// If + /// is a null reference. + public static bool IsDataContextDataBound(this FrameworkElement element) + { + if (element == null) throw new ArgumentNullException("element"); + return element.GetBindingExpression(FrameworkElement.DataContextProperty) != null; + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml index 11ae36c..318ca54 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml @@ -1,14 +1,14 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml.cs index 6410157..51b78ac 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/App.xaml.cs @@ -1,17 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Windows; -using Hardcodet.Wpf.TaskbarNotification; - -namespace Samples -{ - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application - { - } +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; +using Hardcodet.Wpf.TaskbarNotification; + +namespace Samples +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CloseWindowCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CloseWindowCommand.cs index 2b47832..00930e8 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CloseWindowCommand.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CloseWindowCommand.cs @@ -1,24 +1,24 @@ -using System.Windows; -using System.Windows.Input; - -namespace Samples.Commands -{ - /// - /// Closes the current window. - /// - public class CloseWindowCommand : CommandBase - { - public override void Execute(object parameter) - { - GetTaskbarWindow(parameter).Close(); - CommandManager.InvalidateRequerySuggested(); - } - - - public override bool CanExecute(object parameter) - { - Window win = GetTaskbarWindow(parameter); - return win != null; - } - } +using System.Windows; +using System.Windows.Input; + +namespace Samples.Commands +{ + /// + /// Closes the current window. + /// + public class CloseWindowCommand : CommandBase + { + public override void Execute(object parameter) + { + GetTaskbarWindow(parameter).Close(); + CommandManager.InvalidateRequerySuggested(); + } + + + public override bool CanExecute(object parameter) + { + Window win = GetTaskbarWindow(parameter); + return win != null; + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CommandBase.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CommandBase.cs index ccfe761..ed0ae3b 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CommandBase.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/CommandBase.cs @@ -1,157 +1,157 @@ -using System; -using System.ComponentModel; -using System.Windows; -using System.Windows.Input; -using System.Windows.Markup; -using System.Windows.Media; -using Hardcodet.Wpf.TaskbarNotification; - -namespace Samples.Commands -{ - /// - /// Basic implementation of the - /// interface, which is also accessible as a markup - /// extension. - /// - public abstract class CommandBase : MarkupExtension, ICommand - where T : class, ICommand, new() - { - /// - /// A singleton instance. - /// - private static T command; - - /// - /// Gets a shared command instance. - /// - public override object ProvideValue(IServiceProvider serviceProvider) - { - if (command == null) command = new T(); - return command; - } - - /// - /// Fires when changes occur that affect whether - /// or not the command should execute. - /// - public event EventHandler CanExecuteChanged - { - add { CommandManager.RequerySuggested += value; } - remove { CommandManager.RequerySuggested -= value; } - } - - /// - /// Defines the method to be called when the command is invoked. - /// - /// Data used by the command. - /// If the command does not require data to be passed, - /// this object can be set to null. - /// - public abstract void Execute(object parameter); - - /// - /// Defines the method that determines whether the command - /// can execute in its current state. - /// - /// - /// This default implementation always returns true. - /// - /// Data used by the command. - /// If the command does not require data to be passed, - /// this object can be set to null. - /// - public virtual bool CanExecute(object parameter) - { - return IsDesignMode ? false : true; - } - - - public static bool IsDesignMode - { - get - { - return (bool) - DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, - typeof (FrameworkElement)) - .Metadata.DefaultValue; - } - } - - - /// - /// Resolves the window that owns the TaskbarIcon class. - /// - /// - /// - protected Window GetTaskbarWindow(object commandParameter) - { - if (IsDesignMode) return null; - - //get the showcase window off the taskbaricon - var tb = commandParameter as TaskbarIcon; - return tb == null ? null : TryFindParent(tb); - } - - #region TryFindParent helper - - /// - /// Finds a parent of a given item on the visual tree. - /// - /// The type of the queried item. - /// A direct or indirect child of the - /// queried item. - /// The first parent item that matches the submitted - /// type parameter. If not matching item can be found, a null - /// reference is being returned. - public static T TryFindParent(DependencyObject child) - where T : DependencyObject - { - //get parent item - DependencyObject parentObject = GetParentObject(child); - - //we've reached the end of the tree - if (parentObject == null) return null; - - //check if the parent matches the type we're looking for - T parent = parentObject as T; - if (parent != null) - { - return parent; - } - else - { - //use recursion to proceed with next level - return TryFindParent(parentObject); - } - } - - /// - /// This method is an alternative to WPF's - /// method, which also - /// supports content elements. Keep in mind that for content element, - /// this method falls back to the logical tree of the element! - /// - /// The item to be processed. - /// The submitted item's parent, if available. Otherwise - /// null. - public static DependencyObject GetParentObject(DependencyObject child) - { - if (child == null) return null; - ContentElement contentElement = child as ContentElement; - - if (contentElement != null) - { - DependencyObject parent = ContentOperations.GetParent(contentElement); - if (parent != null) return parent; - - FrameworkContentElement fce = contentElement as FrameworkContentElement; - return fce != null ? fce.Parent : null; - } - - //if it's not a ContentElement, rely on VisualTreeHelper - return VisualTreeHelper.GetParent(child); - } - - #endregion - } +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Input; +using System.Windows.Markup; +using System.Windows.Media; +using Hardcodet.Wpf.TaskbarNotification; + +namespace Samples.Commands +{ + /// + /// Basic implementation of the + /// interface, which is also accessible as a markup + /// extension. + /// + public abstract class CommandBase : MarkupExtension, ICommand + where T : class, ICommand, new() + { + /// + /// A singleton instance. + /// + private static T command; + + /// + /// Gets a shared command instance. + /// + public override object ProvideValue(IServiceProvider serviceProvider) + { + if (command == null) command = new T(); + return command; + } + + /// + /// Fires when changes occur that affect whether + /// or not the command should execute. + /// + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + /// + /// Defines the method to be called when the command is invoked. + /// + /// Data used by the command. + /// If the command does not require data to be passed, + /// this object can be set to null. + /// + public abstract void Execute(object parameter); + + /// + /// Defines the method that determines whether the command + /// can execute in its current state. + /// + /// + /// This default implementation always returns true. + /// + /// Data used by the command. + /// If the command does not require data to be passed, + /// this object can be set to null. + /// + public virtual bool CanExecute(object parameter) + { + return IsDesignMode ? false : true; + } + + + public static bool IsDesignMode + { + get + { + return (bool) + DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, + typeof (FrameworkElement)) + .Metadata.DefaultValue; + } + } + + + /// + /// Resolves the window that owns the TaskbarIcon class. + /// + /// + /// + protected Window GetTaskbarWindow(object commandParameter) + { + if (IsDesignMode) return null; + + //get the showcase window off the taskbaricon + var tb = commandParameter as TaskbarIcon; + return tb == null ? null : TryFindParent(tb); + } + + #region TryFindParent helper + + /// + /// Finds a parent of a given item on the visual tree. + /// + /// The type of the queried item. + /// A direct or indirect child of the + /// queried item. + /// The first parent item that matches the submitted + /// type parameter. If not matching item can be found, a null + /// reference is being returned. + public static T TryFindParent(DependencyObject child) + where T : DependencyObject + { + //get parent item + DependencyObject parentObject = GetParentObject(child); + + //we've reached the end of the tree + if (parentObject == null) return null; + + //check if the parent matches the type we're looking for + T parent = parentObject as T; + if (parent != null) + { + return parent; + } + else + { + //use recursion to proceed with next level + return TryFindParent(parentObject); + } + } + + /// + /// This method is an alternative to WPF's + /// method, which also + /// supports content elements. Keep in mind that for content element, + /// this method falls back to the logical tree of the element! + /// + /// The item to be processed. + /// The submitted item's parent, if available. Otherwise + /// null. + public static DependencyObject GetParentObject(DependencyObject child) + { + if (child == null) return null; + ContentElement contentElement = child as ContentElement; + + if (contentElement != null) + { + DependencyObject parent = ContentOperations.GetParent(contentElement); + if (parent != null) return parent; + + FrameworkContentElement fce = contentElement as FrameworkContentElement; + return fce != null ? fce.Parent : null; + } + + //if it's not a ContentElement, rely on VisualTreeHelper + return VisualTreeHelper.GetParent(child); + } + + #endregion + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/HideSampleWindowCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/HideSampleWindowCommand.cs index ca18829..0e5be4e 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/HideSampleWindowCommand.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/HideSampleWindowCommand.cs @@ -1,24 +1,24 @@ -using System.Windows; -using System.Windows.Input; - -namespace Samples.Commands -{ - /// - /// Hides the main window. - /// - public class HideSampleWindowCommand : CommandBase - { - public override void Execute(object parameter) - { - GetTaskbarWindow(parameter).Hide(); - CommandManager.InvalidateRequerySuggested(); - } - - - public override bool CanExecute(object parameter) - { - Window win = GetTaskbarWindow(parameter); - return win != null && win.IsVisible; - } - } +using System.Windows; +using System.Windows.Input; + +namespace Samples.Commands +{ + /// + /// Hides the main window. + /// + public class HideSampleWindowCommand : CommandBase + { + public override void Execute(object parameter) + { + GetTaskbarWindow(parameter).Hide(); + CommandManager.InvalidateRequerySuggested(); + } + + + public override bool CanExecute(object parameter) + { + Window win = GetTaskbarWindow(parameter); + return win != null && win.IsVisible; + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/ShowSampleWindowCommand.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/ShowSampleWindowCommand.cs index b35d8a3..f954968 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/ShowSampleWindowCommand.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Commands/ShowSampleWindowCommand.cs @@ -1,24 +1,24 @@ -using System.Windows; -using System.Windows.Input; - -namespace Samples.Commands -{ - /// - /// Shows the main window. - /// - public class ShowSampleWindowCommand : CommandBase - { - public override void Execute(object parameter) - { - GetTaskbarWindow(parameter).Show(); - CommandManager.InvalidateRequerySuggested(); - } - - - public override bool CanExecute(object parameter) - { - Window win = GetTaskbarWindow(parameter); - return win != null && !win.IsVisible; - } - } +using System.Windows; +using System.Windows.Input; + +namespace Samples.Commands +{ + /// + /// Shows the main window. + /// + public class ShowSampleWindowCommand : CommandBase + { + public override void Execute(object parameter) + { + GetTaskbarWindow(parameter).Show(); + CommandManager.InvalidateRequerySuggested(); + } + + + public override bool CanExecute(object parameter) + { + Window win = GetTaskbarWindow(parameter); + return win != null && !win.IsVisible; + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Main.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Main.xaml index 1421c8f..95473cc 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Main.xaml +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Main.xaml @@ -1,242 +1,242 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyPopup.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyPopup.xaml.cs index 636c716..d29c5de 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyPopup.xaml.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyPopup.xaml.cs @@ -1,46 +1,46 @@ -using System.Windows; -using System.Windows.Controls; - -namespace Samples -{ - /// - /// Interaction logic for FancyPopup.xaml - /// - public partial class FancyPopup : UserControl - { - #region ClickCount dependency property - - /// - /// The number of clicks on the popup button. - /// - public static readonly DependencyProperty ClickCountProperty = - DependencyProperty.Register("ClickCount", - typeof (int), - typeof (FancyPopup), - new FrameworkPropertyMetadata(0)); - - /// - /// A property wrapper for the - /// dependency property:
- /// The number of clicks on the popup button. - ///
- public int ClickCount - { - get { return (int) GetValue(ClickCountProperty); } - set { SetValue(ClickCountProperty, value); } - } - - #endregion - - public FancyPopup() - { - InitializeComponent(); - } - - private void OnButtonClick(object sender, RoutedEventArgs e) - { - //just increment a counter - will be displayed on screen - ClickCount++; - } - } +using System.Windows; +using System.Windows.Controls; + +namespace Samples +{ + /// + /// Interaction logic for FancyPopup.xaml + /// + public partial class FancyPopup : UserControl + { + #region ClickCount dependency property + + /// + /// The number of clicks on the popup button. + /// + public static readonly DependencyProperty ClickCountProperty = + DependencyProperty.Register("ClickCount", + typeof (int), + typeof (FancyPopup), + new FrameworkPropertyMetadata(0)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The number of clicks on the popup button. + ///
+ public int ClickCount + { + get { return (int) GetValue(ClickCountProperty); } + set { SetValue(ClickCountProperty, value); } + } + + #endregion + + public FancyPopup() + { + InitializeComponent(); + } + + private void OnButtonClick(object sender, RoutedEventArgs e) + { + //just increment a counter - will be displayed on screen + ClickCount++; + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml index 0e42d0b..9392e7b 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml @@ -1,114 +1,114 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml.cs index 5609d6a..f8757e2 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/FancyToolTip.xaml.cs @@ -1,51 +1,51 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using Hardcodet.Wpf.TaskbarNotification; - -namespace Samples -{ - /// - /// Interaction logic for FancyToolTip.xaml - /// - public partial class FancyToolTip - { - #region InfoText dependency property - - /// - /// The tooltip details. - /// - public static readonly DependencyProperty InfoTextProperty = - DependencyProperty.Register("InfoText", - typeof (string), - typeof (FancyToolTip), - new FrameworkPropertyMetadata("")); - - /// - /// A property wrapper for the - /// dependency property:
- /// The tooltip details. - ///
- public string InfoText - { - get { return (string) GetValue(InfoTextProperty); } - set { SetValue(InfoTextProperty, value); } - } - - #endregion - - public FancyToolTip() - { - this.InitializeComponent(); - } - } +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Hardcodet.Wpf.TaskbarNotification; + +namespace Samples +{ + /// + /// Interaction logic for FancyToolTip.xaml + /// + public partial class FancyToolTip + { + #region InfoText dependency property + + /// + /// The tooltip details. + /// + public static readonly DependencyProperty InfoTextProperty = + DependencyProperty.Register("InfoText", + typeof (string), + typeof (FancyToolTip), + new FrameworkPropertyMetadata("")); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The tooltip details. + ///
+ public string InfoText + { + get { return (string) GetValue(InfoTextProperty); } + set { SetValue(InfoTextProperty, value); } + } + + #endregion + + public FancyToolTip() + { + this.InitializeComponent(); + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/NotifyIconResources.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/NotifyIconResources.xaml index 2f0a526..46bf6be 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/NotifyIconResources.xaml +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/NotifyIconResources.xaml @@ -1,81 +1,81 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/ShowcaseWindow.xaml b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/ShowcaseWindow.xaml index c4fa802..5e19f35 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/ShowcaseWindow.xaml +++ b/Hardcodet.NotifyIcon.Wpf/Source/Sample Project/Showcase/ShowcaseWindow.xaml @@ -1,640 +1,640 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WPF NotifyIcon - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/FancyPopup.xaml.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/FancyPopup.xaml.cs index 6799925..2a8fcaa 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/FancyPopup.xaml.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/FancyPopup.xaml.cs @@ -1,45 +1,45 @@ -using System.Windows; - -namespace Samples -{ - /// - /// Interaction logic for FancyPopup.xaml - /// - public partial class FancyPopup - { - #region ClickCount dependency property - - /// - /// The number of clicks on the popup button. - /// - public static readonly DependencyProperty ClickCountProperty = - DependencyProperty.Register("ClickCount", - typeof (int), - typeof (FancyPopup), - new FrameworkPropertyMetadata(0)); - - /// - /// A property wrapper for the - /// dependency property:
- /// The number of clicks on the popup button. - ///
- public int ClickCount - { - get { return (int) GetValue(ClickCountProperty); } - set { SetValue(ClickCountProperty, value); } - } - - #endregion - - public FancyPopup() - { - InitializeComponent(); - } - - private void OnButtonClick(object sender, RoutedEventArgs e) - { - //just increment a counter - will be displayed on screen - ClickCount++; - } - } +using System.Windows; + +namespace Samples +{ + /// + /// Interaction logic for FancyPopup.xaml + /// + public partial class FancyPopup + { + #region ClickCount dependency property + + /// + /// The number of clicks on the popup button. + /// + public static readonly DependencyProperty ClickCountProperty = + DependencyProperty.Register("ClickCount", + typeof (int), + typeof (FancyPopup), + new FrameworkPropertyMetadata(0)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// The number of clicks on the popup button. + ///
+ public int ClickCount + { + get { return (int) GetValue(ClickCountProperty); } + set { SetValue(ClickCountProperty, value); } + } + + #endregion + + public FancyPopup() + { + InitializeComponent(); + } + + private void OnButtonClick(object sender, RoutedEventArgs e) + { + //just increment a counter - will be displayed on screen + ClickCount++; + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.Designer.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.Designer.cs index eaab61d..8eed7cb 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.Designer.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.Designer.cs @@ -1,62 +1,62 @@ -namespace WindowsFormsSample -{ - partial class Form1 - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.label1 = new System.Windows.Forms.Label(); - this.SuspendLayout(); - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(32, 25); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(408, 13); - this.label1.TabIndex = 0; - this.label1.Text = "Click on the red LED icon in the taskbar to display an interactive WPF Popup cont" + - "rol."; - // - // Form1 - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(488, 264); - this.Controls.Add(this.label1); - this.Name = "Form1"; - this.Text = "Form1"; - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Label label1; - } -} - +namespace WindowsFormsSample +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(32, 25); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(408, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Click on the red LED icon in the taskbar to display an interactive WPF Popup cont" + + "rol."; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(488, 264); + this.Controls.Add(this.label1); + this.Name = "Form1"; + this.Text = "Form1"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + } +} + diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.cs index 52da957..9e32170 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.cs @@ -1,39 +1,39 @@ -using System; -using System.Windows; -using System.Windows.Forms; -using Hardcodet.Wpf.TaskbarNotification; -using Samples; -using WindowsFormsSample.Properties; - -namespace WindowsFormsSample -{ - public partial class Form1 : Form - { - private TaskbarIcon notifyIcon; - - public Form1() - { - InitializeComponent(); - } - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - notifyIcon = new TaskbarIcon(); - notifyIcon.Icon = Resources.Led; - notifyIcon.ToolTipText = "Left-click to open popup"; - notifyIcon.Visibility = Visibility.Visible; - - notifyIcon.TrayPopup = new FancyPopup(); - } - - protected override void OnClosed(EventArgs e) - { - base.OnClosed(e); - - //the notify icon only closes automatically on WPF applications - //-> dispose the notify icon manually - notifyIcon.Dispose(); - } - } +using System; +using System.Windows; +using System.Windows.Forms; +using Hardcodet.Wpf.TaskbarNotification; +using Samples; +using WindowsFormsSample.Properties; + +namespace WindowsFormsSample +{ + public partial class Form1 : Form + { + private TaskbarIcon notifyIcon; + + public Form1() + { + InitializeComponent(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + notifyIcon = new TaskbarIcon(); + notifyIcon.Icon = Resources.Led; + notifyIcon.ToolTipText = "Left-click to open popup"; + notifyIcon.Visibility = Visibility.Visible; + + notifyIcon.TrayPopup = new FancyPopup(); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + + //the notify icon only closes automatically on WPF applications + //-> dispose the notify icon manually + notifyIcon.Dispose(); + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.resx b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.resx index ff31a6d..19dc0dd 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.resx +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Form1.resx @@ -1,120 +1,120 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Program.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Program.cs index b155e0a..026aaa3 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Program.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Program.cs @@ -1,20 +1,20 @@ -using System; -using System.Windows.Forms; -using Samples; - -namespace WindowsFormsSample -{ - internal static class Program - { - /// - /// The main entry point for the application. - /// - [STAThread] - private static void Main() - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new Form1()); - } - } +using System; +using System.Windows.Forms; +using Samples; + +namespace WindowsFormsSample +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + private static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } } \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/AssemblyInfo.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/AssemblyInfo.cs index 3ba7613..b6341d8 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/AssemblyInfo.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/AssemblyInfo.cs @@ -1,40 +1,40 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyTitle("WindowsFormsSample")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("WindowsFormsSample")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("072bbfa0-9b8b-48df-bf88-3e4806b3e3e8")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] - -[assembly: AssemblyVersion("1.0.0.0")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("WindowsFormsSample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("WindowsFormsSample")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("072bbfa0-9b8b-48df-bf88-3e4806b3e3e8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] + +[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.Designer.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.Designer.cs index 4dc5ac7..ad67f05 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.Designer.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.Designer.cs @@ -1,73 +1,73 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18408 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace WindowsFormsSample.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowsFormsSample.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). - /// - internal static System.Drawing.Icon Led { - get { - object obj = ResourceManager.GetObject("Led", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18408 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsFormsSample.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowsFormsSample.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon Led { + get { + object obj = ResourceManager.GetObject("Led", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.resx b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.resx index 4c8eec3..d657fca 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.resx +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Resources.resx @@ -1,124 +1,124 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\icon\led.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\icon\led.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.Designer.cs b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.Designer.cs index 2a00ed0..b781a34 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.Designer.cs +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18408 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace WindowsFormsSample.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18408 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsFormsSample.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.settings b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.settings index eeb7df0..e04fc63 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.settings +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/Properties/Settings.settings @@ -1,8 +1,8 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/WindowsFormsSample.csproj b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/WindowsFormsSample.csproj index 6ee8d4e..d7823aa 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/WindowsFormsSample.csproj +++ b/Hardcodet.NotifyIcon.Wpf/Source/WindowsFormsSample/WindowsFormsSample.csproj @@ -1,162 +1,162 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8} - WinExe - Properties - WindowsFormsSample - WindowsFormsSample - v4.0 - 512 - WindowsFormsSample.Program - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - Client - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - - - - - 3.5 - - - - 3.5 - - - 3.5 - - - - - - - - 3.0 - - - 3.0 - - - - - FancyPopup.xaml - - - Form - - - Form1.cs - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - MSBuild:Compile - Designer - MSBuild:Compile - Designer - - - - - - - - {7AC63864-7638-41C4-969C-D3197EF2BED9} - NotifyIconWpf - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {F6DC0A6D-D1CE-4AD2-92ED-08FFF0AD4FA8} + WinExe + Properties + WindowsFormsSample + WindowsFormsSample + v4.0 + 512 + WindowsFormsSample.Program + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + 3.0 + + + 3.0 + + + + + FancyPopup.xaml + + + Form + + + Form1.cs + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + MSBuild:Compile + Designer + MSBuild:Compile + Designer + + + + + + + + {7AC63864-7638-41C4-969C-D3197EF2BED9} + NotifyIconWpf + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + \ No newline at end of file From 653e313640b58f1f85aa73b020c405288d601a99 Mon Sep 17 00:00:00 2001 From: Philipp Sumi Date: Mon, 25 Nov 2013 17:46:54 +0100 Subject: [PATCH 73/73] Fixed type in change log. --- Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt b/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt index d38878c..4b306f5 100644 --- a/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt +++ b/Hardcodet.NotifyIcon.Wpf/Source/Changelog.txt @@ -7,7 +7,7 @@ Contact and Information: http://www.hardcodet.net ***** FIX Support for x64 applications targeting .NET 4 x64 or higher (big thanks to Mark Junker for submitting a patch!) -CHG Component does no longer throw an exception is no Explorer shell is present, +CHG Component does no longer throw an exception if no Explorer shell is present, but waits for it to be created. CHG NotifyIcon is not only removed on user-initiated disposal, but also garbage collection. CHG The attached ParentTaskbarIconProperty is now derived, so data binding to the attached DP