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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
23 // Peter Bartok pbartok@novell.com
30 using System.ComponentModel;
31 using System.ComponentModel.Design;
34 namespace System.Windows.Forms {
35 [DefaultProperty("Text")]
37 [DefaultEvent("MouseDoubleClick")]
39 [DefaultEvent("MouseDown")]
41 [Designer ("System.Windows.Forms.Design.NotifyIconDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
42 [ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Allow)]
43 public sealed class NotifyIcon : Component {
44 #region Local Variables
45 private ContextMenu context_menu;
47 private Bitmap icon_bitmap;
50 private NotifyIconWindow window;
51 private bool systray_active;
52 private ToolTip tooltip;
53 #endregion // Local Variables
55 #region NotifyIconWindow Class
56 internal class NotifyIconWindow : Form {
60 public NotifyIconWindow(NotifyIcon owner) {
63 rect = new Rectangle(0, 0, 1, 1);
65 FormBorderStyle = FormBorderStyle.None;
69 SizeChanged += new EventHandler(HandleSizeChanged);
71 // Events that need to be sent to our parent
72 Click += new EventHandler(HandleClick);
73 DoubleClick += new EventHandler(HandleDoubleClick);
74 MouseDown +=new MouseEventHandler(HandleMouseDown);
75 MouseUp +=new MouseEventHandler(HandleMouseUp);
76 MouseMove +=new MouseEventHandler(HandleMouseMove);
77 ContextMenu = owner.context_menu;
80 protected override CreateParams CreateParams {
84 cp = base.CreateParams;
86 cp.Parent = IntPtr.Zero;
87 cp.Style = (int)WindowStyles.WS_POPUP;
88 cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS;
90 cp.ExStyle = (int)(WindowExStyles.WS_EX_TOOLWINDOW);
96 protected override void WndProc(ref Message m) {
99 // NotifyIcon does CONTEXTMENU on mouse up, not down
100 // so we swallow the message here, and handle it on our own
102 case Msg.WM_CONTEXTMENU:
106 switch ((Msg)m.LParam.ToInt32()) {
107 case Msg.WM_LBUTTONDOWN: {
108 owner.OnMouseDown (new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
112 case Msg.WM_LBUTTONUP: {
113 owner.OnMouseUp (new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
114 owner.OnClick (EventArgs.Empty);
118 case Msg.WM_LBUTTONDBLCLK: {
119 owner.OnDoubleClick (EventArgs.Empty);
123 case Msg.WM_MOUSEMOVE: {
124 owner.OnMouseMove (new MouseEventArgs(MouseButtons.None, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
128 case Msg.WM_RBUTTONDOWN: {
129 owner.OnMouseDown (new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
133 case Msg.WM_RBUTTONUP: {
134 owner.OnMouseUp (new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0));
135 owner.OnClick (EventArgs.Empty);
139 case Msg.WM_RBUTTONDBLCLK: {
140 owner.OnDoubleClick (EventArgs.Empty);
147 base.WndProc (ref m);
150 internal void CalculateIconRect() {
155 // Icons are always square. Try to center them in the window
156 if (ClientRectangle.Width < ClientRectangle.Height) {
157 size = ClientRectangle.Width;
159 size = ClientRectangle.Height;
161 x = this.ClientRectangle.Width / 2 - size / 2;
162 y = this.ClientRectangle.Height / 2 - size / 2;
163 rect = new Rectangle(x, y, size, size);
165 Bounds = new Rectangle (0, 0, size, size);
168 internal override void OnPaintInternal (PaintEventArgs e) {
169 if (owner.icon != null) {
170 e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(SystemColors.Window), rect);
171 e.Graphics.DrawImage(owner.icon_bitmap,
173 new Rectangle (0, 0, owner.icon_bitmap.Width, owner.icon_bitmap.Height),
179 internal void InternalRecreateHandle () {
180 base.RecreateHandle ();
184 private void HandleSizeChanged(object sender, EventArgs e) {
185 owner.Recalculate ();
188 private void HandleClick (object sender, EventArgs e)
193 private void HandleDoubleClick (object sender, EventArgs e)
195 owner.OnDoubleClick (e);
198 private void HandleMouseDown (object sender, MouseEventArgs e)
200 owner.OnMouseDown (e);
203 private void HandleMouseUp (object sender, MouseEventArgs e)
208 private void HandleMouseMove (object sender, MouseEventArgs e)
210 owner.OnMouseMove (e);
213 #endregion // NotifyIconWindow Class
215 #region Public Constructors
216 public NotifyIcon() {
217 window = new NotifyIconWindow(this);
218 systray_active = false;
221 public NotifyIcon(System.ComponentModel.IContainer container) : this() {
223 #endregion // Public Constructors
225 #region Private Methods
226 private void OnClick (EventArgs e)
228 EventHandler eh = (EventHandler)(Events [ClickEvent]);
233 private void OnDoubleClick (EventArgs e)
235 EventHandler eh = (EventHandler)(Events [DoubleClickEvent]);
240 private void OnMouseDown (MouseEventArgs e)
242 MouseEventHandler eh = (MouseEventHandler)(Events [MouseDownEvent]);
247 private void OnMouseUp (MouseEventArgs e)
249 if ((e.Button & MouseButtons.Right) == MouseButtons.Right && context_menu != null)
250 context_menu.Show (window, new Point(e.X, e.Y));
252 MouseEventHandler eh = (MouseEventHandler)(Events [MouseUpEvent]);
257 private void OnMouseMove (MouseEventArgs e)
259 MouseEventHandler eh = (MouseEventHandler)(Events [MouseMoveEvent]);
264 private void Recalculate ()
266 window.CalculateIconRect ();
272 private void ShowSystray()
274 systray_active = true;
279 icon_bitmap = icon.ToBitmap();
281 XplatUI.SystrayAdd(window.Handle, text, icon, out tooltip);
284 private void HideSystray()
286 if (!systray_active) {
290 systray_active = false;
291 XplatUI.SystrayRemove(window.Handle, ref tooltip);
294 private void UpdateSystray()
296 if (icon_bitmap != null) {
297 icon_bitmap.Dispose();
301 icon_bitmap = icon.ToBitmap();
304 XplatUI.SystrayChange(window.Handle, text, icon, ref tooltip);
307 #endregion // Private Methods
309 #region Public Instance Properties
314 public ContextMenu ContextMenu {
320 if (context_menu != value) {
321 context_menu = value;
322 window.ContextMenu = value;
337 if (text == string.Empty && icon == null) {
349 [Editor ("System.ComponentModel.Design.MultilineStringEditor, " + Consts.AssemblySystem_Design,
350 typeof (System.Drawing.Design.UITypeEditor))]
360 if (value.Length >= 64) {
361 throw new ArgumentException("ToolTip length must be less than 64 characters long", "Text");
364 if (text == string.Empty && icon == null) {
374 [DefaultValue(false)]
375 public bool Visible {
381 if (visible != value) {
384 // Let our control know, too
385 window.is_visible = value;
395 #endregion // Public Instance Properties
397 #region Protected Instance Methods
398 protected override void Dispose(bool disposing) {
399 if (icon_bitmap != null) {
400 icon_bitmap.Dispose();
406 base.Dispose (disposing);
409 #endregion // Protected Instance Methods
412 static object ClickEvent = new object ();
413 static object DoubleClickEvent = new object ();
414 static object MouseDownEvent = new object ();
415 static object MouseMoveEvent = new object ();
416 static object MouseUpEvent = new object ();
419 [MWFCategory("Action")]
423 public event EventHandler Click {
424 add { Events.AddHandler (ClickEvent, value); }
425 remove { Events.RemoveHandler (ClickEvent, value); }
429 [MWFCategory("Action")]
433 public event EventHandler DoubleClick {
434 add { Events.AddHandler (DoubleClickEvent, value); }
435 remove { Events.RemoveHandler (DoubleClickEvent, value); }
438 public event MouseEventHandler MouseDown {
439 add { Events.AddHandler (MouseDownEvent, value); }
440 remove { Events.RemoveHandler (MouseDownEvent, value); }
443 public event MouseEventHandler MouseMove {
444 add { Events.AddHandler (MouseMoveEvent, value); }
445 remove { Events.RemoveHandler (MouseMoveEvent, value); }
448 public event MouseEventHandler MouseUp {
449 add { Events.AddHandler (MouseUpEvent, value); }
450 remove { Events.RemoveHandler (MouseUpEvent, value); }