// Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // Copyright (c) 2005 Novell, Inc. (http://www.novell.com) // // Authors: // Peter Bartok pbartok@novell.com // // // NOT COMPLETE using System; using System.ComponentModel; using System.ComponentModel.Design; using System.Drawing; namespace System.Windows.Forms { [DefaultProperty("Text")] [DefaultEvent("MouseDown")] [Designer ("System.Windows.Forms.Design.NotifyIconDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] [ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Allow)] public sealed class NotifyIcon : System.ComponentModel.Component { #region Local Variables private ContextMenu context_menu; private Icon icon; private Bitmap icon_bitmap; private string text; private bool visible; private NotifyIconWindow window; private bool systray_active; private ToolTip tooltip; #endregion // Local Variables #region NotifyIconWindow Class internal class NotifyIconWindow : Form { NotifyIcon owner; Rectangle rect; public NotifyIconWindow(NotifyIcon owner) { this.owner = owner; is_visible = false; rect = new Rectangle(0, 0, 1, 1); CreateControl(); SizeChanged += new EventHandler(HandleSizeChanged); // Events that need to be sent to our parent Click += new EventHandler(HandleClick); DoubleClick += new EventHandler(HandleDoubleClick); MouseDown +=new MouseEventHandler(HandleMouseDown); MouseUp +=new MouseEventHandler(HandleMouseUp); MouseMove +=new MouseEventHandler(HandleMouseMove); ContextMenu = owner.context_menu; } protected override CreateParams CreateParams { get { CreateParams cp; cp = base.CreateParams; cp.Parent = IntPtr.Zero; cp.Style = (int)WindowStyles.WS_POPUP; cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS; cp.ExStyle = (int)(WindowExStyles.WS_EX_TOOLWINDOW); return cp; } } protected override void WndProc(ref Message m) { switch((Msg)m.Msg) { case Msg.WM_NCPAINT: { PaintEventArgs paint_event; paint_event = XplatUI.PaintEventStart(Handle, false); OnPaintInternal (paint_event); XplatUI.PaintEventEnd(Handle, false); break; } // // NotifyIcon does CONTEXTMENU on mouse up, not down // so we swallow the message here, and handle it on our own // case Msg.WM_CONTEXTMENU: return; case Msg.WM_USER: { switch ((Msg)m.LParam.ToInt32()) { case Msg.WM_LBUTTONDOWN: { HandleMouseDown(this, new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0)); return; } case Msg.WM_LBUTTONUP: { HandleMouseUp(this, new MouseEventArgs(MouseButtons.Left, 1, Control.MousePosition.X, Control.MousePosition.Y, 0)); HandleClick(this, EventArgs.Empty); return; } case Msg.WM_LBUTTONDBLCLK: { HandleDoubleClick(this, EventArgs.Empty); return; } case Msg.WM_MOUSEMOVE: { HandleMouseMove(this, new MouseEventArgs(MouseButtons.None, 1, Control.MousePosition.X, Control.MousePosition.Y, 0)); return; } case Msg.WM_RBUTTONDOWN: { HandleMouseDown(this, new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0)); return; } case Msg.WM_RBUTTONUP: { HandleMouseUp(this, new MouseEventArgs(MouseButtons.Right, 1, Control.MousePosition.X, Control.MousePosition.Y, 0)); HandleClick(this, EventArgs.Empty); return; } case Msg.WM_RBUTTONDBLCLK: { HandleDoubleClick(this, EventArgs.Empty); return; } } return; } } base.WndProc (ref m); } internal void CalculateIconRect() { if (owner != null && owner.icon != null) { int x; int y; int size; // Icons are always square. Try to center them in the window if (ClientRectangle.Width < ClientRectangle.Height) { size = ClientRectangle.Width; } else { size = ClientRectangle.Height; } x = this.ClientRectangle.Width / 2 - size / 2; y = this.ClientRectangle.Height / 2 - size / 2; rect = new Rectangle(x, y, size, size); // Force our window to be square if (Width != size) { this.Width = size; } if (Height != size) { this.Height = size; } } } internal override void OnPaintInternal (PaintEventArgs e) { if (owner.icon != null) { e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(SystemColors.Window), rect); e.Graphics.DrawImage(owner.icon_bitmap, rect); } } internal void InternalRecreateHandle () { base.RecreateHandle (); } private void HandleSizeChanged(object sender, EventArgs e) { CalculateIconRect(); } private void HandleClick(object sender, EventArgs e) { if (owner.Click != null) { owner.Click(owner, e); } } private void HandleDoubleClick(object sender, EventArgs e) { if (owner.DoubleClick != null) { owner.DoubleClick(owner, e); } } private void HandleMouseDown(object sender, MouseEventArgs e) { if (owner.MouseDown != null) { owner.MouseDown(owner, e); } } private void HandleMouseUp(object sender, MouseEventArgs e) { if (owner.context_menu != null) { owner.context_menu.Show(this, new Point(e.X, e.Y)); } if (owner.MouseUp != null) { owner.MouseUp(owner, e); } } private void HandleMouseMove(object sender, MouseEventArgs e) { if (owner.MouseMove != null) { owner.MouseMove(owner, e); } } } #endregion // NotifyIconWindow Class #region Public Constructors public NotifyIcon() { window = new NotifyIconWindow(this); systray_active = false; } public NotifyIcon(System.ComponentModel.IContainer container) : this() { } #endregion // Public Constructors #region Private Methods private void ShowSystray(bool property_changed) { if (property_changed) { window.CalculateIconRect(); } if (systray_active) { if (property_changed) { UpdateSystray(); } return; } if (icon == null) { return; } icon_bitmap = icon.ToBitmap(); systray_active = true; XplatUI.SystrayAdd(window.Handle, text, icon, out tooltip); } private void HideSystray() { if (!systray_active) { return; } systray_active = false; XplatUI.SystrayRemove(window.Handle, ref tooltip); } private void UpdateSystray() { if (icon_bitmap != null) { icon_bitmap.Dispose(); } if (icon != null) { icon_bitmap = icon.ToBitmap(); } XplatUI.SystrayChange(window.Handle, text, icon, ref tooltip); window.Invalidate(); } #endregion // Private Methods #region Public Instance Properties [DefaultValue(null)] public ContextMenu ContextMenu { get { return context_menu; } set { if (context_menu != value) { context_menu = value; window.ContextMenu = value; } } } [Localizable(true)] [DefaultValue(null)] public Icon Icon { get { return icon; } set { if (icon != value) { icon = value; ShowSystray(true); } } } [Localizable(true)] public string Text { get { return text; } set { if (text != value) { if (value.Length >= 64) { throw new ArgumentException("ToolTip length must be less than 64 characters long", "Text"); } text = value; if (text == string.Empty && icon == null) { HideSystray(); } else { ShowSystray(true); } } } } [Localizable(true)] [DefaultValue(false)] public bool Visible { get { return visible; } set { if (visible != value) { visible = value; // Let our control know, too window.is_visible = value; if (visible) { ShowSystray(false); } else { HideSystray(); } } } } #endregion // Public Instance Properties #region Protected Instance Methods protected override void Dispose(bool disposing) { if (icon_bitmap != null) { icon_bitmap.Dispose(); } if (disposing) icon = null; base.Dispose (disposing); } #endregion // Protected Instance Methods #region Events [Category("Action")] public event EventHandler Click; [Category("Action")] public event EventHandler DoubleClick; public event MouseEventHandler MouseDown; public event MouseEventHandler MouseMove; public event MouseEventHandler MouseUp; #endregion // Events } }