NotifyIcon.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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, typeof (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)(WindowStyles.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_USER: {
  80. switch ((Msg)m.LParam.ToInt32()) {
  81. case Msg.WM_LBUTTONDOWN: {
  82. HandleMouseDown(this, new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  83. return;
  84. }
  85. case Msg.WM_LBUTTONUP: {
  86. HandleMouseUp(this, new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  87. HandleClick(this, EventArgs.Empty);
  88. return;
  89. }
  90. case Msg.WM_LBUTTONDBLCLK: {
  91. HandleDoubleClick(this, EventArgs.Empty);
  92. return;
  93. }
  94. case Msg.WM_MOUSEMOVE: {
  95. HandleMouseMove(this, new MouseEventArgs(MouseButtons.None, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  96. return;
  97. }
  98. case Msg.WM_RBUTTONDOWN: {
  99. HandleMouseDown(this, new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  100. return;
  101. }
  102. case Msg.WM_RBUTTONUP: {
  103. HandleMouseUp(this, new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
  104. HandleClick(this, EventArgs.Empty);
  105. return;
  106. }
  107. case Msg.WM_RBUTTONDBLCLK: {
  108. HandleDoubleClick(this, EventArgs.Empty);
  109. return;
  110. }
  111. }
  112. return;
  113. }
  114. }
  115. base.WndProc (ref m);
  116. }
  117. internal void CalculateIconRect() {
  118. if (owner != null && owner.icon != null) {
  119. int x;
  120. int y;
  121. int size;
  122. // Icons are always square. Try to center them in the window
  123. if (ClientRectangle.Width < ClientRectangle.Height) {
  124. size = ClientRectangle.Width;
  125. } else {
  126. size = ClientRectangle.Height;
  127. }
  128. x = this.ClientRectangle.Width / 2 - size / 2;
  129. y = this.ClientRectangle.Height / 2 - size / 2;
  130. rect = new Rectangle(x, y, size, size);
  131. // Force our window to be square
  132. if (Width != size) {
  133. this.Width = size;
  134. }
  135. if (Height != size) {
  136. this.Height = size;
  137. }
  138. }
  139. }
  140. private void HandlePaint(object sender, PaintEventArgs e) {
  141. if (owner.icon != null) {
  142. e.Graphics.DrawImage(owner.icon_bitmap, rect);
  143. }
  144. }
  145. private void HandleSizeChanged(object sender, EventArgs e) {
  146. CalculateIconRect();
  147. }
  148. private void HandleClick(object sender, EventArgs e) {
  149. if (owner.Click != null) {
  150. owner.Click(owner, e);
  151. }
  152. }
  153. private void HandleDoubleClick(object sender, EventArgs e) {
  154. if (owner.DoubleClick != null) {
  155. owner.DoubleClick(owner, e);
  156. }
  157. }
  158. private void HandleMouseDown(object sender, MouseEventArgs e) {
  159. if (owner.MouseDown != null) {
  160. owner.MouseDown(owner, e);
  161. }
  162. }
  163. private void HandleMouseUp(object sender, MouseEventArgs e) {
  164. if (owner.context_menu != null) {
  165. owner.context_menu.Show(this, new Point(e.X, e.Y));
  166. }
  167. if (owner.MouseUp != null) {
  168. owner.MouseUp(owner, e);
  169. }
  170. }
  171. private void HandleMouseMove(object sender, MouseEventArgs e) {
  172. if (owner.MouseMove != null) {
  173. owner.MouseMove(owner, e);
  174. }
  175. }
  176. }
  177. #endregion // NotifyIconWindow Class
  178. #region Public Constructors
  179. public NotifyIcon() {
  180. window = new NotifyIconWindow(this);
  181. systray_active = false;
  182. }
  183. public NotifyIcon(System.ComponentModel.IContainer container) : this() {
  184. }
  185. #endregion // Public Constructors
  186. #region Private Methods
  187. private void ShowSystray(bool property_changed) {
  188. if (property_changed) {
  189. window.CalculateIconRect();
  190. }
  191. if (systray_active) {
  192. if (property_changed) {
  193. UpdateSystray();
  194. }
  195. return;
  196. }
  197. if (icon != null) {
  198. icon_bitmap = icon.ToBitmap();
  199. }
  200. systray_active = true;
  201. XplatUI.SystrayAdd(window.Handle, text, icon, out tooltip);
  202. }
  203. private void HideSystray() {
  204. if (!systray_active) {
  205. return;
  206. }
  207. systray_active = false;
  208. XplatUI.SystrayRemove(window.Handle, ref tooltip);
  209. }
  210. private void UpdateSystray() {
  211. if (icon_bitmap != null) {
  212. icon_bitmap.Dispose();
  213. }
  214. if (icon != null) {
  215. icon_bitmap = icon.ToBitmap();
  216. }
  217. XplatUI.SystrayChange(window.Handle, text, icon, ref tooltip);
  218. window.Invalidate();
  219. }
  220. #endregion // Private Methods
  221. #region Public Instance Properties
  222. [DefaultValue(null)]
  223. public ContextMenu ContextMenu {
  224. get {
  225. return context_menu;
  226. }
  227. set {
  228. if (context_menu != value) {
  229. context_menu = value;
  230. window.ContextMenu = value;
  231. }
  232. }
  233. }
  234. [Localizable(true)]
  235. [DefaultValue(null)]
  236. public Icon Icon {
  237. get {
  238. return icon;
  239. }
  240. set {
  241. if (icon != value) {
  242. if (icon != null) {
  243. icon.Dispose();
  244. }
  245. icon = value;
  246. ShowSystray(true);
  247. }
  248. }
  249. }
  250. [Localizable(true)]
  251. public string Text {
  252. get {
  253. return text;
  254. }
  255. set {
  256. if (text != value) {
  257. if (value.Length >= 64) {
  258. throw new ArgumentException("ToolTip length must be less than 64 characters long", "Text");
  259. }
  260. text = value;
  261. if (text == string.Empty && icon == null) {
  262. HideSystray();
  263. } else {
  264. ShowSystray(true);
  265. }
  266. }
  267. }
  268. }
  269. [Localizable(true)]
  270. [DefaultValue(false)]
  271. public bool Visible {
  272. get {
  273. return visible;
  274. }
  275. set {
  276. if (visible != value) {
  277. visible = value;
  278. // Let our control know, too
  279. window.is_visible = value;
  280. if (visible) {
  281. ShowSystray(false);
  282. } else {
  283. HideSystray();
  284. }
  285. }
  286. }
  287. }
  288. #endregion // Public Instance Properties
  289. #region Protected Instance Methods
  290. protected override void Dispose(bool disposing) {
  291. if (icon != null) {
  292. icon.Dispose();
  293. }
  294. if (icon_bitmap != null) {
  295. icon_bitmap.Dispose();
  296. }
  297. base.Dispose (disposing);
  298. }
  299. #endregion // Protected Instance Methods
  300. #region Events
  301. [Category]
  302. public event EventHandler Click;
  303. [Category]
  304. public event EventHandler DoubleClick;
  305. public event MouseEventHandler MouseDown;
  306. public event MouseEventHandler MouseMove;
  307. public event MouseEventHandler MouseUp;
  308. #endregion // Events
  309. }
  310. }