- NotifyIcon improvements
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / NotifyIcon.cs
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    pbartok@novell.com
24 //
25 //
26
27 // NOT COMPLETE
28
29 using System;
30 using System.Drawing;
31
32 namespace System.Windows.Forms {
33         public sealed class NotifyIcon : System.ComponentModel.Component {
34                 #region Local Variables
35                 private ContextMenu             context_menu;
36                 private Icon                    icon;
37                 private Bitmap                  icon_bitmap;
38                 private string                  text;
39                 private bool                    visible;
40                 private NotifyIconWindow        window;
41                 private bool                    systray_active;
42                 private ToolTip                 tooltip;
43                 #endregion      // Local Variables
44
45                 #region NotifyIconWindow Class
46                 internal class NotifyIconWindow : Control {
47                         NotifyIcon      owner;
48                         Rectangle       rect;
49
50                         public NotifyIconWindow(NotifyIcon owner) {
51                                 this.owner = owner;
52                                 is_visible = false;
53                                 rect = new Rectangle(0, 0, 1, 1);
54
55                                 CreateControl();
56
57                                 Paint += new PaintEventHandler(HandlePaint);
58                                 SizeChanged += new EventHandler(HandleSizeChanged);
59
60                                 // Events that need to be sent to our parent
61                                 Click += new EventHandler(HandleClick);
62                                 DoubleClick += new EventHandler(HandleDoubleClick);
63                                 MouseDown +=new MouseEventHandler(HandleMouseDown);
64                                 MouseUp +=new MouseEventHandler(HandleMouseUp);
65                                 MouseMove +=new MouseEventHandler(HandleMouseMove);
66                                 ContextMenu = owner.context_menu;
67                         }\r
68 \r
69                         protected override CreateParams CreateParams {\r
70                                 get {\r
71                                         CreateParams cp;\r
72 \r
73                                         cp = base.CreateParams;\r
74 \r
75                                         cp.Parent = IntPtr.Zero;\r
76                                         cp.Style = (int)WindowStyles.WS_POPUP;\r
77                                         cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS;\r
78 \r
79                                         cp.ExStyle = (int)(WindowStyles.WS_EX_TOOLWINDOW);
80 \r
81                                         return cp;\r
82                                 }\r
83                         }\r
84 \r
85                         protected override void WndProc(ref Message m) {\r
86                                 switch((Msg)m.Msg) {\r
87                                         case Msg.WM_USER: {\r
88                                                 switch ((Msg)m.LParam.ToInt32()) {\r
89                                                         case Msg.WM_LBUTTONDOWN: {\r
90                                                                 HandleMouseDown(this, new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));\r
91                                                                 return;\r
92                                                         }\r
93 \r
94                                                         case Msg.WM_LBUTTONUP: {\r
95                                                                 HandleMouseUp(this, new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));\r
96                                                                 HandleClick(this, EventArgs.Empty);\r
97                                                                 return;\r
98                                                         }\r
99 \r
100                                                         case Msg.WM_LBUTTONDBLCLK: {\r
101                                                                 HandleDoubleClick(this, EventArgs.Empty);\r
102                                                                 return;\r
103                                                         }\r
104 \r
105                                                         case Msg.WM_MOUSEMOVE: {\r
106                                                                 HandleMouseMove(this, new MouseEventArgs(MouseButtons.None, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));\r
107                                                                 return;\r
108                                                         }\r
109 \r
110                                                         case Msg.WM_RBUTTONDOWN: {\r
111                                                                 HandleMouseDown(this, new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));\r
112                                                                 return;\r
113                                                         }\r
114 \r
115                                                         case Msg.WM_RBUTTONUP: {\r
116                                                                 HandleMouseUp(this, new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));\r
117                                                                 HandleClick(this, EventArgs.Empty);\r
118                                                                 return;\r
119                                                         }\r
120 \r
121                                                         case Msg.WM_RBUTTONDBLCLK: {\r
122                                                                 HandleDoubleClick(this, EventArgs.Empty);\r
123                                                                 return;\r
124                                                         }\r
125                                                 }\r
126                                                 return;\r
127                                         }\r
128                                 }\r
129                                 base.WndProc (ref m);\r
130                         }\r
131 \r
132                         internal void CalculateIconRect() {\r
133                                 if (owner != null && owner.icon != null) {\r
134                                         int             x;
135                                         int             y;
136                                         int             size;\r
137 \r
138 Console.WriteLine("CalculateIconRect: Width:{0}, Height:{1}", Width, Height);\r
139 \r
140                                         // Icons are always square. Try to center them in the window\r
141                                         if (ClientRectangle.Width < ClientRectangle.Height) {\r
142                                                 size = ClientRectangle.Width;\r
143                                         } else {\r
144                                                 size = ClientRectangle.Height;\r
145                                         }\r
146                                         x = this.ClientRectangle.Width / 2 - size / 2;\r
147                                         y = this.ClientRectangle.Height / 2 - size / 2;\r
148                                         rect = new Rectangle(x, y, size, size);\r
149 \r
150                                         // Force our window to be square\r
151                                         this.Width = size;\r
152                                         this.Height = size;\r
153                                 }\r
154                         }\r
155 \r
156                         private void HandlePaint(object sender, PaintEventArgs e) {\r
157                                 if (owner.icon != null) {\r
158                                         e.Graphics.DrawImage(owner.icon_bitmap, rect);\r
159 \r
160                                 }\r
161                         }\r
162 \r
163                         private void HandleSizeChanged(object sender, EventArgs e) {\r
164                                 CalculateIconRect();\r
165                         }\r
166 \r
167                         private void HandleClick(object sender, EventArgs e) {\r
168                                 if (owner.Click != null) {\r
169                                         owner.Click(owner, e);\r
170                                 }\r
171                         }\r
172 \r
173                         private void HandleDoubleClick(object sender, EventArgs e) {\r
174                                 if (owner.DoubleClick != null) {\r
175                                         owner.DoubleClick(owner, e);\r
176                                 }\r
177                         }\r
178 \r
179                         private void HandleMouseDown(object sender, MouseEventArgs e) {\r
180                                 if (owner.MouseDown != null) {\r
181                                         owner.MouseDown(owner, e);\r
182                                 }\r
183                         }\r
184
185                         private void HandleMouseUp(object sender, MouseEventArgs e) {\r
186                                 if (owner.context_menu != null) {\r
187                                         owner.context_menu.Show(this, new Point(e.X, e.Y));\r
188                                 }\r
189 \r
190                                 if (owner.MouseUp != null) {\r
191                                         owner.MouseUp(owner, e);\r
192                                 }\r
193                         }\r
194 \r
195                         private void HandleMouseMove(object sender, MouseEventArgs e) {\r
196                                 if (owner.MouseMove != null) {\r
197                                         owner.MouseMove(owner, e);\r
198                                 }\r
199                         }\r
200                 }
201                 #endregion      // NotifyIconWindow Class
202
203                 #region Public Constructors
204                 public NotifyIcon() {
205                         window = new NotifyIconWindow(this);
206                         systray_active = false;
207                 }
208
209                 public NotifyIcon(System.ComponentModel.IContainer container) : this() {
210                 }
211                 #endregion      // Public Constructors
212
213                 #region Private Methods
214                 private void ShowSystray(bool property_changed) {
215                         if (property_changed) {
216                                 window.CalculateIconRect();
217                         }
218
219                         if (systray_active) {
220                                 if (property_changed) {
221                                         UpdateSystray();
222                                 }
223                                 return;
224                         }
225
226                         if (icon != null) {
227                                 icon_bitmap = icon.ToBitmap();
228                         }
229
230                         systray_active = true;
231                         XplatUI.SystrayAdd(window.Handle, text, icon, out tooltip);
232                 }
233
234                 private void HideSystray() {
235                         if (!systray_active) {
236                                 return;
237                         }
238
239                         systray_active = false;
240                         XplatUI.SystrayRemove(window.Handle, ref tooltip);
241                 }
242
243                 private void UpdateSystray() {
244                         if (icon_bitmap != null) {
245                                 icon_bitmap.Dispose();
246                         }
247
248                         if (icon != null) {
249                                 icon_bitmap = icon.ToBitmap();
250                         }
251
252                         XplatUI.SystrayChange(window.Handle, text, icon, ref tooltip);
253                         window.Invalidate();
254                 }
255                 #endregion      // Private Methods
256
257                 #region Public Instance Properties
258                 public ContextMenu ContextMenu {
259                         get {
260                                 return context_menu;
261                         }
262
263                         set {
264                                 if (context_menu != value) {
265                                         context_menu = value;
266                                         window.ContextMenu = value;
267                                 }
268                         }
269                 }
270
271                 public Icon Icon {
272                         get {
273                                 return icon;
274                         }
275
276                         set {
277                                 if (icon != value) {
278                                         if (icon != null) {
279                                                 icon.Dispose();
280                                         }
281                                         icon = value;
282                                         ShowSystray(true);
283                                 }
284                         }
285                 }
286
287                 public string Text {
288                         get {
289                                 return text;
290                         }
291
292                         set {
293                                 if (text != value) {
294                                         if (value.Length >= 64) {
295                                                 throw new ArgumentException("ToolTip length must be less than 64 characters long", "Text");
296                                         }
297                                         text = value;
298                                         if (text == string.Empty && icon == null) {
299                                                 HideSystray();
300                                         } else {
301                                                 ShowSystray(true);
302                                         }
303                                 }
304                         }
305                 }
306
307                 public bool Visible {
308                         get {
309                                 return visible;
310                         }
311
312                         set {
313                                 if (visible != value) {
314                                         visible = value;
315
316                                         // Let our control know, too
317                                         window.is_visible = value;
318
319                                         if (visible) {
320                                                 ShowSystray(false);
321                                         } else {
322                                                 HideSystray();
323                                         }
324                                 }
325                         }
326                 }
327                 #endregion      // Public Instance Properties
328
329                 #region Protected Instance Methods
330                 protected override void Dispose(bool disposing) {\r
331                         if (icon != null) {\r
332                                 icon.Dispose();\r
333                         }\r
334 \r
335                         if (icon_bitmap != null) {\r
336                                 icon_bitmap.Dispose();\r
337                         }\r
338                         base.Dispose (disposing);\r
339                 }\r
340
341                 #endregion      // Protected Instance Methods
342
343                 #region Events
344                 public event EventHandler       Click;
345                 public event EventHandler       DoubleClick;
346                 public event MouseEventHandler  MouseDown;
347                 public event MouseEventHandler  MouseMove;
348                 public event MouseEventHandler  MouseUp;
349                 #endregion      // Events
350         }
351 }