Util.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // hardcodet.net NotifyIcon for WPF
  2. // Copyright (c) 2009 - 2013 Philipp Sumi
  3. // Contact and Information: http://www.hardcodet.net
  4. //
  5. // This library is free software; you can redistribute it and/or
  6. // modify it under the terms of the Code Project Open License (CPOL);
  7. // either version 1.0 of the License, or (at your option) any later
  8. // version.
  9. //
  10. // The above copyright notice and this permission notice shall be
  11. // included in all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  15. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  17. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  18. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. // OTHER DEALINGS IN THE SOFTWARE.
  21. //
  22. // THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE
  23. using System;
  24. using System.ComponentModel;
  25. using System.Drawing;
  26. using System.Windows;
  27. using System.Windows.Input;
  28. using System.Windows.Media;
  29. using System.Windows.Resources;
  30. using System.Windows.Threading;
  31. using Hardcodet.Wpf.TaskbarNotification.Interop;
  32. namespace Hardcodet.Wpf.TaskbarNotification
  33. {
  34. /// <summary>
  35. /// Util and extension methods.
  36. /// </summary>
  37. internal static class Util
  38. {
  39. public static readonly object SyncRoot = new object();
  40. #region IsDesignMode
  41. private static readonly bool isDesignMode;
  42. /// <summary>
  43. /// Checks whether the application is currently in design mode.
  44. /// </summary>
  45. public static bool IsDesignMode
  46. {
  47. get { return isDesignMode; }
  48. }
  49. #endregion
  50. #region construction
  51. static Util()
  52. {
  53. isDesignMode =
  54. (bool)
  55. DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty,
  56. typeof (FrameworkElement))
  57. .Metadata.DefaultValue;
  58. }
  59. #endregion
  60. #region CreateHelperWindow
  61. /// <summary>
  62. /// Creates an transparent window without dimension that
  63. /// can be used to temporarily obtain focus and/or
  64. /// be used as a window message sink.
  65. /// </summary>
  66. /// <returns>Empty window.</returns>
  67. public static Window CreateHelperWindow()
  68. {
  69. return new Window
  70. {
  71. Width = 0,
  72. Height = 0,
  73. ShowInTaskbar = false,
  74. WindowStyle = WindowStyle.None,
  75. AllowsTransparency = true,
  76. Opacity = 0
  77. };
  78. }
  79. #endregion
  80. #region WriteIconData
  81. /// <summary>
  82. /// Updates the taskbar icons with data provided by a given
  83. /// <see cref="NotifyIconData"/> instance.
  84. /// </summary>
  85. /// <param name="data">Configuration settings for the NotifyIcon.</param>
  86. /// <param name="command">Operation on the icon (e.g. delete the icon).</param>
  87. /// <returns>True if the data was successfully written.</returns>
  88. /// <remarks>See Shell_NotifyIcon documentation on MSDN for details.</remarks>
  89. public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command)
  90. {
  91. return WriteIconData(ref data, command, data.ValidMembers);
  92. }
  93. /// <summary>
  94. /// Updates the taskbar icons with data provided by a given
  95. /// <see cref="NotifyIconData"/> instance.
  96. /// </summary>
  97. /// <param name="data">Configuration settings for the NotifyIcon.</param>
  98. /// <param name="command">Operation on the icon (e.g. delete the icon).</param>
  99. /// <param name="flags">Defines which members of the <paramref name="data"/>
  100. /// structure are set.</param>
  101. /// <returns>True if the data was successfully written.</returns>
  102. /// <remarks>See Shell_NotifyIcon documentation on MSDN for details.</remarks>
  103. public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command, IconDataMembers flags)
  104. {
  105. //do nothing if in design mode
  106. if (IsDesignMode) return true;
  107. data.ValidMembers = flags;
  108. lock (SyncRoot)
  109. {
  110. return WinApi.Shell_NotifyIcon(command, ref data);
  111. }
  112. }
  113. #endregion
  114. #region GetBalloonFlag
  115. /// <summary>
  116. /// Gets a <see cref="BalloonFlags"/> enum value that
  117. /// matches a given <see cref="BalloonIcon"/>.
  118. /// </summary>
  119. public static BalloonFlags GetBalloonFlag(this BalloonIcon icon)
  120. {
  121. switch (icon)
  122. {
  123. case BalloonIcon.None:
  124. return BalloonFlags.None;
  125. case BalloonIcon.Info:
  126. return BalloonFlags.Info;
  127. case BalloonIcon.Warning:
  128. return BalloonFlags.Warning;
  129. case BalloonIcon.Error:
  130. return BalloonFlags.Error;
  131. default:
  132. throw new ArgumentOutOfRangeException("icon");
  133. }
  134. }
  135. #endregion
  136. #region ImageSource to Icon
  137. /// <summary>
  138. /// Reads a given image resource into a WinForms icon.
  139. /// </summary>
  140. /// <param name="imageSource">Image source pointing to
  141. /// an icon file (*.ico).</param>
  142. /// <returns>An icon object that can be used with the
  143. /// taskbar area.</returns>
  144. public static Icon ToIcon(this ImageSource imageSource)
  145. {
  146. if (imageSource == null) return null;
  147. Uri uri = new Uri(imageSource.ToString());
  148. StreamResourceInfo streamInfo = Application.GetResourceStream(uri);
  149. if (streamInfo == null)
  150. {
  151. string msg = "The supplied image source '{0}' could not be resolved.";
  152. msg = string.Format(msg, imageSource);
  153. throw new ArgumentException(msg);
  154. }
  155. return new Icon(streamInfo.Stream);
  156. }
  157. #endregion
  158. #region evaluate listings
  159. /// <summary>
  160. /// Checks a list of candidates for equality to a given
  161. /// reference value.
  162. /// </summary>
  163. /// <typeparam name="T"></typeparam>
  164. /// <param name="value">The evaluated value.</param>
  165. /// <param name="candidates">A liste of possible values that are
  166. /// regarded valid.</param>
  167. /// <returns>True if one of the submitted <paramref name="candidates"/>
  168. /// matches the evaluated value. If the <paramref name="candidates"/>
  169. /// parameter itself is null, too, the method returns false as well,
  170. /// which allows to check with null values, too.</returns>
  171. /// <exception cref="ArgumentNullException">If <paramref name="candidates"/>
  172. /// is a null reference.</exception>
  173. public static bool Is<T>(this T value, params T[] candidates)
  174. {
  175. if (candidates == null) return false;
  176. foreach (var t in candidates)
  177. {
  178. if (value.Equals(t)) return true;
  179. }
  180. return false;
  181. }
  182. #endregion
  183. #region match MouseEvent to PopupActivation
  184. /// <summary>
  185. /// Checks if a given <see cref="PopupActivationMode"/> is a match for
  186. /// an effectively pressed mouse button.
  187. /// </summary>
  188. public static bool IsMatch(this MouseEvent me, PopupActivationMode activationMode)
  189. {
  190. switch (activationMode)
  191. {
  192. case PopupActivationMode.LeftClick:
  193. return me == MouseEvent.IconLeftMouseUp;
  194. case PopupActivationMode.RightClick:
  195. return me == MouseEvent.IconRightMouseUp;
  196. case PopupActivationMode.LeftOrRightClick:
  197. return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconRightMouseUp);
  198. case PopupActivationMode.LeftOrDoubleClick:
  199. return me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconDoubleClick);
  200. case PopupActivationMode.DoubleClick:
  201. return me.Is(MouseEvent.IconDoubleClick);
  202. case PopupActivationMode.MiddleClick:
  203. return me == MouseEvent.IconMiddleMouseUp;
  204. case PopupActivationMode.All:
  205. //return true for everything except mouse movements
  206. return me != MouseEvent.MouseMove;
  207. default:
  208. throw new ArgumentOutOfRangeException("activationMode");
  209. }
  210. }
  211. #endregion
  212. #region execute command
  213. /// <summary>
  214. /// Executes a given command if its <see cref="ICommand.CanExecute"/> method
  215. /// indicates it can run.
  216. /// </summary>
  217. /// <param name="command">The command to be executed, or a null reference.</param>
  218. /// <param name="commandParameter">An optional parameter that is associated with
  219. /// the command.</param>
  220. /// <param name="target">The target element on which to raise the command.</param>
  221. public static void ExecuteIfEnabled(this ICommand command, object commandParameter, IInputElement target)
  222. {
  223. if (command == null) return;
  224. RoutedCommand rc = command as RoutedCommand;
  225. if (rc != null)
  226. {
  227. //routed commands work on a target
  228. if (rc.CanExecute(commandParameter, target)) rc.Execute(commandParameter, target);
  229. }
  230. else if (command.CanExecute(commandParameter))
  231. {
  232. command.Execute(commandParameter);
  233. }
  234. }
  235. #endregion
  236. /// <summary>
  237. /// Returns a dispatcher for multi-threaded scenarios
  238. /// </summary>
  239. /// <returns>Dispatcher</returns>
  240. internal static Dispatcher GetDispatcher(this DispatcherObject source)
  241. {
  242. //use the application's dispatcher by default
  243. if (Application.Current != null) return Application.Current.Dispatcher;
  244. //fallback for WinForms environments
  245. if (source.Dispatcher != null) return source.Dispatcher;
  246. // ultimately use the thread's dispatcher
  247. return Dispatcher.CurrentDispatcher;
  248. }
  249. /// <summary>
  250. /// Checks whether the <see cref="FrameworkElement.DataContextProperty"/>
  251. /// is bound or not.
  252. /// </summary>
  253. /// <param name="element">The element to be checked.</param>
  254. /// <returns>True if the data context property is being managed by a
  255. /// binding expression.</returns>
  256. /// <exception cref="ArgumentNullException">If <paramref name="element"/>
  257. /// is a null reference.</exception>
  258. public static bool IsDataContextDataBound(this FrameworkElement element)
  259. {
  260. if (element == null) throw new ArgumentNullException("element");
  261. return element.GetBindingExpression(FrameworkElement.DataContextProperty) != null;
  262. }
  263. }
  264. }