diff --git a/Source/NotifyIconWpf/BalloonIcon.cs b/Source/NotifyIconWpf/BalloonIcon.cs index 610ff57..8f1cb70 100644 --- a/Source/NotifyIconWpf/BalloonIcon.cs +++ b/Source/NotifyIconWpf/BalloonIcon.cs @@ -24,26 +24,29 @@ 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 - } + /// + /// 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/Source/NotifyIconWpf/Interop/BalloonFlags.cs b/Source/NotifyIconWpf/Interop/BalloonFlags.cs index a59a90d..0243003 100644 --- a/Source/NotifyIconWpf/Interop/BalloonFlags.cs +++ b/Source/NotifyIconWpf/Interop/BalloonFlags.cs @@ -1,55 +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. + /// Flags that define the icon that is shown on a balloon + /// tooltip. /// - 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 - - } + 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 index be284cb..071d087 100644 --- a/Source/NotifyIconWpf/Interop/IconDataMembers.cs +++ b/Source/NotifyIconWpf/Interop/IconDataMembers.cs @@ -2,66 +2,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. + /// 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. /// - 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, + [Flags] + public enum IconDataMembers + { + /// + /// The message ID is set. + /// + Message = 0x01, - /// - /// 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 - } + /// + /// 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/Source/NotifyIconWpf/Interop/IconState.cs b/Source/NotifyIconWpf/Interop/IconState.cs index 44a9e7f..627eaee 100644 --- a/Source/NotifyIconWpf/Interop/IconState.cs +++ b/Source/NotifyIconWpf/Interop/IconState.cs @@ -1,23 +1,24 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop { - /// - /// The state of the icon - can be set to - /// hide the icon. - /// - public enum IconState - { /// - /// The icon is visible. + /// The state of the icon - can be set to + /// hide the icon. /// - Visible = 0x00, - /// - /// Hide the icon. - /// - Hidden = 0x01, + public enum IconState + { + /// + /// The icon is visible. + /// + Visible = 0x00, - /// - /// The icon is shared - currently not supported, thus commented out. - /// - //Shared = 0x02 - } + /// + /// 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 index 6f57593..3aec31c 100644 --- a/Source/NotifyIconWpf/Interop/MouseEvent.cs +++ b/Source/NotifyIconWpf/Interop/MouseEvent.cs @@ -1,48 +1,54 @@ - - -namespace Hardcodet.Wpf.TaskbarNotification.Interop +namespace Hardcodet.Wpf.TaskbarNotification.Interop { - /// - /// Event flags for clicked events. - /// - public enum MouseEvent - { /// - /// The mouse was moved withing the - /// taskbar icon's area. + /// Event flags for clicked events. /// - 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 - } -} + 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/Source/NotifyIconWpf/Interop/NotifyCommand.cs b/Source/NotifyIconWpf/Interop/NotifyCommand.cs index de0a639..3e72985 100644 --- a/Source/NotifyIconWpf/Interop/NotifyCommand.cs +++ b/Source/NotifyIconWpf/Interop/NotifyCommand.cs @@ -1,39 +1,41 @@ - - namespace Hardcodet.Wpf.TaskbarNotification.Interop { - /// - /// Main operations performed on the - /// function. - /// - public enum NotifyCommand - { /// - /// The taskbar icon is being created. + /// Main operations performed on the + /// function. /// - 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 - } + 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 index b169b8e..59f8f13 100644 --- a/Source/NotifyIconWpf/Interop/NotifyIconData.cs +++ b/Source/NotifyIconWpf/Interop/NotifyIconData.cs @@ -3,163 +3,163 @@ 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. + /// 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. /// - 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) + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct NotifyIconData { - var data = new NotifyIconData(); + /// + /// Size of this structure, in bytes. + /// + public uint cbSize; - 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 + /// + /// 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; - //set to fixed timeout - data.VersionOrTimeout = 10; - } + /// + /// 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; - data.WindowHandle = handle; - data.TaskbarIconId = 0x0; - data.CallbackMessageId = WindowMessageSink.CallbackMessageId; - data.VersionOrTimeout = (uint) NotifyIconVersion.Win95; + /// + /// 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; - data.IconHandle = IntPtr.Zero; + /// + /// Application-defined message identifier. The system uses this identifier to send + /// notifications to the window identified in hWnd. + /// + public uint CallbackMessageId; - //hide initially - data.IconState = IconState.Hidden; - data.StateMask = IconState.Hidden; + /// + /// A handle to the icon that should be displayed. Just + /// Icon.Handle. + /// + public IntPtr IconHandle; - //set flags - data.ValidMembers = IconDataMembers.Message - | IconDataMembers.Icon - | IconDataMembers.Tip; + /// + /// 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; - //reset strings - data.ToolTipText = data.BalloonText = data.BalloonTitle = String.Empty; - return data; + /// + /// 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/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs b/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs index 5947c59..277f278 100644 --- a/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs +++ b/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs @@ -1,25 +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. + /// The notify icon version that is used. The higher + /// the version, the more capabilities are available. /// - 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 - } + 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/Source/NotifyIconWpf/Interop/Point.cs b/Source/NotifyIconWpf/Interop/Point.cs index 219adcb..2c1f5bb 100644 --- a/Source/NotifyIconWpf/Interop/Point.cs +++ b/Source/NotifyIconWpf/Interop/Point.cs @@ -2,13 +2,13 @@ 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; - } + /// + /// 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/TrayInfo.cs b/Source/NotifyIconWpf/Interop/TrayInfo.cs index 34ea681..9ddc83f 100644 --- a/Source/NotifyIconWpf/Interop/TrayInfo.cs +++ b/Source/NotifyIconWpf/Interop/TrayInfo.cs @@ -7,165 +7,158 @@ 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. + /// Resolves the current tray position. /// - /// Tray coordinates. - public static Point GetTrayLocation() + public static class TrayInfo { - 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) + /// + /// Gets the position of the system tray. + /// + /// Tray coordinates. + public static Point GetTrayLocation() { - Marshal.FreeHGlobal(rawRect); - return new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); + 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; } } - 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) + public Rectangle WorkArea { - throw new Exception("Failed to communicate with the given AppBar"); + 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; } - } - 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/WinApi.cs b/Source/NotifyIconWpf/Interop/WinApi.cs index 38e7d6a..c9f8ffd 100644 --- a/Source/NotifyIconWpf/Interop/WinApi.cs +++ b/Source/NotifyIconWpf/Interop/WinApi.cs @@ -3,85 +3,85 @@ using System.Runtime.InteropServices; namespace Hardcodet.Wpf.TaskbarNotification.Interop { - /// - /// Win32 API imports. - /// - internal static class WinApi - { /// - /// Creates, updates or deletes the taskbar icon. + /// Win32 API imports. /// - [DllImport("shell32.Dll", CharSet = CharSet.Unicode)] - public static extern bool Shell_NotifyIcon(NotifyCommand cmd, [In]ref NotifyIconData data); + 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); + /// + /// 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); + /// + /// Processes a default windows procedure. + /// + [DllImport("USER32.DLL")] + public static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wparam, IntPtr lparam); - /// - /// Registers a listener for a window message. - /// - /// - /// - [DllImport("User32.Dll", EntryPoint = "RegisterWindowMessageW")] - public static extern uint RegisterWindowMessage([MarshalAs(UnmanagedType.LPWStr)] string lpString); + /// + /// Registers the helper window class. + /// + [DllImport("USER32.DLL", EntryPoint = "RegisterClassW", SetLastError = true)] + public static extern short RegisterClass(ref WindowClass lpWndClass); - /// - /// 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); + /// + /// 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); + /// + /// 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 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 GetCursorPos(ref Point lpPoint); - } + /// + /// 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/WindowClass.cs b/Source/NotifyIconWpf/Interop/WindowClass.cs index bfc42f7..c3bc6f4 100644 --- a/Source/NotifyIconWpf/Interop/WindowClass.cs +++ b/Source/NotifyIconWpf/Interop/WindowClass.cs @@ -3,29 +3,29 @@ 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); + /// + /// 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 - { - 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; - } + /// + /// 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.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs index 4aabdef..2c36c5f 100644 --- a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -22,7 +22,6 @@ // THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE - using System; using System.ComponentModel; using System.Diagnostics; @@ -30,345 +29,340 @@ 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. + /// Receives messages from the taskbar icon through + /// window messages of an underlying helper window. /// - 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. - /// - /// 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) + public class WindowMessageSink : IDisposable { - Version = version; - CreateMessageWindow(); - } + #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. + /// + /// 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() - { - } + 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 - }; - } + /// + /// 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 + #endregion + #region CreateMessageWindow - #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; - /// - /// 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; - //register window message handler - messageHandler = OnWindowMessageReceived; + // Create a simple window class which is reference through + //the messageHandler delegate + WindowClass wc; - // 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; - 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); - // 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"); - // 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); - // 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 (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"); + 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 + /// 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 } - - #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 - /// 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/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj index 19ac8f1..aabbfd7 100644 --- a/Source/NotifyIconWpf/NotifyIconWpf.csproj +++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,11 +10,11 @@ Properties Hardcodet.Wpf.TaskbarNotification Hardcodet.Wpf.TaskbarNotification - v3.5 + v4.0 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 - Client + Client true @@ -25,6 +25,7 @@ prompt 4 AnyCPU + AllRules.ruleset pdbonly @@ -34,6 +35,7 @@ prompt 4 bin\Release\Hardcodet.Wpf.TaskbarNotification.xml + AllRules.ruleset @@ -41,6 +43,7 @@ 3.5 + diff --git a/Source/NotifyIconWpf/PopupActivationMode.cs b/Source/NotifyIconWpf/PopupActivationMode.cs index 2020929..0197347 100644 --- a/Source/NotifyIconWpf/PopupActivationMode.cs +++ b/Source/NotifyIconWpf/PopupActivationMode.cs @@ -24,46 +24,52 @@ 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. + /// Defines flags that define when a popup + /// is being displyed. /// - 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 - } -} + 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/Source/NotifyIconWpf/Properties/AssemblyInfo.cs b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs index 9dcc92f..88453b3 100644 --- a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs +++ b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs @@ -6,21 +6,25 @@ 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: AssemblyDescription("NotifyIcon implementation for the WPF platform.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("hardcodet.net")] [assembly: AssemblyProduct("NotifyIcon WPF")] -[assembly: AssemblyCopyright("Copyright © Philipp Sumi 2009")] +[assembly: AssemblyCopyright("Copyright © Philipp Sumi 2046")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] //provides simplified declaration + +[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 @@ -35,12 +39,12 @@ using System.Windows.Markup; [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) + //(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) -)] + //(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: @@ -53,5 +57,6 @@ 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.4.0")] -[assembly: AssemblyFileVersion("1.0.4.0")] + +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] \ No newline at end of file diff --git a/Source/NotifyIconWpf/Properties/Resources.Designer.cs b/Source/NotifyIconWpf/Properties/Resources.Designer.cs index d78e26d..24d3386 100644 --- a/Source/NotifyIconWpf/Properties/Resources.Designer.cs +++ b/Source/NotifyIconWpf/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.3053 +// 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 Hardcodet.Wpf.TaskbarNotification.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 Hardcodet.Wpf.TaskbarNotification.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// internal static System.Drawing.Icon DefaultTrayIcon { get { object obj = ResourceManager.GetObject("DefaultTrayIcon", resourceCulture); diff --git a/Source/NotifyIconWpf/RoutedEventHelper.cs b/Source/NotifyIconWpf/RoutedEventHelper.cs index 127ec77..89bc299 100644 --- a/Source/NotifyIconWpf/RoutedEventHelper.cs +++ b/Source/NotifyIconWpf/RoutedEventHelper.cs @@ -3,79 +3,79 @@ 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. + /// Helper class used by routed events of the + /// class. /// - /// UIElement or ContentElement on which to raise the event - /// RoutedEventArgs to use when raising the event - internal static void RaiseEvent(DependencyObject target, RoutedEventArgs args) + internal static class RoutedEventHelper { - if (target is UIElement) - { - (target as UIElement).RaiseEvent(args); - } - else if (target is ContentElement) - { - (target as ContentElement).RaiseEvent(args); - } - } + #region RoutedEvent Helper Methods - /// - /// 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) + /// + /// 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) { - ce.AddHandler(routedEvent, handler); + if (target is UIElement) + { + (target as UIElement).RaiseEvent(args); + } + else if (target is ContentElement) + { + (target as ContentElement).RaiseEvent(args); + } } - } - } - /// - /// 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) + /// + /// 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) { - ce.RemoveHandler(routedEvent, 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); + } + } } - } - } - #endregion - } -} + /// + /// 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/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 27a03bf..f7c0a16 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -705,7 +705,7 @@ namespace Hardcodet.Wpf.TaskbarNotification IntPtr handle = IntPtr.Zero; //try to get a handle on the context itself - HwndSource source = (HwndSource)PresentationSource.FromVisual(ContextMenu); + HwndSource source = (HwndSource) PresentationSource.FromVisual(ContextMenu); if (source != null) { handle = source.Handle; diff --git a/Source/NotifyIconWpf/Util.cs b/Source/NotifyIconWpf/Util.cs index 75b46b0..6334250 100644 --- a/Source/NotifyIconWpf/Util.cs +++ b/Source/NotifyIconWpf/Util.cs @@ -34,275 +34,276 @@ 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. + /// Util and extension methods. /// - public static bool IsDesignMode + internal static class Util { - get { return isDesignMode; } + 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; + } } - - #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/Source/Sample Project/App.xaml.cs b/Source/Sample Project/App.xaml.cs index 0764b0a..6410157 100644 --- a/Source/Sample Project/App.xaml.cs +++ b/Source/Sample Project/App.xaml.cs @@ -8,11 +8,10 @@ using Hardcodet.Wpf.TaskbarNotification; namespace Samples { - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application - { - - } -} + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} \ No newline at end of file diff --git a/Source/Sample Project/Commands/CommandBase.cs b/Source/Sample Project/Commands/CommandBase.cs index e120a47..ccfe761 100644 --- a/Source/Sample Project/Commands/CommandBase.cs +++ b/Source/Sample Project/Commands/CommandBase.cs @@ -8,151 +8,150 @@ 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. + /// Basic implementation of the + /// interface, which is also accessible as a markup + /// extension. /// - private static T command; - - /// - /// Gets a shared command instance. - /// - public override object ProvideValue(IServiceProvider serviceProvider) + public abstract class CommandBase : MarkupExtension, ICommand + where T : class, ICommand, new() { - if (command == null) command = new T(); - return command; + /// + /// 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 } - - /// - /// 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/Source/Sample Project/Commands/HideSampleWindowCommand.cs b/Source/Sample Project/Commands/HideSampleWindowCommand.cs index d27cbcd..ca18829 100644 --- a/Source/Sample Project/Commands/HideSampleWindowCommand.cs +++ b/Source/Sample Project/Commands/HideSampleWindowCommand.cs @@ -3,25 +3,22 @@ using System.Windows.Input; namespace Samples.Commands { - /// - /// Hides the main window. - /// - public class HideSampleWindowCommand : CommandBase - { - - public override void Execute(object parameter) + /// + /// Hides the main window. + /// + public class HideSampleWindowCommand : CommandBase { - GetTaskbarWindow(parameter).Hide(); - CommandManager.InvalidateRequerySuggested(); + 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; + } } - - - public override bool CanExecute(object parameter) - { - Window win = GetTaskbarWindow(parameter); - return win != null && win.IsVisible; - } - - - } -} +} \ No newline at end of file diff --git a/Source/Sample Project/Commands/ShowSampleWindowCommand.cs b/Source/Sample Project/Commands/ShowSampleWindowCommand.cs index 63a256a..b35d8a3 100644 --- a/Source/Sample Project/Commands/ShowSampleWindowCommand.cs +++ b/Source/Sample Project/Commands/ShowSampleWindowCommand.cs @@ -3,22 +3,22 @@ using System.Windows.Input; namespace Samples.Commands { - /// - /// Shows the main window. - /// - public class ShowSampleWindowCommand : CommandBase - { - public override void Execute(object parameter) + /// + /// Shows the main window. + /// + public class ShowSampleWindowCommand : CommandBase { - GetTaskbarWindow(parameter).Show(); - CommandManager.InvalidateRequerySuggested(); - } + 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; + public override bool CanExecute(object parameter) + { + Window win = GetTaskbarWindow(parameter); + return win != null && !win.IsVisible; + } } - } } \ No newline at end of file diff --git a/Source/Sample Project/Main.xaml b/Source/Sample Project/Main.xaml index 0d17808..969eac6 100644 --- a/Source/Sample Project/Main.xaml +++ b/Source/Sample Project/Main.xaml @@ -1,210 +1,227 @@  - - - - - - - + x:Class="Samples.Main" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + Title="NotifyIcon Samples" + Height="563" + Width="703" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + mc:Ignorable="d"> + + + + + + + - - - - - - - + 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