NotifyIcon.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
  21. //
  22. // Authors:
  23. // Peter Bartok [email protected]
  24. //
  25. //
  26. // NOT COMPLETE
  27. using System;
  28. using System.ComponentModel;
  29. using System.ComponentModel.Design;
  30. using System.Drawing;
  31. namespace System.Windows.Forms {
  32. [DefaultProperty("Text")]
  33. [DefaultEvent("MouseDown")]
  34. [Designer ("System.Windows.Forms.Design.NotifyIconDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
  35. [ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Allow)]
  36. public sealed class NotifyIcon : System.ComponentModel.Component {
  37. #region Local Variables
  38. private ContextMenu context_menu;
  39. private Icon icon;
  40. private Bitmap icon_bitmap;
  41. private string text;
  42. private bool visible;
  43. private NotifyIconWindow window;
  44. private bool systray_active;
  45. private ToolTip tooltip;
  46. #endregion // Local Variables
  47. #region NotifyIconWindow Class
  48. internal class NotifyIconWindow : Control {
  49. NotifyIcon owner;
  50. Rectangle rect;
  51. public NotifyIconWindow(NotifyIcon owner) {
  52. this.owner = owner;
  53. is_visible = false;
  54. rect = new Rectangle(0, 0, 1, 1);
  55. CreateControl();
  56. Paint += new PaintEventHandler(HandlePaint);
  57. SizeChanged += new EventHandler(HandleSizeChanged);
  58. // Events that need to be sent to our parent
  59. Click += new EventHandler(HandleClick);
  60. DoubleClick += new EventHandler(HandleDoubleClick);
  61. MouseDown +=new MouseEventHandler(HandleMouseDown);
  62. MouseUp +=new MouseEventHandler(HandleMouseUp);
  63. MouseMove +=new MouseEventHandler(HandleMouseMove);
  64. ContextMenu = owner.context_menu;
  65. }
  66. protected override CreateParams CreateParams {
  67. get {
  68. CreateParams cp;
  69. cp = base.CreateParams;
  70. cp.Parent = IntPtr.Zero;
  71. cp.Style = (int)WindowStyles.WS_POPUP;
  72. cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS;
  73. cp.ExStyle = (int)(WindowExStyles.WS_EX_TOOLWINDOW);
  74. return cp;
  75. }
  76. }
  77. protected override void WndProc(ref Message m) {
  78. switch((Msg)m.Msg) {
  79. case Msg.WM_NCPAINT: {
  80. PaintEventArgs paint_event;
  81. paint_event = XplatUI.PaintEventStart(Handle, false);
  82. OnPaint(paint_event);
  83. XplatUI.PaintEventEnd(Handle, false);
  84. break;
  85. }
  86. case Msg.WM_USER: {
  87. switch ((Msg)m.LParam.ToInt32()) {
  88. case Msg.WM_LBUTTONDOWN: {
  89. HandleMouseDown(this, new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  90. return;
  91. }
  92. case Msg.WM_LBUTTONUP: {
  93. HandleMouseUp(this, new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  94. HandleClick(this, EventArgs.Empty);
  95. return;
  96. }
  97. case Msg.WM_LBUTTONDBLCLK: {
  98. HandleDoubleClick(this, EventArgs.Empty);
  99. return;
  100. }
  101. case Msg.WM_MOUSEMOVE: {
  102. HandleMouseMove(this, new MouseEventArgs(MouseButtons.None, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  103. return;
  104. }
  105. case Msg.WM_RBUTTONDOWN: {
  106. HandleMouseDown(this, new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  107. return;
  108. }
  109. case Msg.WM_RBUTTONUP: {
  110. HandleMouseUp(this, new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  111. HandleClick(this, EventArgs.Empty);
  112. return;
  113. }
  114. case Msg.WM_RBUTTONDBLCLK: {
  115. HandleDoubleClick(this, EventArgs.Empty);
  116. return;
  117. }
  118. }
  119. return;
  120. }
  121. }
  122. base.WndProc (ref m);
  123. }
  124. internal void CalculateIconRect() {
  125. if (owner != null && owner.icon != null) {
  126. int x;
  127. int y;
  128. int size;
  129. // Icons are always square. Try to center them in the window
  130. if (ClientRectangle.Width < ClientRectangle.Height) {
  131. size = ClientRectangle.Width;
  132. } else {
  133. size = ClientRectangle.Height;
  134. }
  135. x = this.ClientRectangle.Width / 2 - size / 2;
  136. y = this.ClientRectangle.Height / 2 - size / 2;
  137. rect = new Rectangle(x, y, size, size);
  138. // Force our window to be square
  139. if (Width != size) {
  140. this.Width = size;
  141. }
  142. if (Height != size) {
  143. this.Height = size;
  144. }
  145. }
  146. }
  147. private void HandlePaint(object sender, PaintEventArgs e) {
  148. if (owner.icon != null) {
  149. e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(SystemColors.Window), rect);
  150. e.Graphics.DrawImage(owner.icon_bitmap, rect);
  151. }
  152. }
  153. private void HandleSizeChanged(object sender, EventArgs e) {
  154. CalculateIconRect();
  155. }
  156. private void HandleClick(object sender, EventArgs e) {
  157. if (owner.Click != null) {
  158. owner.Click(owner, e);
  159. }
  160. }
  161. private void HandleDoubleClick(object sender, EventArgs e) {
  162. if (owner.DoubleClick != null) {
  163. owner.DoubleClick(owner, e);
  164. }
  165. }
  166. private void HandleMouseDown(object sender, MouseEventArgs e) {
  167. if (owner.MouseDown != null) {
  168. owner.MouseDown(owner, e);
  169. }
  170. }
  171. private void HandleMouseUp(object sender, MouseEventArgs e) {
  172. if (owner.context_menu != null) {
  173. owner.context_menu.Show(this, new Point(e.X, e.Y));
  174. }
  175. if (owner.MouseUp != null) {
  176. owner.MouseUp(owner, e);
  177. }
  178. }
  179. private void HandleMouseMove(object sender, MouseEventArgs e) {
  180. if (owner.MouseMove != null) {
  181. owner.MouseMove(owner, e);
  182. }
  183. }
  184. }
  185. #endregion // NotifyIconWindow Class
  186. #region Public Constructors
  187. public NotifyIcon() {
  188. window = new NotifyIconWindow(this);
  189. systray_active = false;
  190. }
  191. public NotifyIcon(System.ComponentModel.IContainer container) : this() {
  192. }
  193. #endregion // Public Constructors
  194. #region Private Methods
  195. private void ShowSystray(bool property_changed) {
  196. if (property_changed) {
  197. window.CalculateIconRect();
  198. }
  199. if (systray_active) {
  200. if (property_changed) {
  201. UpdateSystray();
  202. }
  203. return;
  204. }
  205. if (icon == null) {
  206. return;
  207. }
  208. icon_bitmap = icon.ToBitmap();
  209. systray_active = true;
  210. XplatUI.SystrayAdd(window.Handle, text, icon, out tooltip);
  211. }
  212. private void HideSystray() {
  213. if (!systray_active) {
  214. return;
  215. }
  216. systray_active = false;
  217. XplatUI.SystrayRemove(window.Handle, ref tooltip);
  218. }
  219. private void UpdateSystray() {
  220. if (icon_bitmap != null) {
  221. icon_bitmap.Dispose();
  222. }
  223. if (icon != null) {
  224. icon_bitmap = icon.ToBitmap();
  225. }
  226. XplatUI.SystrayChange(window.Handle, text, icon, ref tooltip);
  227. window.Invalidate();
  228. }
  229. #endregion // Private Methods
  230. #region Public Instance Properties
  231. [DefaultValue(null)]
  232. public ContextMenu ContextMenu {
  233. get {
  234. return context_menu;
  235. }
  236. set {
  237. if (context_menu != value) {
  238. context_menu = value;
  239. window.ContextMenu = value;
  240. }
  241. }
  242. }
  243. [Localizable(true)]
  244. [DefaultValue(null)]
  245. public Icon Icon {
  246. get {
  247. return icon;
  248. }
  249. set {
  250. if (icon != value) {
  251. icon = value;
  252. ShowSystray(true);
  253. }
  254. }
  255. }
  256. [Localizable(true)]
  257. public string Text {
  258. get {
  259. return text;
  260. }
  261. set {
  262. if (text != value) {
  263. if (value.Length >= 64) {
  264. throw new ArgumentException("ToolTip length must be less than 64 characters long", "Text");
  265. }
  266. text = value;
  267. if (text == string.Empty && icon == null) {
  268. HideSystray();
  269. } else {
  270. ShowSystray(true);
  271. }
  272. }
  273. }
  274. }
  275. [Localizable(true)]
  276. [DefaultValue(false)]
  277. public bool Visible {
  278. get {
  279. return visible;
  280. }
  281. set {
  282. if (visible != value) {
  283. visible = value;
  284. // Let our control know, too
  285. window.is_visible = value;
  286. if (visible) {
  287. ShowSystray(false);
  288. } else {
  289. HideSystray();
  290. }
  291. }
  292. }
  293. }
  294. #endregion // Public Instance Properties
  295. #region Protected Instance Methods
  296. protected override void Dispose(bool disposing) {
  297. if (icon_bitmap != null) {
  298. icon_bitmap.Dispose();
  299. }
  300. if (disposing)
  301. icon = null;
  302. base.Dispose (disposing);
  303. }
  304. #endregion // Protected Instance Methods
  305. #region Events
  306. [Category("Action")]
  307. public event EventHandler Click;
  308. [Category("Action")]
  309. public event EventHandler DoubleClick;
  310. public event MouseEventHandler MouseDown;
  311. public event MouseEventHandler MouseMove;
  312. public event MouseEventHandler MouseUp;
  313. #endregion // Events
  314. }
  315. }