commit 94085b72938cf4cdcc32d2e267c1b169feb247ee Author: Philipp Sumi Date: Mon Mar 30 22:01:35 2009 +0000 WPF NotifyIcon -------------- Initial import git-svn-id: https://svn.evolvesoftware.ch/repos/evolve.net/WPF/NotifyIcon@52 9f600761-6f11-4665-b6dc-0185e9171623 diff --git a/Source/NotifyIconWpf.sln b/Source/NotifyIconWpf.sln new file mode 100644 index 0000000..f4acf09 --- /dev/null +++ b/Source/NotifyIconWpf.sln @@ -0,0 +1,38 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotifyIconWpf", "NotifyIconWpf\NotifyIconWpf.csproj", "{7AC63864-7638-41C4-969C-D3197EF2BED9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApplication2", "ConsoleApplication2\ConsoleApplication2.csproj", "{A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApplication1", "ConsoleApplication1\ConsoleApplication1.csproj", "{10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample Project", "Sample Project\Sample Project.csproj", "{71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.Build.0 = Release|Any CPU + {A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A92D287A-6DD2-4D75-9CE5-64BFB990E2D8}.Release|Any CPU.Build.0 = Release|Any CPU + {10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10BB9EF0-20F9-460E-96A3-284FF0D1C2E6}.Release|Any CPU.Build.0 = Release|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Source/NotifyIconWpf.sln.cache b/Source/NotifyIconWpf.sln.cache new file mode 100644 index 0000000..e57874d --- /dev/null +++ b/Source/NotifyIconWpf.sln.cache @@ -0,0 +1,236 @@ + + + <_SolutionProjectConfiguration>Debug|Any CPU + <_SolutionProjectToolsVersion>3.5 + <_SolutionProjectCacheVersion>3.5 + + + <_SolutionProjectProjects Include="ConsoleApplication1\ConsoleApplication1.csproj" /> + <_SolutionProjectProjects Include="ConsoleApplication2\ConsoleApplication2.csproj" /> + <_SolutionProjectProjects Include="NotifyIconWpf\NotifyIconWpf.csproj" /> + <_SolutionProjectProjects Include="Sample Project\Sample Project.csproj" /> + + + + Debug + AnyCPU + + + Debug + AnyCPU + + + Debug + AnyCPU + + + Debug + AnyCPU + + + + + Release + AnyCPU + + + Release + AnyCPU + + + Release + AnyCPU + + + Release + AnyCPU + + + + + + Debug + + + Any CPU + + + $(Configuration) + + + D:\Philipp\Repositories\evolve.net\WPF\NotifyIcon\Source\ + .sln + NotifyIconWpf.sln + NotifyIconWpf + D:\Philipp\Repositories\evolve.net\WPF\NotifyIcon\Source\NotifyIconWpf.sln + + + v2.0 + v3.5 + + + + + Debug|AnyCPU + Debug|AnyCPU + Debug|AnyCPU + Debug|AnyCPU + + + + + + + Release|AnyCPU + Release|AnyCPU + Release|AnyCPU + Release|AnyCPU + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/NotifyIconWpf/BalloonIcon.cs b/Source/NotifyIconWpf/BalloonIcon.cs new file mode 100644 index 0000000..018aae9 --- /dev/null +++ b/Source/NotifyIconWpf/BalloonIcon.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Supported icons for the tray's ballon messages. + /// + public enum BalloonIcon + { + /// + /// The balloon message is displayed without an icon. + /// + None, + /// + /// An information is displayed. + /// + Info, + /// + /// A warning is displayed. + /// + Warning, + /// + /// An error is displayed. + /// + Error + } +} diff --git a/Source/NotifyIconWpf/DefaultTrayIcon.ico b/Source/NotifyIconWpf/DefaultTrayIcon.ico new file mode 100644 index 0000000..e3ff3c4 Binary files /dev/null and b/Source/NotifyIconWpf/DefaultTrayIcon.ico differ diff --git a/Source/NotifyIconWpf/Interop/BalloonFlags.cs b/Source/NotifyIconWpf/Interop/BalloonFlags.cs new file mode 100644 index 0000000..a59a90d --- /dev/null +++ b/Source/NotifyIconWpf/Interop/BalloonFlags.cs @@ -0,0 +1,55 @@ +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Flags that define the icon that is shown on a balloon + /// tooltip. + /// + public enum BalloonFlags + { + /// + /// No icon is displayed. + /// + None = 0x00, + /// + /// An information icon is displayed. + /// + Info = 0x01, + /// + /// A warning icon is displayed. + /// + Warning = 0x02, + /// + /// An error icon is displayed. + /// + Error = 0x03, + /// + /// Windows XP Service Pack 2 (SP2) and later. + /// Use a custom icon as the title icon. + /// + User = 0x04, + /// + /// Windows XP (Shell32.dll version 6.0) and later. + /// Do not play the associated sound. Applies only to balloon ToolTips. + /// + NoSound = 0x10, + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The large version + /// of the icon should be used as the balloon icon. This corresponds to the + /// icon with dimensions SM_CXICON x SM_CYICON. If this flag is not set, + /// the icon with dimensions XM_CXSMICON x SM_CYSMICON is used.
+ /// - This flag can be used with all stock icons.
+ /// - Applications that use older customized icons (NIIF_USER with hIcon) must + /// provide a new SM_CXICON x SM_CYICON version in the tray icon (hIcon). These + /// icons are scaled down when they are displayed in the System Tray or + /// System Control Area (SCA).
+ /// - New customized icons (NIIF_USER with hBalloonIcon) must supply an + /// SM_CXICON x SM_CYICON version in the supplied icon (hBalloonIcon). + ///
+ LargeIcon = 0x20, + /// + /// Windows 7 and later. + /// + RespectQuietTime = 0x80 + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/IconDataMembers.cs b/Source/NotifyIconWpf/Interop/IconDataMembers.cs new file mode 100644 index 0000000..d3dd8db --- /dev/null +++ b/Source/NotifyIconWpf/Interop/IconDataMembers.cs @@ -0,0 +1,67 @@ +using System; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Indicates which members of a structure + /// were set, and thus contain valid data or provide additional information + /// to the ToolTip as to how it should display. + /// + [Flags] + public enum IconDataMembers + { + /// + /// The message ID is set. + /// + Message = 0x01, + /// + /// The notification icon is set. + /// + Icon = 0x02, + /// + /// The tooltip is set. + /// + Tip = 0x04, + /// + /// State information () is set. This + /// applies to both and + /// . + /// + State = 0x08, + /// + /// The ballon ToolTip is set. Accordingly, the following + /// members are set: , + /// , , + /// and . + /// + Info = 0x10, + + /// + /// Internal identifier is set. Reserved, thus commented out. + /// + //Guid = 0x20, + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. If the ToolTip + /// cannot be displayed immediately, discard it.
+ /// Use this flag for ToolTips that represent real-time information which + /// would be meaningless or misleading if displayed at a later time. + /// For example, a message that states "Your telephone is ringing."
+ /// This modifies and must be combined with the flag. + ///
+ Realtime = 0x40, + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. + /// Use the standard ToolTip. Normally, when uVersion is set + /// to NOTIFYICON_VERSION_4, the standard ToolTip is replaced + /// by the application-drawn pop-up user interface (UI). + /// If the application wants to show the standard tooltip + /// in that case, regardless of whether the on-hover UI is showing, + /// it can specify NIF_SHOWTIP to indicate the standard tooltip + /// should still be shown.
+ /// Note that the NIF_SHOWTIP flag is effective until the next call + /// to Shell_NotifyIcon. + ///
+ UseLegacyToolTips = 0x80 + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/IconState.cs b/Source/NotifyIconWpf/Interop/IconState.cs new file mode 100644 index 0000000..44a9e7f --- /dev/null +++ b/Source/NotifyIconWpf/Interop/IconState.cs @@ -0,0 +1,23 @@ +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// The state of the icon - can be set to + /// hide the icon. + /// + public enum IconState + { + /// + /// The icon is visible. + /// + Visible = 0x00, + /// + /// Hide the icon. + /// + Hidden = 0x01, + + /// + /// The icon is shared - currently not supported, thus commented out. + /// + //Shared = 0x02 + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/MouseEvent.cs b/Source/NotifyIconWpf/Interop/MouseEvent.cs new file mode 100644 index 0000000..c304289 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/MouseEvent.cs @@ -0,0 +1,46 @@ +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Event flags for clicked events. + /// + public enum MouseEvent + { + /// + /// The mouse was moved withing the + /// taskbar icon's area. + /// + MouseMove, + /// + /// The right mouse button was clicked. + /// + IconRightMouseDown, + /// + /// The left mouse button was clicked. + /// + IconLeftMouseDown, + /// + /// The right mouse button was released. + /// + IconRightMouseUp, + /// + /// The left mouse button was released. + /// + IconLeftMouseUp, + /// + /// The middle mouse button was clicked. + /// + IconMiddleMouseDown, + /// + /// The middle mouse button was released. + /// + IconMiddleMouseUp, + /// + /// The taskbar icon was double clicked. + /// + IconDoubleClick, + /// + /// The balloon tip was clicked. + /// + BalloonToolTipClicked + } +} diff --git a/Source/NotifyIconWpf/Interop/NotifyCommand.cs b/Source/NotifyIconWpf/Interop/NotifyCommand.cs new file mode 100644 index 0000000..7c3abde --- /dev/null +++ b/Source/NotifyIconWpf/Interop/NotifyCommand.cs @@ -0,0 +1,39 @@ +using System; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Main operations performed on the + /// function. + /// + public enum NotifyCommand + { + /// + /// The taskbar icon is being created. + /// + Add = 0x00, + /// + /// The settings of the taskbar icon are being updated. + /// + Modify = 0x01, + /// + /// The taskbar icon is deleted. + /// + Delete = 0x02, + /// + /// Focus is returned to the taskbar icon. Currently not in use. + /// + SetFocus = 0x03, + /// + /// Shell32.dll version 5.0 and later only. Instructs the taskbar + /// to behave according to the version number specified in the + /// uVersion member of the structure pointed to by lpdata. + /// This message allows you to specify whether you want the version + /// 5.0 behavior found on Microsoft Windows 2000 systems, or the + /// behavior found on earlier Shell versions. The default value for + /// uVersion is zero, indicating that the original Windows 95 notify + /// icon behavior should be used. + /// + SetVersion = 0x04 + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/NotifyIconData.cs b/Source/NotifyIconWpf/Interop/NotifyIconData.cs new file mode 100644 index 0000000..9f6f396 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/NotifyIconData.cs @@ -0,0 +1,153 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// A struct that is submitted in order to configure + /// the taskbar icon. Provides various members that + /// can be configured partially, according to the + /// values of the + /// that were defined. + /// + [StructLayout(LayoutKind.Sequential)] + public struct NotifyIconData + { + /// + /// Size of this structure, in bytes. + /// + public uint cbSize; + + /// + /// Handle to the window that receives notification messages associated with an icon in the + /// taskbar status area. The Shell uses hWnd and uID to identify which icon to operate on + /// when Shell_NotifyIcon is invoked. + /// + public IntPtr WindowHandle; + + /// + /// Application-defined identifier of the taskbar icon. The Shell uses hWnd and uID to identify + /// which icon to operate on when Shell_NotifyIcon is invoked. You can have multiple icons + /// associated with a single hWnd by assigning each a different uID. This feature, however + /// is currently not used. + /// + public uint TaskbarIconId; + + /// + /// Flags that indicate which of the other members contain valid data. This member can be + /// a combination of the NIF_XXX constants. + /// + public IconDataMembers ValidMembers; + + /// + /// Application-defined message identifier. The system uses this identifier to send + /// notifications to the window identified in hWnd. + /// + public uint CallbackMessageId; + + /// + /// A handle to the icon that should be displayed. Just + /// . + /// + public IntPtr IconHandle; + + /// + /// String with the text for a standard ToolTip. It can have a maximum of 64 characters including + /// the terminating NULL. For Version 5.0 and later, szTip can have a maximum of + /// 128 characters, including the terminating NULL. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string ToolTipText; + + + /// + /// State of the icon. Remember to also set the . + /// + public IconState IconState; + + /// + /// A value that specifies which bits of the state member are retrieved or modified. + /// For example, setting this member to + /// causes only the item's hidden + /// state to be retrieved. + /// + public IconState StateMask; + + /// + /// String with the text for a balloon ToolTip. It can have a maximum of 255 characters. + /// To remove the ToolTip, set the NIF_INFO flag in uFlags and set szInfo to an empty string. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string BalloonText; + + /// + /// Mainly used to set the version when is invoked + /// with . However, for legacy operations, + /// the same member is also used to set timouts for balloon ToolTips. + /// + public uint VersionOrTimeout; + + /// + /// String containing a title for a balloon ToolTip. This title appears in boldface + /// above the text. It can have a maximum of 63 characters. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string BalloonTitle; + + /// + /// Adds an icon to a balloon ToolTip, which is placed to the left of the title. If the + /// member is zero-length, the icon is not shown. + /// + public BalloonFlags BalloonFlags; + + /// + /// Windows XP (Shell32.dll version 6.0) and later.
+ /// - Windows 7 and later: A registered GUID that identifies the icon. + /// This value overrides uID and is the recommended method of identifying the icon.
+ /// - Windows XP through Windows Vista: Reserved. + ///
+ public Guid TaskbarIconGuid; + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The handle of a customized + /// balloon icon provided by the application that should be used independently + /// of the tray icon. If this member is non-NULL and the + /// flag is set, this icon is used as the balloon icon.
+ /// If this member is NULL, the legacy behavior is carried out. + ///
+ public IntPtr CustomBalloonIconHandle; + + + /// + /// Creates a default data structure that provides + /// a hidden taskbar icon without the icon being set. + /// + /// + /// + public static NotifyIconData CreateDefault(IntPtr handle) + { + var data = new NotifyIconData(); + + data.cbSize = (uint) Marshal.SizeOf(data); + + data.WindowHandle = handle; + data.TaskbarIconId = 0x0; + data.CallbackMessageId = WindowMessageSink.CallbackMessageId; + data.VersionOrTimeout = (uint) NotifyIconVersion.Win95; + + data.IconHandle = IntPtr.Zero; + + //hide initially + data.IconState = IconState.Hidden; + data.StateMask = IconState.Hidden; + + //set flags + data.ValidMembers = IconDataMembers.Message + | IconDataMembers.Icon + | IconDataMembers.Tip; + + //reset strings + data.ToolTipText = data.BalloonText = data.BalloonTitle = String.Empty; + + return data; + } + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs b/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs new file mode 100644 index 0000000..8be1618 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/NotifyIconVersion.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// The notify icon version that is used. The higher + /// the version, the more capabilities are available. + /// + public enum NotifyIconVersion + { + /// + /// Default behavior (legacy Win95). + /// + Win95 = 0x0, + /// + /// Behavior representing Win2000 an higher. + /// + Win2000 = 0x3, + /// + /// Extended tooltip support, which is available + /// for Vista and later. + /// + Vista = 0x4 + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/TrayLocator.cs b/Source/NotifyIconWpf/Interop/TrayLocator.cs new file mode 100644 index 0000000..de524a8 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/TrayLocator.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + public struct Rect + { + public int left; + public int top; + public int right; + public int bottom; + public override string ToString() + { + return "(" + left + ", " + top + ") --> (" + right + ", " + bottom + ")"; + } + } + + public struct TaskbarInfo + { + public int cbSize; + public IntPtr WindowHandle; + public int uCallbackMessage; + public TaskbarPosition Position; + public Rect Rectangle; + public IntPtr lParam; + } + + + + public enum TaskbarPosition + { + Left = 0, + Top, + Right, + Bottom + } + + + + + /// + /// Locates the position of the tray area. + /// + public class TrayLocator + { + public enum ABMsg + { + ABM_NEW = 0, + ABM_REMOVE = 1, + ABM_QUERYPOS = 2, + ABM_SETPOS = 3, + ABM_GETSTATE = 4, + ABM_GETTASKBARPOS = 5, + ABM_ACTIVATE = 6, + ABM_GETAUTOHIDEBAR = 7, + ABM_SETAUTOHIDEBAR = 8, + ABM_WINDOWPOSCHANGED = 9, + ABM_SETSTATE = 10 + } + + public enum ABNotify + { + ABN_STATECHANGE = 0, + ABN_POSCHANGED, + ABN_FULLSCREENAPP, + ABN_WINDOWARRANGE + } + + [DllImport("shell32.dll", EntryPoint = "SHAppBarMessage", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern int SHAppBarMessage(int dwMessage, ref TaskbarInfo pData); + + + /// + /// Determines the current location of the taskbar. + /// + /// + public static TaskbarInfo GetTaskbarInformation() + { + TaskbarInfo tbInfo = new TaskbarInfo(); + tbInfo.cbSize = Marshal.SizeOf(tbInfo); + + //retrieve the bounding rectangle of the Windows taskbar. + SHAppBarMessage((int)ABMsg.ABM_GETTASKBARPOS, ref tbInfo); + + return tbInfo; + } + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WinApi.cs b/Source/NotifyIconWpf/Interop/WinApi.cs new file mode 100644 index 0000000..7df8f20 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/WinApi.cs @@ -0,0 +1,80 @@ +using System; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Win32 API imports. + /// + internal static class WinApi + { + /// + /// Creates, updates or deletes the taskbar icon. + /// + [DllImport("shell32.Dll")] + public static extern bool Shell_NotifyIcon(NotifyCommand cmd, [In]ref NotifyIconData data); + + + /// + /// Creates the helper window that receives messages from the taskar icon. + /// + [DllImport("USER32.DLL", EntryPoint = "CreateWindowExW", SetLastError = true)] + public static extern IntPtr CreateWindowEx(int dwExStyle, [MarshalAs(UnmanagedType.LPWStr)] string lpClassName, + [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, int dwStyle, int x, int y, + int nWidth, int nHeight, uint hWndParent, int hMenu, int hInstance, + int lpParam); + + + /// + /// Processes a default windows procedure. + /// + [DllImport("USER32.DLL")] + public static extern long DefWindowProc(IntPtr hWnd, uint msg, uint wparam, uint lparam); + + /// + /// Registers the helper window class. + /// + [DllImport("USER32.DLL", EntryPoint = "RegisterClassW", SetLastError = true)] + public static extern short RegisterClass(ref WindowClass lpWndClass); + + /// + /// Registers a listener for a window message. + /// + /// + /// + [DllImport("User32.Dll", EntryPoint = "RegisterWindowMessageW")] + public static extern uint RegisterWindowMessage([MarshalAs(UnmanagedType.LPWStr)] string lpString); + + /// + /// Used to destroy the hidden helper window that receives messages from the + /// taskbar icon. + /// + /// + /// + [DllImport("USER32.DLL", SetLastError = true)] + public static extern bool DestroyWindow(IntPtr hWnd); + + + /// + /// Gives focus to a given window. + /// + /// + /// + [DllImport("USER32.DLL")] + public static extern bool SetForegroundWindow(IntPtr hWnd); + + + /// + /// Gets the maximum number of milliseconds that can elapse between a + /// first click and a second click for the OS to consider the + /// mouse action a double-click. + /// + /// The maximum amount of time, in milliseconds, that can + /// elapse between a first click and a second click for the OS to + /// consider the mouse action a double-click. + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + public static extern int GetDoubleClickTime(); + + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowClass.cs b/Source/NotifyIconWpf/Interop/WindowClass.cs new file mode 100644 index 0000000..e4f625a --- /dev/null +++ b/Source/NotifyIconWpf/Interop/WindowClass.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.InteropServices; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Callback delegate which is used by the Windows API to + /// submit window messages. + /// + public delegate long WindowProcedureHandler(IntPtr hwnd, uint uMsg, uint wparam, uint lparam); + + + /// + /// Win API WNDCLASS struct - represents a single window. + /// Used to receive window messages. + /// + [StructLayout(LayoutKind.Sequential)] + public struct WindowClass + { + public uint style; + public WindowProcedureHandler lpfnWndProc; + public int cbClsExtra; + public int cbWndExtra; + public IntPtr hInstance; + public IntPtr hIcon; + public IntPtr hCursor; + public IntPtr hbrBackground; + [MarshalAs(UnmanagedType.LPWStr)] public string lpszMenuName; + [MarshalAs(UnmanagedType.LPWStr)] public string lpszClassName; + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs new file mode 100644 index 0000000..5a4d4e9 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.Handle.cs @@ -0,0 +1,102 @@ +using System; +using System.ComponentModel; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Provides low level code that is used to receive + /// window messages without having a window that + /// prevents a WPF application from shutting down + /// properly. + /// + public partial class WindowMessageSink + { + /// + /// Window class ID. + /// + private string WindowId; + + /// + /// Handle for the message window. + /// + /// The ID of the message that is being received if the + /// taskbar is (re)started. + /// + private uint taskbarRestartMessageId; + + /// + /// A delegate that processes messages of the hidden + /// native window that receives window messages. Storing + /// this reference makes sure we don't loose our reference + /// to the message window. + /// + private WindowProcedureHandler messageHandler; + + /// + /// Creates the helper message window that is used + /// to receive messages from the taskbar icon. + /// + private void CreateMessageWindow() + { + WindowId = "WPFTaskbarIcon_" + Guid.NewGuid().ToString(); + + //register window message handler + messageHandler = OnWindowMessageReceived; + + // Create a simple window class which is reference through + //the messageHandler delegate + WindowClass wc; + + wc.style = 0; + wc.lpfnWndProc = messageHandler; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = IntPtr.Zero; + wc.hIcon = IntPtr.Zero; + wc.hCursor = IntPtr.Zero; + wc.hbrBackground = IntPtr.Zero; + wc.lpszMenuName = ""; + wc.lpszClassName = WindowId; + + // Register the window class + WinApi.RegisterClass(ref wc); + + // Get the message used to indicate the taskbar has been restarted + // This is used to re-add icons when the taskbar restarts + taskbarRestartMessageId = WinApi.RegisterWindowMessage("TaskbarCreated"); + + // Create the message window + MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, 0, 0, 0, 0); + + if (MessageWindowHandle == IntPtr.Zero) + { + throw new Win32Exception(); + } + } + + + + /// + /// Callback method that receives messages from the taskbar area. + /// + private long OnWindowMessageReceived(IntPtr hwnd, uint messageId, uint wparam, uint lparam) + { + if (messageId == taskbarRestartMessageId) + { + //recreate the icon if the taskbar was restarted + //TODO refresh icon + } + + ProcessWindowMessage(messageId, wparam, lparam); + + //handle mouse clicks... + + // Pass the message to the default window procedure + return WinApi.DefWindowProc(hwnd, messageId, wparam, lparam); + } + + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/Interop/WindowMessageSink.cs b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs new file mode 100644 index 0000000..29e2542 --- /dev/null +++ b/Source/NotifyIconWpf/Interop/WindowMessageSink.cs @@ -0,0 +1,255 @@ +using System; +using System.Diagnostics; + +namespace Hardcodet.Wpf.TaskbarNotification.Interop +{ + /// + /// Receives messages from the taskbar icon through + /// window messages of an underlying helper window. + /// + public partial class WindowMessageSink : IDisposable + { + + #region members + + /// + /// The ID of messages that are received from the the + /// taskbar icon. + /// + public const int CallbackMessageId = 0x400; + + /// + /// The version of the underlying icon. Defines how + /// incoming messages are interpreted. + /// + public NotifyIconVersion Version { get; set; } + + #endregion + + + #region events + + /// + /// The custom tooltip should be closed or hidden. + /// + public event Action ChangeToolTipStateRequest; + + /// + /// Fired in case the user clicked or moved within + /// the taskbar icon area. + /// + public event Action MouseEventReceived; + + /// + /// Fired if a balloon ToolTip was either displayed + /// or closed (indicated by the boolean flag). + /// + public event Action BallonToolTipChanged; + + /// + /// Fired if the taskbar was created. Requires the taskbar + /// icon to be reset. + /// + public event Action TaskbarCreated; + + #endregion + + + #region construction + + /// + /// Creates a new message sink that receives message from + /// a given taskbar icon. + /// + /// + public WindowMessageSink(NotifyIconVersion version) + { + Version = version; + CreateMessageWindow(); + } + + + private WindowMessageSink() + { + } + + + /// + /// Creates a dummy instance that provides an empty + /// pointer rather than a real window handler.
+ /// Used at design time. + ///
+ /// + internal static WindowMessageSink CreateEmpty() + { + return new WindowMessageSink + { + MessageWindowHandle = IntPtr.Zero, + Version = NotifyIconVersion.Vista + }; + } + + #endregion + + + #region Process Window Messages + + /// + /// Processes incoming system messages. + /// + /// + /// + /// + /// + private void ProcessWindowMessage(uint msg, uint wParam, uint lParam) + { + if (msg != CallbackMessageId) return; + + switch (lParam) + { + case 0x200: +// Debug.WriteLine("MOVE"); + MouseEventReceived(MouseEvent.MouseMove); + break; + + case 0x201: + Debug.WriteLine("left down 1"); + MouseEventReceived(MouseEvent.IconLeftMouseDown); + break; + + case 0x202: + Debug.WriteLine("left up"); + MouseEventReceived(MouseEvent.IconLeftMouseUp); + break; + + case 0x203: + Debug.WriteLine("left click 2"); + MouseEventReceived(MouseEvent.IconDoubleClick); + break; + + case 0x204: + Debug.WriteLine("right click 1"); + MouseEventReceived(MouseEvent.IconRightMouseDown); + break; + + case 0x205: + Console.Out.WriteLine("right mouse up"); + MouseEventReceived(MouseEvent.IconRightMouseUp); + break; + + case 0x206: + //double click with right mouse button - do not trigger event + Debug.WriteLine("right click 2"); + break; + + case 0x207: + Debug.WriteLine("middle click 1"); + MouseEventReceived(MouseEvent.IconMiddleMouseDown); + break; + + case 520: + Debug.WriteLine("mouse up middle"); + MouseEventReceived(MouseEvent.IconMiddleMouseUp); + break; + + case 0x209: + //double click with middle mouse button - do not trigger event + Debug.WriteLine("middle click 2"); + break; + + case 0x402: + Debug.WriteLine("balloon shown"); + BallonToolTipChanged(true); + break; + + case 0x403: + case 0x404: + Debug.WriteLine("balloon close"); + BallonToolTipChanged(false); + break; + + case 0x405: + Debug.WriteLine("balloon clicked"); + MouseEventReceived(MouseEvent.BalloonToolTipClicked); + break; + + case 0x406: + Debug.WriteLine("show custom tooltip"); + ChangeToolTipStateRequest(true); + break; + + case 0x407: + Debug.WriteLine("close custom tooltip"); + ChangeToolTipStateRequest(false); + break; + + default: + Debug.WriteLine("Unhandled message ID: " + lParam); + break; + } + + } + + #endregion + + + + #region Dispose + + /// + /// Set to true as soon as + /// has been invoked. + /// + public bool IsDisposed { get; private set; } + + + /// + /// Disposes the object. + /// + /// This method is not virtual by design. Derived classes + /// should override . + /// + public void Dispose() + { + Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// This destructor will run only if the + /// method does not get called. This gives this base class the + /// opportunity to finalize. + /// + /// Important: Do not provide destructors in types derived from + /// this class. + /// + /// + ~WindowMessageSink() + { + Dispose(false); + } + + + /// + /// Removes the windows hook that receives window + /// messages and closes the underlying helper window. + /// + private void Dispose(bool disposing) + { + //don't do anything if the component is already disposed + if (IsDisposed || !disposing) return; + IsDisposed = true; + + WinApi.DestroyWindow(MessageWindowHandle); + messageHandler = null; + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj new file mode 100644 index 0000000..a3b1416 --- /dev/null +++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj @@ -0,0 +1,108 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {7AC63864-7638-41C4-969C-D3197EF2BED9} + library + Properties + Hardcodet.Wpf.TaskbarNotification + Hardcodet.Wpf.TaskbarNotification + v3.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + \ No newline at end of file diff --git a/Source/NotifyIconWpf/PopupActivationMode.cs b/Source/NotifyIconWpf/PopupActivationMode.cs new file mode 100644 index 0000000..81248b8 --- /dev/null +++ b/Source/NotifyIconWpf/PopupActivationMode.cs @@ -0,0 +1,45 @@ +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Defines flags that define when a popup + /// is being displyed. + /// + public enum PopupActivationMode + { + /// + /// The item is displayed if the user clicks the + /// tray icon with the left mouse button. + /// + LeftClick, + /// + /// The item is displayed if the user clicks the + /// tray icon with the right mouse button. + /// + RightClick, + /// + /// The item is displayed if the user double-clicks the + /// tray icon. + /// + DoubleClick, + /// + /// The item is displayed if the user clicks the + /// tray icon with the left or the right mouse button. + /// + LeftOrRightClick, + /// + /// The item is displayed if the user clicks the + /// tray icon with the left mouse button or if a + /// double-click is being performed. + /// + LeftOrDoubleClick, + /// + /// The item is displayed if the user clicks the + /// tray icon with the middle mouse button. + /// + MiddleClick, + /// + /// The item is displayed whenever a click occurs. + /// + All + } +} diff --git a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..adfde1d --- /dev/null +++ b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Markup; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("NotifyIconWpf")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("NotifyIconWpf")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + + +[assembly: XmlnsDefinition("http://www.hardcodet.net/taskbar", "Hardcodet.Wpf.TaskbarNotification")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/NotifyIconWpf/Properties/Resources.Designer.cs b/Source/NotifyIconWpf/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d78e26d --- /dev/null +++ b/Source/NotifyIconWpf/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Hardcodet.Wpf.TaskbarNotification.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Hardcodet.Wpf.TaskbarNotification.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Icon DefaultTrayIcon { + get { + object obj = ResourceManager.GetObject("DefaultTrayIcon", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/Source/NotifyIconWpf/Properties/Resources.resx b/Source/NotifyIconWpf/Properties/Resources.resx new file mode 100644 index 0000000..c0f916f --- /dev/null +++ b/Source/NotifyIconWpf/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\defaulttrayicon.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Source/NotifyIconWpf/Properties/Settings.Designer.cs b/Source/NotifyIconWpf/Properties/Settings.Designer.cs new file mode 100644 index 0000000..b9cf0e1 --- /dev/null +++ b/Source/NotifyIconWpf/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Hardcodet.Wpf.TaskbarNotification.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Source/NotifyIconWpf/Properties/Settings.settings b/Source/NotifyIconWpf/Properties/Settings.settings new file mode 100644 index 0000000..8f2fd95 --- /dev/null +++ b/Source/NotifyIconWpf/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/NotifyIconWpf/RoutedEventHelper.cs b/Source/NotifyIconWpf/RoutedEventHelper.cs new file mode 100644 index 0000000..127ec77 --- /dev/null +++ b/Source/NotifyIconWpf/RoutedEventHelper.cs @@ -0,0 +1,81 @@ +using System; +using System.Windows; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Helper class used by routed events of the + /// class. + /// + internal static class RoutedEventHelper + { + #region RoutedEvent Helper Methods + + /// + /// A static helper method to raise a routed event on a target UIElement or ContentElement. + /// + /// UIElement or ContentElement on which to raise the event + /// RoutedEventArgs to use when raising the event + internal static void RaiseEvent(DependencyObject target, RoutedEventArgs args) + { + if (target is UIElement) + { + (target as UIElement).RaiseEvent(args); + } + else if (target is ContentElement) + { + (target as ContentElement).RaiseEvent(args); + } + } + + /// + /// A static helper method that adds a handler for a routed event + /// to a target UIElement or ContentElement. + /// + /// UIElement or ContentElement that listens to the event + /// Event that will be handled + /// Event handler to be added + internal static void AddHandler(DependencyObject element, RoutedEvent routedEvent, Delegate handler) + { + UIElement uie = element as UIElement; + if (uie != null) + { + uie.AddHandler(routedEvent, handler); + } + else + { + ContentElement ce = element as ContentElement; + if (ce != null) + { + ce.AddHandler(routedEvent, handler); + } + } + } + + /// + /// A static helper method that removes a handler for a routed event + /// from a target UIElement or ContentElement. + /// + /// UIElement or ContentElement that listens to the event + /// Event that will no longer be handled + /// Event handler to be removed + internal static void RemoveHandler(DependencyObject element, RoutedEvent routedEvent, Delegate handler) + { + UIElement uie = element as UIElement; + if (uie != null) + { + uie.RemoveHandler(routedEvent, handler); + } + else + { + ContentElement ce = element as ContentElement; + if (ce != null) + { + ce.RemoveHandler(routedEvent, handler); + } + } + } + + #endregion + } +} diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs new file mode 100644 index 0000000..e3a893a --- /dev/null +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -0,0 +1,868 @@ +using System; +using System.Drawing; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; +using Hardcodet.Wpf.TaskbarNotification.Interop; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Contains declarations of WPF dependency properties + /// and events. + /// + partial class TaskbarIcon + { + //DEPENDENCY PROPERTIES + + #region ToolTipText dependency property + + /// + /// A tooltip text that is being displayed if no custom + /// was set or if custom tooltips are not supported. + /// + public static readonly DependencyProperty ToolTipTextProperty = + DependencyProperty.Register("ToolTipText", + typeof (string), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(String.Empty, ToolTipTextPropertyChanged)); + + + /// + /// A property wrapper for the + /// dependency property:
+ /// A tooltip text that is being displayed if no custom + /// was set or if custom tooltips are not supported. + ///
+ public string ToolTipText + { + get { return (string) GetValue(ToolTipTextProperty); } + set { SetValue(ToolTipTextProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnToolTipTextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e) + { + string newValue = (string) e.NewValue; + + iconData.ToolTipText = newValue ?? String.Empty; + WriteToolTipSettings(); + } + + #endregion + + + #region ToolTip dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnToolTipPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnToolTipPropertyChanged(DependencyPropertyChangedEventArgs e) + { + if (e.NewValue != null) + { + ToolTip tt = e.NewValue as ToolTip; + if (tt == null) + { + tt = new ToolTip(); + tt.Content = e.NewValue; + + ToolTip = tt; + return; + } + } + + WriteToolTipSettings(); + } + + #endregion + + + #region Icon property / IconSource dependency property + + private Icon icon; + + /// + /// Gets or sets the icon to be displayed. This is not a + /// dependency property - if you want to assign the property + /// through XAML, please use the + /// dependency property. + /// + public Icon Icon + { + get { return icon; } + set + { + icon = value; + iconData.IconHandle = value == null ? IntPtr.Zero : icon.Handle; + + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Icon); + } + } + + + /// + /// Resolves an image source and updates the property accordingly. + /// + public static readonly DependencyProperty IconSourceProperty = + DependencyProperty.Register("IconSource", + typeof (ImageSource), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, IconSourcePropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Resolves an image source and updates the property accordingly. + ///
+ public ImageSource IconSource + { + get { return (ImageSource) GetValue(IconSourceProperty); } + set { SetValue(IconSourceProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnIconSourcePropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e) + { + ImageSource newValue = (ImageSource) e.NewValue; + Icon = newValue.ToIcon(); + } + + #endregion + + + #region TaskbarIconPopup dependency property + + /// + /// A custom popup that is displayed when the taskbar icon is clicked. + /// + public static readonly DependencyProperty TaskbarIconPopupProperty = + DependencyProperty.Register("TaskbarIconPopup", + typeof (Popup), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null, TaskbarIconPopupPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// A custom popup that is displayed when the taskbar icon is clicked. + ///
+ public Popup TaskbarIconPopup + { + get { return (Popup) GetValue(TaskbarIconPopupProperty); } + set { SetValue(TaskbarIconPopupProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void TaskbarIconPopupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnTaskbarIconPopupPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnTaskbarIconPopupPropertyChanged(DependencyPropertyChangedEventArgs e) + { + Popup newValue = (Popup) e.NewValue; + } + + #endregion + + + #region MenuActivation dependency property + + /// + /// Defines what mouse events display the context menu. + /// Defaults to . + /// + public static readonly DependencyProperty MenuActivationProperty = + DependencyProperty.Register("MenuActivation", + typeof (PopupActivationMode), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(PopupActivationMode.RightClick, MenuActivationPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Defines what mouse events display the context menu. + /// Defaults to . + ///
+ public PopupActivationMode MenuActivation + { + get { return (PopupActivationMode) GetValue(MenuActivationProperty); } + set { SetValue(MenuActivationProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void MenuActivationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnMenuActivationPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnMenuActivationPropertyChanged(DependencyPropertyChangedEventArgs e) + { + PopupActivationMode newValue = (PopupActivationMode) e.NewValue; + + //TODO provide implementation + throw new NotImplementedException("Change event handler for dependency property MenuActivation not implemented."); + } + + #endregion + + + #region PopupActivation dependency property + + /// + /// Defines what mouse events trigger the . + /// Default is . + /// + public static readonly DependencyProperty PopupActivationProperty = + DependencyProperty.Register("PopupActivation", + typeof (PopupActivationMode), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(PopupActivationMode.LeftClick, PopupActivationPropertyChanged)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Defines what mouse events trigger the . + /// Default is . + ///
+ public PopupActivationMode PopupActivation + { + get { return (PopupActivationMode) GetValue(PopupActivationProperty); } + set { SetValue(PopupActivationProperty, value); } + } + + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void PopupActivationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnPopupActivationPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnPopupActivationPropertyChanged(DependencyPropertyChangedEventArgs e) + { + PopupActivationMode newValue = (PopupActivationMode) e.NewValue; + + //TODO provide implementation + throw new NotImplementedException("Change event handler for dependency property PopupActivation not implemented."); + } + + #endregion + + + #region Visibility dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnVisibilityPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnVisibilityPropertyChanged(DependencyPropertyChangedEventArgs e) + { + Visibility newValue = (Visibility) e.NewValue; + + //update + if (newValue == Visibility.Visible) + { + CreateTaskbarIcon(); + } + else + { + RemoveTaskbarIcon(); + } + } + + #endregion + + + #region ContextMenu dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnContextMenuPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) + { + ContextMenu newValue = (ContextMenu) e.NewValue; + //TODO provide implementation + } + + #endregion + + + + //EVENTS + + #region TaskbarIconLeftMouseDown + + /// + /// TaskbarIconLeftMouseDown Routed Event + /// + public static readonly RoutedEvent TaskbarIconLeftMouseDownEvent = EventManager.RegisterRoutedEvent("TaskbarIconLeftMouseDown", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user presses the left mouse button. + /// + public event RoutedEventHandler TaskbarIconLeftMouseDown + { + add { AddHandler(TaskbarIconLeftMouseDownEvent, value); } + remove { RemoveHandler(TaskbarIconLeftMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconLeftMouseDown event. + /// + protected RoutedEventArgs RaiseTaskbarIconLeftMouseDownEvent() + { + return RaiseTaskbarIconLeftMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconLeftMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconLeftMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconLeftMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconRightMouseDown + + /// + /// TaskbarIconRightMouseDown Routed Event + /// + public static readonly RoutedEvent TaskbarIconRightMouseDownEvent = EventManager.RegisterRoutedEvent("TaskbarIconRightMouseDown", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the presses the right mouse button. + /// + public event RoutedEventHandler TaskbarIconRightMouseDown + { + add { AddHandler(TaskbarIconRightMouseDownEvent, value); } + remove { RemoveHandler(TaskbarIconRightMouseDownEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconRightMouseDown event. + /// + protected RoutedEventArgs RaiseTaskbarIconRightMouseDownEvent() + { + return RaiseTaskbarIconRightMouseDownEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconRightMouseDown event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconRightMouseDownEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconRightMouseDownEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconLeftMouseUp + + /// + /// TaskbarIconLeftMouseUp Routed Event + /// + public static readonly RoutedEvent TaskbarIconLeftMouseUpEvent = EventManager.RegisterRoutedEvent("TaskbarIconLeftMouseUp", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user releases the left mouse button. + /// + public event RoutedEventHandler TaskbarIconLeftMouseUp + { + add { AddHandler(TaskbarIconLeftMouseUpEvent, value); } + remove { RemoveHandler(TaskbarIconLeftMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconLeftMouseUp event. + /// + protected RoutedEventArgs RaiseTaskbarIconLeftMouseUpEvent() + { + return RaiseTaskbarIconLeftMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconLeftMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconLeftMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconLeftMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconRightMouseUp + + /// + /// TaskbarIconRightMouseUp Routed Event + /// + public static readonly RoutedEvent TaskbarIconRightMouseUpEvent = EventManager.RegisterRoutedEvent("TaskbarIconRightMouseUp", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Occurs when the user releases the right mouse button. + /// + public event RoutedEventHandler TaskbarIconRightMouseUp + { + add { AddHandler(TaskbarIconRightMouseUpEvent, value); } + remove { RemoveHandler(TaskbarIconRightMouseUpEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconRightMouseUp event. + /// + protected RoutedEventArgs RaiseTaskbarIconRightMouseUpEvent() + { + return RaiseTaskbarIconRightMouseUpEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconRightMouseUp event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconRightMouseUpEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconRightMouseUpEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + #region TaskbarIconPopupOpen (and PreviewTaskbarIconPopupOpen) + + /// + /// TaskbarIconPopupOpen Routed Event + /// + public static readonly RoutedEvent TaskbarIconPopupOpenEvent = EventManager.RegisterRoutedEvent("TaskbarIconPopupOpen", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Bubbled event that occurs when the custom popup is being opened. + /// + public event RoutedEventHandler TaskbarIconPopupOpen + { + add { AddHandler(TaskbarIconPopupOpenEvent, value); } + remove { RemoveHandler(TaskbarIconPopupOpenEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconPopupOpen event. + /// + protected RoutedEventArgs RaiseTaskbarIconPopupOpenEvent() + { + return RaiseTaskbarIconPopupOpenEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconPopupOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconPopupOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconPopupOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTaskbarIconPopupOpen Routed Event + /// + public static readonly RoutedEvent PreviewTaskbarIconPopupOpenEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconPopupOpen", + RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Tunneled event that occurs when the custom popup is being opened. + /// + public event RoutedEventHandler PreviewTaskbarIconPopupOpen + { + add { AddHandler(PreviewTaskbarIconPopupOpenEvent, value); } + remove { RemoveHandler(PreviewTaskbarIconPopupOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTaskbarIconPopupOpen event. + /// + protected RoutedEventArgs RaisePreviewTaskbarIconPopupOpenEvent() + { + return RaisePreviewTaskbarIconPopupOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTaskbarIconPopupOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTaskbarIconPopupOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTaskbarIconPopupOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconToolTipOpen (and PreviewTaskbarIconToolTipOpen) + + /// + /// TaskbarIconToolTipOpen Routed Event + /// + public static readonly RoutedEvent TaskbarIconToolTipOpenEvent = EventManager.RegisterRoutedEvent("TaskbarIconToolTipOpen", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Bubbled event that occurs when the custom ToolTip is being displayed. + /// + public event RoutedEventHandler TaskbarIconToolTipOpen + { + add { AddHandler(TaskbarIconToolTipOpenEvent, value); } + remove { RemoveHandler(TaskbarIconToolTipOpenEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconToolTipOpen event. + /// + protected RoutedEventArgs RaiseTaskbarIconToolTipOpenEvent() + { + return RaiseTaskbarIconToolTipOpenEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconToolTipOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconToolTipOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconToolTipOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTaskbarIconToolTipOpen Routed Event + /// + public static readonly RoutedEvent PreviewTaskbarIconToolTipOpenEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconToolTipOpen", + RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Tunneled event that occurs when the custom ToolTip is being displayed. + /// + public event RoutedEventHandler PreviewTaskbarIconToolTipOpen + { + add { AddHandler(PreviewTaskbarIconToolTipOpenEvent, value); } + remove { RemoveHandler(PreviewTaskbarIconToolTipOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTaskbarIconToolTipOpen event. + /// + protected RoutedEventArgs RaisePreviewTaskbarIconToolTipOpenEvent() + { + return RaisePreviewTaskbarIconToolTipOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTaskbarIconToolTipOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTaskbarIconToolTipOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTaskbarIconToolTipOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + #region TaskbarIconContextMenuOpen (and PreviewTaskbarIconContextMenuOpen) + + /// + /// TaskbarIconContextMenuOpen Routed Event + /// + public static readonly RoutedEvent TaskbarIconContextMenuOpenEvent = EventManager.RegisterRoutedEvent("TaskbarIconContextMenuOpen", + RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Bubbled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler TaskbarIconContextMenuOpen + { + add { AddHandler(TaskbarIconContextMenuOpenEvent, value); } + remove { RemoveHandler(TaskbarIconContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the TaskbarIconContextMenuOpen event. + /// + protected RoutedEventArgs RaiseTaskbarIconContextMenuOpenEvent() + { + return RaiseTaskbarIconContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the TaskbarIconContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaiseTaskbarIconContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = TaskbarIconContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + /// + /// PreviewTaskbarIconContextMenuOpen Routed Event + /// + public static readonly RoutedEvent PreviewTaskbarIconContextMenuOpenEvent = EventManager.RegisterRoutedEvent("PreviewTaskbarIconContextMenuOpen", + RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon)); + + /// + /// Tunneled event that occurs when the context menu of the taskbar icon is being displayed. + /// + public event RoutedEventHandler PreviewTaskbarIconContextMenuOpen + { + add { AddHandler(PreviewTaskbarIconContextMenuOpenEvent, value); } + remove { RemoveHandler(PreviewTaskbarIconContextMenuOpenEvent, value); } + } + + /// + /// A helper method to raise the PreviewTaskbarIconContextMenuOpen event. + /// + protected RoutedEventArgs RaisePreviewTaskbarIconContextMenuOpenEvent() + { + return RaisePreviewTaskbarIconContextMenuOpenEvent(this); + } + + /// + /// A static helper method to raise the PreviewTaskbarIconContextMenuOpen event on a target element. + /// + /// UIElement or ContentElement on which to raise the event + internal static RoutedEventArgs RaisePreviewTaskbarIconContextMenuOpenEvent(DependencyObject target) + { + if (target == null) return null; + + RoutedEventArgs args = new RoutedEventArgs(); + args.RoutedEvent = PreviewTaskbarIconContextMenuOpenEvent; + RoutedEventHelper.RaiseEvent(target, args); + return args; + } + + #endregion + + + + + //CONSTRUCTOR DECLARATIONS + + /// + /// Registers properties. + /// + static TaskbarIcon() + { + //register change listener for the Visibility property + PropertyMetadata md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); + VisibilityProperty.OverrideMetadata(typeof(TaskbarIcon), md); + + //register change listener for the ContextMenu property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged)); + ContextMenuProperty.OverrideMetadata(typeof (TaskbarIcon), md); + + //register change listener for the ToolTip property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ToolTipPropertyChanged)); + ToolTipProperty.OverrideMetadata(typeof(TaskbarIcon), md); + + } + } +} \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.Interop.cs b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs new file mode 100644 index 0000000..4921a97 --- /dev/null +++ b/Source/NotifyIconWpf/TaskbarIcon.Interop.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using Hardcodet.Wpf.TaskbarNotification.Interop; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + partial class TaskbarIcon + { + /// + /// An action that is being invoked if the + /// fires. + /// + private Action delayedTimerAction; + + /// + /// A timer that is used to differentiate between single + /// and double clicks. + /// + private readonly Timer singleClickTimer; + + + #region SetVersion + + /// + /// Sets the version flag for the . + /// + private void SetVersion() + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Vista; + bool status = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref iconData); + + if (!status) + { + iconData.VersionOrTimeout = (uint) NotifyIconVersion.Win2000; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + iconData.VersionOrTimeout = (uint)NotifyIconVersion.Win95; + status = Util.WriteIconData(ref iconData, NotifyCommand.SetVersion); + } + + if (!status) + { + Debug.Fail("Could not set version"); + } + } + + #endregion + + + /// + /// Sets tooltip settings for the class. + /// + private void WriteToolTipSettings() + { + IconDataMembers flags = IconDataMembers.Tip; + iconData.ToolTipText = ToolTipText; + + if (messageSink.Version == NotifyIconVersion.Vista) + { + if (String.IsNullOrEmpty(ToolTipText) && ToolTip != null) + { + //if we have not tooltip text but a custom tooltip, we + //need to set a dummy value + iconData.ToolTipText = "ToolTip"; + } + else if (!String.IsNullOrEmpty(ToolTipText) && ToolTip == null) + { + //if a tooltip text was set but there is no custom tooltip, + //we need to fall back to legacy operations + flags |= IconDataMembers.UseLegacyToolTips; + } + } + + //just write the the tooltip + Util.WriteIconData(ref iconData, NotifyCommand.Modify, flags); + } + + + #region Show / Hide Balloon ToolTip + + /// + /// Displays a balloon tip with the specified title, + /// text, and icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// Indicates the severity. + public void ShowBalloonTip(string title, string message, BalloonIcon icon) + { + lock(this) + { + ShowBalloonTip(title, message, icon.GetBalloonFlag(), IntPtr.Zero); + } + } + + + /// + /// Displays a balloon tip with the specified title, + /// text, and a custom icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A custom icon. + /// If + /// is a null reference. + public void ShowBalloonTip(string title, string message, Icon customIcon) + { + if (customIcon == null) throw new ArgumentNullException("customIcon"); + + lock(this) + { + ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle); + } + } + + + + /// + /// Invokes in order to display + /// a given balloon ToolTip. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// Indicates what icon to use. + /// A handle to a custom icon, if any, or + /// . + private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) + { + EnsureNotDisposed(); + + iconData.BalloonText = message; + iconData.BalloonTitle = title; + + iconData.BalloonFlags = flags; + iconData.CustomBalloonIconHandle = balloonIconHandle; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + } + + + + /// + /// Hides a balloon ToolTip, if any is displayed. + /// + public void HideBalloonTip() + { + EnsureNotDisposed(); + + //reset balloon by just setting the info to an empty string + iconData.BalloonText = iconData.BalloonTitle = String.Empty; + Util.WriteIconData(ref iconData, NotifyCommand.Modify, IconDataMembers.Info); + } + + #endregion + + + #region Single Click Timer event + + /// + /// Performs a delayed action if the user requested an action + /// based on a single click of the left mouse.
+ /// This method is invoked by the . + ///
+ private void DoSingleClickAction(object state) + { + if (IsDisposed) return; + + //run action + Action action = delayedTimerAction; + if (action != null) + { + //cleanup action + delayedTimerAction = null; + + //switch to UI thread + Application.Current.Dispatcher.Invoke(action); + } + } + + #endregion + + + #region Show Tray Popup / Context Menu + + /// + /// Displays the control if + /// it was set. + /// + private void ShowTrayPopup() + { + if (IsDisposed) return; + + if (TaskbarIconPopup != null) + { + //raise preview event + var args = RaisePreviewTaskbarIconPopupOpenEvent(); + if (args.Handled) return; + + //open popup + TaskbarIconPopup.IsOpen = true; + + //activate the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); + + //bubble event + RaiseTaskbarIconPopupOpenEvent(); + } + } + + + /// + /// Displays the if + /// it was set. + /// + private void ShowContextMenu() + { + if (IsDisposed) return; + + if (ContextMenu != null) + { + //raise preview event + var args = RaisePreviewTaskbarIconContextMenuOpenEvent(); + if (args.Handled) return; + + //CreateActivationWindow(); + ContextMenu.IsOpen = true; + + //activate the message window to track deactivation - otherwise, the context menu + //does not close if the user clicks somewhere else + WinApi.SetForegroundWindow(messageSink.MessageWindowHandle); + + //bubble event + RaiseTaskbarIconContextMenuOpenEvent(); + } + } + + #endregion + } +} diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs new file mode 100644 index 0000000..d13005a --- /dev/null +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -0,0 +1,379 @@ +using System; +using System.ComponentModel; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; +using Hardcodet.Wpf.TaskbarNotification.Interop; +using Rect=Hardcodet.Wpf.TaskbarNotification.Interop.Rect; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + internal class MyClass + { + public void Test() + { + TaskbarIcon icon = new TaskbarIcon(); + icon.Icon = Properties.Resources.DefaultTrayIcon; + Console.Out.WriteLine("DISPLAY NOW..."); + Thread.CurrentThread.Join(1500); + //icon.ShowBalloonTip("some title", "hello world", Properties.Resources.DefaultTrayIcon); + //Console.Out.WriteLine("status = {0}", status); + Thread.CurrentThread.Join(5000); + } + + public void Test2() + { + var tbInfo = TrayLocator.GetTaskbarInformation(); + var w = new Window(); + w.Background = Brushes.Red; + w.WindowStyle = WindowStyle.None; + + Rect rect = tbInfo.Rectangle; + w.Width = Math.Max(20, rect.right - rect.left); + w.Height = Math.Max(20, rect.bottom - rect.top); + w.Left = rect.left; + w.Top = rect.top - 100; + w.ShowDialog(); + } + } + + /// + /// Represent a taskbar icon that sits in the system + /// tray. + /// + public partial class TaskbarIcon : FrameworkElement, IDisposable + { + /// + /// Represents the current icon data. + /// + private NotifyIconData iconData; + + /// + /// Receives messages from the taskbar icon. + /// + private readonly WindowMessageSink messageSink; + + /// + /// Indicates whether the taskbar icon has been created or not. + /// + public bool IsTaskbarIconCreated { get; set; } + + + /// + /// Indicates whether custom tooltips are supported. + /// + public bool SupportsCustomToolTips + { + get { return messageSink.Version == NotifyIconVersion.Vista; } + } + + + /// + /// Inits the taskbar icon and registers a message listener + /// in order to receive events from the taskbar area. + /// + public TaskbarIcon() + { + //do nothing if in design mode + if (Util.IsDesignMode) + { + messageSink = WindowMessageSink.CreateEmpty(); + } + else + { + //create message sink that receives window messages + messageSink = new WindowMessageSink(NotifyIconVersion.Win95); + } + + //init icon data structure + iconData = NotifyIconData.CreateDefault(messageSink.MessageWindowHandle); + + //create the taskbar icon + CreateTaskbarIcon(); + + //register event listeners + messageSink.MouseEventReceived += OnMouseEvent; + messageSink.TaskbarCreated += OnTaskbarCreated; + messageSink.ChangeToolTipStateRequest += OnToolTipChange; + messageSink.BallonToolTipChanged += OnBalloonToolTipChanged; + + //init single click timer + singleClickTimer = new Timer(DoSingleClickAction); + + + //register listener in order to get notified when the application closes + if (Application.Current != null) Application.Current.Exit += OnExit; + + } + + + + /// + /// Processes mouse events, which are bubbled + /// through the class' routed events, trigger + /// certain actions (e.g. show a popup), or + /// both. + /// + /// Event flag. + private void OnMouseEvent(MouseEvent me) + { + if (IsDisposed) return; + + switch(me) + { + case MouseEvent.MouseMove: + break; + case MouseEvent.IconRightMouseDown: + RaiseTaskbarIconRightMouseDownEvent(); + break; + case MouseEvent.IconLeftMouseDown: + RaiseTaskbarIconLeftMouseDownEvent(); + break; + case MouseEvent.IconRightMouseUp: + RaiseTaskbarIconRightMouseUpEvent(); + break; + case MouseEvent.IconLeftMouseUp: + RaiseTaskbarIconLeftMouseUpEvent(); + break; + case MouseEvent.IconMiddleMouseDown: + break; + case MouseEvent.IconMiddleMouseUp: + break; + case MouseEvent.IconDoubleClick: + + //cancel single click timer + singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); + + break; + case MouseEvent.BalloonToolTipClicked: + break; + default: + throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me); + + } + + + //show popup, if requested + if (me.IsMatch(PopupActivation)) + { + if (me == MouseEvent.IconLeftMouseUp) + { + //show popup once we are sure it's not a double click + delayedTimerAction = ShowTrayPopup; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + } + else + { + //show popup immediately + ShowTrayPopup(); + } + } + + + //show context menu, if requested + if (me.IsMatch(MenuActivation)) + { + if (me == MouseEvent.IconLeftMouseUp) + { + //show context menu once we are sure it's not a double click + delayedTimerAction = ShowContextMenu; + singleClickTimer.Change(WinApi.GetDoubleClickTime(), Timeout.Infinite); + } + else + { + //show context menu immediately + ShowContextMenu(); + } + } + } + + + + private void OnToolTipChange(bool visible) + { + //if we have a custom tooltip, show it now + if (ToolTip == null) return; + + ToolTip tt = (ToolTip)ToolTip; + tt.IsOpen = visible; + } + + + private void OnBalloonToolTipChanged(bool visible) + { + //TODO just raise event + } + + + + /// + /// Recreates the taskbar icon if the whole taskbar was + /// recreated (e.g. because Explorer was shut down). + /// + private void OnTaskbarCreated() + { + IsTaskbarIconCreated = false; + CreateTaskbarIcon(); + } + + + + + + + #region create / remove taskbar icon + + /// + /// Creates the taskbar icon. This message is invoked during initialization, + /// if the taskbar is restarted, and whenever the icon is displayed. + /// + private void CreateTaskbarIcon() + { + lock (this) + { + if (!IsTaskbarIconCreated) + { + const IconDataMembers members = IconDataMembers.Message + | IconDataMembers.Icon + | IconDataMembers.Tip; + + //write initial configuration + var status = Util.WriteIconData(ref iconData, NotifyCommand.Add, members); + if (!status) + { + throw new Win32Exception("Could not create icon data"); + } + + //set to most recent version + SetVersion(); + messageSink.Version = (NotifyIconVersion) iconData.VersionOrTimeout; + + IsTaskbarIconCreated = true; + } + } + } + + + /// + /// Closes the taskbar icon if required. + /// + private void RemoveTaskbarIcon() + { + lock (this) + { + if (IsTaskbarIconCreated) + { + Util.WriteIconData(ref iconData, NotifyCommand.Delete, IconDataMembers.Message); + IsTaskbarIconCreated = false; + } + } + } + + #endregion + + + #region Dispose / Exit + + /// + /// Set to true as soon as + /// has been invoked. + /// + public bool IsDisposed { get; private set; } + + + /// + /// Checks if the object has been disposed and + /// raises a in case + /// the flag is true. + /// + private void EnsureNotDisposed() + { + if (IsDisposed) throw new ObjectDisposedException(Name ?? GetType().FullName); + } + + + /// + /// Disposes the class if the application exits. + /// + private void OnExit(object sender, EventArgs e) + { + Dispose(); + } + + + /// + /// This destructor will run only if the + /// method does not get called. This gives this base class the + /// opportunity to finalize. + /// + /// Important: Do not provide destructors in types derived from + /// this class. + /// + /// + ~TaskbarIcon() + { + Dispose(false); + } + + + /// + /// Disposes the object. + /// + /// This method is not virtual by design. Derived classes + /// should override . + /// + public void Dispose() + { + Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + + /// + /// Closes the tray and releases all resources. + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// + /// If disposing equals false, the method + /// has been called by the runtime from inside the finalizer and you + /// should not reference other objects. Only unmanaged resources can + /// be disposed. + /// Check the property to determine whether + /// the method has already been called. + private void Dispose(bool disposing) + { + //don't do anything if the component is already disposed + if (IsDisposed || !disposing) return; + + lock (this) + { + IsDisposed = true; + + //deregister application event listener + Application.Current.Exit -= OnExit; + + //stop timer + singleClickTimer.Dispose(); + + //dispose message sink + messageSink.Dispose(); + + RemoveTaskbarIcon(); + } + } + + #endregion + } +} diff --git a/Source/NotifyIconWpf/Util.cs b/Source/NotifyIconWpf/Util.cs new file mode 100644 index 0000000..55e773d --- /dev/null +++ b/Source/NotifyIconWpf/Util.cs @@ -0,0 +1,225 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows; +using System.Windows.Media; +using System.Windows.Resources; +using Hardcodet.Wpf.TaskbarNotification.Interop; + +namespace Hardcodet.Wpf.TaskbarNotification +{ + /// + /// Util and extension methods. + /// + internal static class Util + { + public static readonly object SyncRoot = new object(); + + + #region IsDesignMode + + private static readonly bool isDesignMode; + + /// + /// Checks whether the application is currently in design mode. + /// + public static bool IsDesignMode + { + get { return isDesignMode; } + } + + #endregion + + + #region construction + + static Util() + { + isDesignMode = + (bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement)) + .Metadata.DefaultValue; + } + + #endregion + + + #region CreateHelperWindow + + /// + /// Creates an transparent window without dimension that + /// can be used to temporarily obtain focus and/or + /// be used as a window message sink. + /// + /// Empty window. + public static Window CreateHelperWindow() + { + return new Window + { + Width = 0, + Height = 0, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None, + AllowsTransparency = true, + Opacity = 0 + }; + } + + #endregion + + + #region WriteIconData + + /// + /// Updates the taskbar icons with data provided by a given + /// instance. + /// + /// + /// + /// + public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command) + { + return WriteIconData(ref data, command, data.ValidMembers); + } + + + /// + /// Updates the taskbar icons with data provided by a given + /// instance. + /// + /// + /// + /// + /// + public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command, IconDataMembers flags) + { + //do nothing if in design mode + if (IsDesignMode) return true; + + data.ValidMembers = flags; + lock (SyncRoot) + { + return WinApi.Shell_NotifyIcon(command, ref data); + } + } + + #endregion + + + #region GetBalloonFlag + + /// + /// Gets a enum value that + /// matches a given . + /// + public static BalloonFlags GetBalloonFlag(this BalloonIcon icon) + { + switch (icon) + { + case BalloonIcon.None: + return BalloonFlags.None; + case BalloonIcon.Info: + return BalloonFlags.Info; + case BalloonIcon.Warning: + return BalloonFlags.Warning; + case BalloonIcon.Error: + return BalloonFlags.Error; + default: + throw new ArgumentOutOfRangeException("icon"); + } + } + + #endregion + + + #region ImageSource to Icon + + /// + /// Reads a given image resource into a WinForms icon. + /// + /// Image source pointing to + /// an icon file (*.ico). + /// An icon object that can be used with the + /// taskbar area. + public static Icon ToIcon(this ImageSource imageSource) + { + if (imageSource == null) return null; + + Uri uri = new Uri(imageSource.ToString()); + StreamResourceInfo streamInfo = Application.GetResourceStream(uri); + + if (streamInfo == null) + { + string msg = "The supplied image source '{0}' could not be resolved."; + msg = String.Format(msg, imageSource); + throw new ArgumentException(msg); + } + + return new Icon(streamInfo.Stream); + } + + #endregion + + + #region evaluate listings + + /// + /// Checks a list of candidates for equality to a given + /// reference value. + /// + /// + /// The evaluated value. + /// A liste of possible values that are + /// regarded valid. + /// True if one of the submitted + /// matches the evaluated value. If the + /// parameter itself is null, too, the method returns false as well, + /// which allows to check with null values, too. + /// If + /// is a null reference. + public static bool Is(this T value, params T[] candidates) + { + if (candidates == null) return false; + + foreach (var t in candidates) + { + if (value.Equals(t)) return true; + } + + return false; + } + + #endregion + + + #region match MouseEvent to PopupActivation + + /// + /// Checks if a given is a match for + /// an effectively pressed mouse button. + /// + public static bool IsMatch(this MouseEvent me, PopupActivationMode activationMode) + { + switch (activationMode) + { + case PopupActivationMode.LeftClick: + return me == MouseEvent.IconLeftMouseUp; + case PopupActivationMode.RightClick: + return me == MouseEvent.IconRightMouseUp; + case PopupActivationMode.LeftOrRightClick: + return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconRightMouseUp); + case PopupActivationMode.LeftOrDoubleClick: + return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconDoubleClick); + case PopupActivationMode.DoubleClick: + return me.Is(MouseEvent.IconDoubleClick); + case PopupActivationMode.MiddleClick: + return me == MouseEvent.IconMiddleMouseUp; + case PopupActivationMode.All: + return true; + default: + throw new ArgumentOutOfRangeException("activationMode"); + } + } + + #endregion + } +} diff --git a/Source/Sample Project/App.xaml b/Source/Sample Project/App.xaml new file mode 100644 index 0000000..0c9c882 --- /dev/null +++ b/Source/Sample Project/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Source/Sample Project/App.xaml.cs b/Source/Sample Project/App.xaml.cs new file mode 100644 index 0000000..92b661a --- /dev/null +++ b/Source/Sample Project/App.xaml.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace Sample_Project +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Source/Sample Project/Icons/Bulb.ico b/Source/Sample Project/Icons/Bulb.ico new file mode 100644 index 0000000..e3ff3c4 Binary files /dev/null and b/Source/Sample Project/Icons/Bulb.ico differ diff --git a/Source/Sample Project/Icons/Computers.ico b/Source/Sample Project/Icons/Computers.ico new file mode 100644 index 0000000..00a4e22 Binary files /dev/null and b/Source/Sample Project/Icons/Computers.ico differ diff --git a/Source/Sample Project/Icons/NetDrives.ico b/Source/Sample Project/Icons/NetDrives.ico new file mode 100644 index 0000000..a9d3372 Binary files /dev/null and b/Source/Sample Project/Icons/NetDrives.ico differ diff --git a/Source/Sample Project/Properties/AssemblyInfo.cs b/Source/Sample Project/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c10547a --- /dev/null +++ b/Source/Sample Project/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Sample Project")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Sample Project")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/Sample Project/Properties/Resources.Designer.cs b/Source/Sample Project/Properties/Resources.Designer.cs new file mode 100644 index 0000000..1646b08 --- /dev/null +++ b/Source/Sample Project/Properties/Resources.Designer.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sample_Project.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sample_Project.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Icon Bulb { + get { + object obj = ResourceManager.GetObject("Bulb", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + internal static System.Drawing.Icon Computers { + get { + object obj = ResourceManager.GetObject("Computers", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + internal static System.Drawing.Icon NetDrives { + get { + object obj = ResourceManager.GetObject("NetDrives", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/Source/Sample Project/Properties/Resources.resx b/Source/Sample Project/Properties/Resources.resx new file mode 100644 index 0000000..98e1ee3 --- /dev/null +++ b/Source/Sample Project/Properties/Resources.resx @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\icons\bulb.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\computers.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\netdrives.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Source/Sample Project/Properties/Settings.Designer.cs b/Source/Sample Project/Properties/Settings.Designer.cs new file mode 100644 index 0000000..4a1169a --- /dev/null +++ b/Source/Sample Project/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sample_Project.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Source/Sample Project/Properties/Settings.settings b/Source/Sample Project/Properties/Settings.settings new file mode 100644 index 0000000..8f2fd95 --- /dev/null +++ b/Source/Sample Project/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/Sample Project/Sample Project.csproj b/Source/Sample Project/Sample Project.csproj new file mode 100644 index 0000000..6a3b392 --- /dev/null +++ b/Source/Sample Project/Sample Project.csproj @@ -0,0 +1,121 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {71C74F29-F1C2-49C5-969F-C25AC4CDFCCC} + WinExe + Properties + Sample_Project + Sample Project + v3.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + Window1.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + {7AC63864-7638-41C4-969C-D3197EF2BED9} + NotifyIconWpf + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Sample Project/Window1.xaml b/Source/Sample Project/Window1.xaml new file mode 100644 index 0000000..8c449cf --- /dev/null +++ b/Source/Sample Project/Window1.xaml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Sample Project/Window1.xaml.cs b/Source/Sample Project/Window1.xaml.cs new file mode 100644 index 0000000..639bfe1 --- /dev/null +++ b/Source/Sample Project/Window1.xaml.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Sample_Project +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class Window1 : Window + { + public Window1() + { + InitializeComponent(); + + //set icon in code - setting the IconSource in XAML + //works just fine but breaks the VS designer + tb.Icon = Properties.Resources.Computers; + } + + private void OnClick(object sender, RoutedEventArgs e) + { + if (tb.Visibility == System.Windows.Visibility.Visible) + { + tb.Visibility = System.Windows.Visibility.Collapsed; + } + else + { + tb.Visibility = Visibility.Visible; + } + } + } +}