moel@363: /* moel@363: moel@363: This Source Code Form is subject to the terms of the Mozilla Public moel@363: License, v. 2.0. If a copy of the MPL was not distributed with this moel@363: file, You can obtain one at http://mozilla.org/MPL/2.0/. moel@363: moel@363: Copyright (C) 2012 Michael Möller moel@363: moel@363: */ moel@363: moel@363: using System; moel@363: using System.ComponentModel; moel@363: using System.Drawing; moel@363: using System.Runtime.InteropServices; moel@363: using System.Reflection; moel@363: using System.Windows.Forms; moel@363: moel@363: namespace OpenHardwareMonitor.GUI { moel@363: moel@371: public class NotifyIconAdv : IDisposable { moel@363: moel@371: private NotifyIcon genericNotifyIcon; moel@371: private NotifyIconWindowsImplementation windowsNotifyIcon; moel@363: moel@371: public NotifyIconAdv() { moel@371: int p = (int)Environment.OSVersion.Platform; moel@371: if ((p == 4) || (p == 128)) { // Unix moel@371: genericNotifyIcon = new NotifyIcon(); moel@371: } else { // Windows moel@371: windowsNotifyIcon = new NotifyIconWindowsImplementation(); moel@371: } moel@371: } moel@363: moel@371: public event EventHandler BalloonTipClicked { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipClicked += value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipClicked += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipClicked -= value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipClicked -= value; moel@371: } moel@371: } moel@371: moel@371: public event EventHandler BalloonTipClosed { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipClosed += value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipClosed += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipClosed -= value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipClosed -= value; moel@371: } moel@371: } moel@371: moel@371: public event EventHandler BalloonTipShown { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipShown += value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipShown += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipShown -= value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipShown -= value; moel@371: } moel@371: } moel@371: moel@371: public event EventHandler Click { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.Click += value; moel@371: else moel@371: windowsNotifyIcon.Click += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.Click -= value; moel@371: else moel@371: windowsNotifyIcon.Click -= value; moel@371: } moel@371: } moel@371: moel@371: public event EventHandler DoubleClick { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.DoubleClick += value; moel@371: else moel@371: windowsNotifyIcon.DoubleClick += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.DoubleClick -= value; moel@371: else moel@371: windowsNotifyIcon.DoubleClick -= value; moel@371: } moel@371: } moel@371: moel@371: public event MouseEventHandler MouseClick { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseClick += value; moel@371: else moel@371: windowsNotifyIcon.MouseClick += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseClick -= value; moel@371: else moel@371: windowsNotifyIcon.MouseClick -= value; moel@371: } moel@371: } moel@371: moel@371: public event MouseEventHandler MouseDoubleClick { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseDoubleClick += value; moel@371: else moel@371: windowsNotifyIcon.MouseDoubleClick += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseDoubleClick -= value; moel@371: else moel@371: windowsNotifyIcon.MouseDoubleClick -= value; moel@371: } moel@371: } moel@371: moel@371: public event MouseEventHandler MouseDown { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseDown += value; moel@371: else moel@371: windowsNotifyIcon.MouseDown += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseDown -= value; moel@371: else moel@371: windowsNotifyIcon.MouseDown -= value; moel@371: } moel@371: } moel@371: moel@371: public event MouseEventHandler MouseMove { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseMove += value; moel@371: else moel@371: windowsNotifyIcon.MouseMove += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseMove -= value; moel@371: else moel@371: windowsNotifyIcon.MouseMove -= value; moel@371: } moel@371: } moel@371: moel@371: public event MouseEventHandler MouseUp { moel@371: add { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseUp += value; moel@371: else moel@371: windowsNotifyIcon.MouseUp += value; moel@371: } moel@371: remove { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.MouseUp -= value; moel@371: else moel@371: windowsNotifyIcon.MouseUp -= value; moel@371: } moel@371: } moel@371: moel@371: public string BalloonTipText { moel@371: get { moel@371: if (genericNotifyIcon != null) moel@371: return genericNotifyIcon.BalloonTipText; moel@371: else moel@371: return windowsNotifyIcon.BalloonTipText; moel@371: } moel@371: set { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipText = value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipText = value; moel@371: } moel@371: } moel@371: moel@371: public ToolTipIcon BalloonTipIcon { moel@371: get { moel@371: if (genericNotifyIcon != null) moel@371: return genericNotifyIcon.BalloonTipIcon; moel@371: else moel@371: return windowsNotifyIcon.BalloonTipIcon; moel@371: } moel@371: set { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipIcon = value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipIcon = value; moel@371: } moel@371: } moel@371: moel@371: public string BalloonTipTitle { moel@371: get { moel@371: if (genericNotifyIcon != null) moel@371: return genericNotifyIcon.BalloonTipTitle; moel@371: else moel@371: return windowsNotifyIcon.BalloonTipTitle; moel@371: } moel@371: set { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.BalloonTipTitle = value; moel@371: else moel@371: windowsNotifyIcon.BalloonTipTitle = value; moel@371: } moel@371: } moel@371: moel@371: public ContextMenu ContextMenu { moel@371: get { moel@371: if (genericNotifyIcon != null) moel@371: return genericNotifyIcon.ContextMenu; moel@371: else moel@371: return windowsNotifyIcon.ContextMenu; moel@371: } moel@371: set { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.ContextMenu = value; moel@371: else moel@371: windowsNotifyIcon.ContextMenu = value; moel@371: } moel@371: } moel@371: moel@371: public ContextMenuStrip ContextMenuStrip { moel@371: get { moel@371: if (genericNotifyIcon != null) moel@371: return genericNotifyIcon.ContextMenuStrip; moel@371: else moel@371: return windowsNotifyIcon.ContextMenuStrip; moel@371: } moel@371: set { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.ContextMenuStrip = value; moel@371: else moel@371: windowsNotifyIcon.ContextMenuStrip = value; moel@371: } moel@371: } moel@371: moel@363: public object Tag { get; set; } moel@363: moel@363: public Icon Icon { moel@363: get { moel@371: if (genericNotifyIcon != null) moel@371: return genericNotifyIcon.Icon; moel@371: else moel@371: return windowsNotifyIcon.Icon; moel@363: } moel@363: set { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.Icon = value; moel@371: else moel@371: windowsNotifyIcon.Icon = value; moel@363: } moel@363: } moel@363: moel@363: public string Text { moel@363: get { moel@371: if (genericNotifyIcon != null) moel@371: return genericNotifyIcon.Text; moel@371: else moel@371: return windowsNotifyIcon.Text; moel@363: } moel@363: set { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.Text = value; moel@371: else moel@371: windowsNotifyIcon.Text = value; moel@363: } moel@363: } moel@363: moel@363: public bool Visible { moel@363: get { moel@371: if (genericNotifyIcon != null) moel@371: return genericNotifyIcon.Visible; moel@371: else moel@371: return windowsNotifyIcon.Visible; moel@363: } moel@363: set { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.Visible = value; moel@371: else moel@371: windowsNotifyIcon.Visible = value; moel@363: } moel@363: } moel@363: moel@371: public void Dispose() { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.Dispose(); moel@371: else moel@371: windowsNotifyIcon.Dispose(); moel@363: } moel@363: moel@363: public void ShowBalloonTip(int timeout) { moel@363: ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon); moel@363: } moel@363: moel@363: public void ShowBalloonTip(int timeout, string tipTitle, string tipText, moel@371: ToolTipIcon tipIcon) { moel@371: if (genericNotifyIcon != null) moel@371: genericNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon); moel@371: else moel@371: windowsNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon); moel@371: } moel@371: moel@371: private class NotifyIconWindowsImplementation : Component { moel@363: moel@371: private static int nextId = 0; moel@363: moel@371: private object syncObj = new object(); moel@371: private Icon icon; moel@371: private string text = ""; moel@371: private int id; moel@371: private bool created; moel@371: private NotifyIconNativeWindow window; moel@371: private bool doubleClickDown; moel@371: private bool visible; moel@371: private MethodInfo commandDispatch; moel@363: moel@371: public event EventHandler BalloonTipClicked; moel@371: public event EventHandler BalloonTipClosed; moel@371: public event EventHandler BalloonTipShown; moel@371: public event EventHandler Click; moel@371: public event EventHandler DoubleClick; moel@371: public event MouseEventHandler MouseClick; moel@371: public event MouseEventHandler MouseDoubleClick; moel@371: public event MouseEventHandler MouseDown; moel@371: public event MouseEventHandler MouseMove; moel@371: public event MouseEventHandler MouseUp; moel@363: moel@371: public string BalloonTipText { get; set; } moel@371: public ToolTipIcon BalloonTipIcon { get; set; } moel@371: public string BalloonTipTitle { get; set; } moel@371: public ContextMenu ContextMenu { get; set; } moel@371: public ContextMenuStrip ContextMenuStrip { get; set; } moel@371: public object Tag { get; set; } moel@363: moel@371: public Icon Icon { moel@371: get { moel@371: return icon; moel@363: } moel@371: set { moel@371: if (icon != value) { moel@371: icon = value; moel@371: UpdateNotifyIcon(visible); moel@363: } moel@363: } moel@363: } moel@363: moel@371: public string Text { moel@371: get { moel@371: return text; moel@371: } moel@371: set { moel@371: if (value == null) moel@371: value = ""; moel@363: moel@371: if (value.Length > 63) moel@371: throw new ArgumentOutOfRangeException(); moel@363: moel@371: if (!value.Equals(text)) { moel@371: text = value; moel@371: moel@371: if (visible) moel@371: UpdateNotifyIcon(visible); moel@371: } moel@371: } moel@363: } moel@363: moel@371: public bool Visible { moel@371: get { moel@371: return visible; moel@371: } moel@371: set { moel@371: if (visible != value) { moel@371: visible = value; moel@371: UpdateNotifyIcon(visible); moel@363: } moel@371: } moel@363: } moel@363: moel@371: public NotifyIconWindowsImplementation() { moel@371: BalloonTipText = ""; moel@371: BalloonTipTitle = ""; moel@371: moel@371: commandDispatch = typeof(Form).Assembly. moel@371: GetType("System.Windows.Forms.Command").GetMethod("DispatchID", moel@371: BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, moel@371: null, new Type[] { typeof(int) }, null); moel@371: moel@371: id = ++NotifyIconWindowsImplementation.nextId; moel@371: window = new NotifyIconNativeWindow(this); moel@363: UpdateNotifyIcon(visible); moel@363: } moel@363: moel@371: protected override void Dispose(bool disposing) { moel@371: if (disposing) { moel@371: if (window != null) { moel@371: icon = null; moel@371: text = ""; moel@371: UpdateNotifyIcon(false); moel@371: window.DestroyHandle(); moel@371: window = null; moel@371: ContextMenu = null; moel@371: ContextMenuStrip = null; moel@371: } moel@371: } else { moel@371: if (window != null && window.Handle != IntPtr.Zero) { moel@371: NativeMethods.PostMessage( moel@371: new HandleRef(window, window.Handle), WM_CLOSE, 0, 0); moel@371: window.ReleaseHandle(); moel@371: } moel@371: } moel@371: base.Dispose(disposing); moel@363: } moel@363: moel@371: public void ShowBalloonTip(int timeout) { moel@371: ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon); moel@363: } moel@363: moel@371: public void ShowBalloonTip(int timeout, string tipTitle, string tipText, moel@371: ToolTipIcon tipIcon) { moel@371: if (timeout < 0) moel@371: throw new ArgumentOutOfRangeException("timeout"); moel@371: moel@371: if (string.IsNullOrEmpty(tipText)) moel@371: throw new ArgumentException("tipText"); moel@371: moel@371: if (DesignMode) moel@371: return; moel@371: moel@371: if (created) { moel@371: NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData(); moel@371: if (window.Handle == IntPtr.Zero) moel@371: window.CreateHandle(new CreateParams()); moel@371: moel@371: data.Window = window.Handle; moel@371: data.ID = id; moel@371: data.Flags = NativeMethods.NotifyIconDataFlags.Info; moel@371: data.TimeoutOrVersion = timeout; moel@371: data.InfoTitle = tipTitle; moel@371: data.Info = tipText; moel@371: data.InfoFlags = (int)tipIcon; moel@371: moel@371: NativeMethods.Shell_NotifyIcon( moel@371: NativeMethods.NotifyIconMessage.Modify, data); moel@363: } moel@363: } moel@363: moel@371: private void ShowContextMenu() { moel@371: if (ContextMenu == null && ContextMenuStrip == null) moel@371: return; moel@371: moel@371: NativeMethods.Point p = new NativeMethods.Point(); moel@371: NativeMethods.GetCursorPos(ref p); moel@371: NativeMethods.SetForegroundWindow( moel@371: new HandleRef(window, window.Handle)); moel@371: moel@371: if (ContextMenu != null) { moel@371: ContextMenu.GetType().InvokeMember("OnPopup", moel@371: BindingFlags.NonPublic | BindingFlags.InvokeMethod | moel@371: BindingFlags.Instance, null, ContextMenu, moel@371: new Object[] { System.EventArgs.Empty }); moel@371: moel@371: NativeMethods.TrackPopupMenuEx( moel@371: new HandleRef(ContextMenu, ContextMenu.Handle), 72, moel@371: p.x, p.y, new HandleRef(window, window.Handle), moel@371: IntPtr.Zero); moel@371: moel@371: NativeMethods.PostMessage( moel@371: new HandleRef(window, window.Handle), WM_NULL, 0, 0); moel@371: return; moel@371: } moel@371: moel@371: if (ContextMenuStrip != null) moel@371: ContextMenuStrip.GetType().InvokeMember("ShowInTaskbar", moel@371: BindingFlags.NonPublic | BindingFlags.InvokeMethod | moel@371: BindingFlags.Instance, null, ContextMenuStrip, moel@371: new Object[] { p.x, p.y }); moel@363: } moel@363: moel@371: private void UpdateNotifyIcon(bool showNotifyIcon) { moel@371: if (DesignMode) moel@371: return; moel@363: moel@371: lock (syncObj) { moel@371: window.LockReference(showNotifyIcon); moel@363: moel@371: NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData(); moel@371: data.CallbackMessage = WM_TRAYMOUSEMESSAGE; moel@371: data.Flags = NativeMethods.NotifyIconDataFlags.Message; moel@363: moel@371: if (showNotifyIcon && window.Handle == IntPtr.Zero) moel@371: window.CreateHandle(new CreateParams()); moel@363: moel@371: data.Window = window.Handle; moel@371: data.ID = id; moel@363: moel@371: if (icon != null) { moel@371: data.Flags |= NativeMethods.NotifyIconDataFlags.Icon; moel@371: data.Icon = icon.Handle; moel@371: } moel@363: moel@371: data.Flags |= NativeMethods.NotifyIconDataFlags.Tip; moel@371: data.Tip = text; moel@371: moel@371: if (showNotifyIcon && icon != null) { moel@371: if (!created) { moel@371: int i = 0; moel@371: do { moel@371: created = NativeMethods.Shell_NotifyIcon( moel@371: NativeMethods.NotifyIconMessage.Add, data); moel@371: if (!created) { moel@371: System.Threading.Thread.Sleep(200); moel@371: i++; moel@371: } moel@371: } while (!created && i < 40); moel@371: } else { moel@371: NativeMethods.Shell_NotifyIcon( moel@371: NativeMethods.NotifyIconMessage.Modify, data); moel@371: } moel@371: } else { moel@371: if (created) { moel@371: int i = 0; moel@371: bool deleted = false; moel@371: do { moel@371: deleted = NativeMethods.Shell_NotifyIcon( moel@371: NativeMethods.NotifyIconMessage.Delete, data); moel@371: if (!deleted) { moel@371: System.Threading.Thread.Sleep(200); moel@371: i++; moel@371: } moel@371: } while (!deleted && i < 40); moel@371: created = false; moel@371: } moel@371: } moel@371: } moel@363: } moel@363: moel@371: private void ProcessMouseDown(ref Message message, MouseButtons button, moel@371: bool doubleClick) { moel@371: if (doubleClick) { moel@371: if (DoubleClick != null) moel@371: DoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0)); moel@371: moel@371: if (MouseDoubleClick != null) moel@371: MouseDoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0)); moel@371: moel@371: doubleClickDown = true; moel@371: } moel@371: moel@371: if (MouseDown != null) moel@371: MouseDown(this, moel@371: new MouseEventArgs(button, doubleClick ? 2 : 1, 0, 0, 0)); moel@363: } moel@363: moel@371: private void ProcessMouseUp(ref Message message, MouseButtons button) { moel@371: if (MouseUp != null) moel@371: MouseUp(this, new MouseEventArgs(button, 0, 0, 0, 0)); moel@371: moel@371: if (!doubleClickDown) { moel@371: if (Click != null) moel@371: Click(this, new MouseEventArgs(button, 0, 0, 0, 0)); moel@371: moel@371: if (MouseClick != null) moel@371: MouseClick(this, new MouseEventArgs(button, 0, 0, 0, 0)); moel@371: } moel@371: doubleClickDown = false; moel@363: } moel@363: moel@371: private void ProcessInitMenuPopup(ref Message message) { moel@371: if (ContextMenu != null && moel@371: (bool)ContextMenu.GetType().InvokeMember("ProcessInitMenuPopup", moel@371: BindingFlags.NonPublic | BindingFlags.InvokeMethod | moel@371: BindingFlags.Instance, null, ContextMenu, moel@371: new Object[] { message.WParam })) { moel@371: return; moel@371: } moel@371: window.DefWndProc(ref message); moel@363: } moel@363: moel@371: private void WndProc(ref Message message) { moel@371: switch (message.Msg) { moel@371: case WM_DESTROY: moel@371: UpdateNotifyIcon(false); moel@371: return; moel@371: case WM_COMMAND: moel@371: if (message.LParam != IntPtr.Zero) { moel@371: window.DefWndProc(ref message); moel@371: return; moel@371: } moel@371: commandDispatch.Invoke(null, new object[] { moel@371: message.WParam.ToInt32() & 0xFFFF }); moel@371: return; moel@371: case WM_INITMENUPOPUP: moel@371: ProcessInitMenuPopup(ref message); moel@371: return; moel@371: case WM_TRAYMOUSEMESSAGE: moel@371: switch ((int)message.LParam) { moel@371: case WM_MOUSEMOVE: moel@371: if (MouseMove != null) moel@371: MouseMove(this, moel@371: new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0)); moel@371: return; moel@371: case WM_LBUTTONDOWN: moel@371: ProcessMouseDown(ref message, MouseButtons.Left, false); moel@371: return; moel@371: case WM_LBUTTONUP: moel@371: ProcessMouseUp(ref message, MouseButtons.Left); moel@371: return; moel@371: case WM_LBUTTONDBLCLK: moel@371: ProcessMouseDown(ref message, MouseButtons.Left, true); moel@371: return; moel@371: case WM_RBUTTONDOWN: moel@371: ProcessMouseDown(ref message, MouseButtons.Right, false); moel@371: return; moel@371: case WM_RBUTTONUP: moel@371: if (ContextMenu != null || ContextMenuStrip != null) moel@371: ShowContextMenu(); moel@371: ProcessMouseUp(ref message, MouseButtons.Right); moel@371: return; moel@371: case WM_RBUTTONDBLCLK: moel@371: ProcessMouseDown(ref message, MouseButtons.Right, true); moel@371: return; moel@371: case WM_MBUTTONDOWN: moel@371: ProcessMouseDown(ref message, MouseButtons.Middle, false); moel@371: return; moel@371: case WM_MBUTTONUP: moel@371: ProcessMouseUp(ref message, MouseButtons.Middle); moel@371: return; moel@371: case WM_MBUTTONDBLCLK: moel@371: ProcessMouseDown(ref message, MouseButtons.Middle, true); moel@371: return; moel@371: case NIN_BALLOONSHOW: moel@371: if (BalloonTipShown != null) moel@371: BalloonTipShown(this, EventArgs.Empty); moel@371: return; moel@371: case NIN_BALLOONHIDE: moel@371: case NIN_BALLOONTIMEOUT: moel@371: if (BalloonTipClosed != null) moel@371: BalloonTipClosed(this, EventArgs.Empty); moel@371: return; moel@371: case NIN_BALLOONUSERCLICK: moel@371: if (BalloonTipClicked != null) moel@371: BalloonTipClicked(this, EventArgs.Empty); moel@371: return; moel@371: default: moel@371: return; moel@371: } moel@371: } moel@363: moel@371: if (message.Msg == NotifyIconWindowsImplementation.WM_TASKBARCREATED) { moel@371: lock (syncObj) { moel@371: created = false; moel@371: } moel@371: UpdateNotifyIcon(visible); moel@371: } moel@371: moel@371: window.DefWndProc(ref message); moel@371: } moel@371: moel@371: private class NotifyIconNativeWindow : NativeWindow { moel@371: private NotifyIconWindowsImplementation reference; moel@371: private GCHandle referenceHandle; moel@371: moel@371: internal NotifyIconNativeWindow(NotifyIconWindowsImplementation component) { moel@371: this.reference = component; moel@371: } moel@371: moel@371: ~NotifyIconNativeWindow() { moel@371: if (base.Handle != IntPtr.Zero) moel@371: NativeMethods.PostMessage( moel@371: new HandleRef(this, base.Handle), WM_CLOSE, 0, 0); moel@371: } moel@371: moel@371: public void LockReference(bool locked) { moel@371: if (locked) { moel@371: if (!referenceHandle.IsAllocated) { moel@371: referenceHandle = GCHandle.Alloc(reference, GCHandleType.Normal); moel@371: return; moel@371: } moel@371: } else { moel@371: if (referenceHandle.IsAllocated) moel@371: referenceHandle.Free(); moel@371: } moel@371: } moel@371: moel@371: protected override void OnThreadException(Exception e) { moel@371: Application.OnThreadException(e); moel@371: } moel@371: moel@371: protected override void WndProc(ref Message m) { moel@371: reference.WndProc(ref m); moel@371: } moel@371: } moel@371: moel@371: private const int WM_NULL = 0x00; moel@371: private const int WM_DESTROY = 0x02; moel@371: private const int WM_CLOSE = 0x10; moel@371: private const int WM_COMMAND = 0x111; moel@371: private const int WM_INITMENUPOPUP = 0x117; moel@371: private const int WM_MOUSEMOVE = 0x200; moel@371: private const int WM_LBUTTONDOWN = 0x201; moel@371: private const int WM_LBUTTONUP = 0x202; moel@371: private const int WM_LBUTTONDBLCLK = 0x203; moel@371: private const int WM_RBUTTONDOWN = 0x204; moel@371: private const int WM_RBUTTONUP = 0x205; moel@371: private const int WM_RBUTTONDBLCLK = 0x206; moel@371: private const int WM_MBUTTONDOWN = 0x207; moel@371: private const int WM_MBUTTONUP = 0x208; moel@371: private const int WM_MBUTTONDBLCLK = 0x209; moel@371: private const int WM_TRAYMOUSEMESSAGE = 0x800; moel@371: moel@371: private const int NIN_BALLOONSHOW = 0x402; moel@371: private const int NIN_BALLOONHIDE = 0x403; moel@371: private const int NIN_BALLOONTIMEOUT = 0x404; moel@371: private const int NIN_BALLOONUSERCLICK = 0x405; moel@371: moel@371: private static int WM_TASKBARCREATED = moel@371: NativeMethods.RegisterWindowMessage("TaskbarCreated"); moel@371: moel@371: private static class NativeMethods { moel@371: [DllImport("user32.dll", CharSet = CharSet.Auto)] moel@371: public static extern IntPtr PostMessage(HandleRef hwnd, int msg, moel@371: int wparam, int lparam); moel@371: moel@371: [DllImport("user32.dll", CharSet = CharSet.Auto)] moel@371: public static extern int RegisterWindowMessage(string msg); moel@371: moel@371: [Flags] moel@371: public enum NotifyIconDataFlags : int { moel@371: Message = 0x1, moel@371: Icon = 0x2, moel@371: Tip = 0x4, moel@371: State = 0x8, moel@371: Info = 0x10 moel@371: } moel@371: moel@371: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] moel@371: public class NotifyIconData { moel@371: private int Size = Marshal.SizeOf(typeof(NotifyIconData)); moel@371: public IntPtr Window; moel@371: public int ID; moel@371: public NotifyIconDataFlags Flags; moel@371: public int CallbackMessage; moel@371: public IntPtr Icon; moel@371: [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] moel@371: public string Tip; moel@371: public int State; moel@371: public int StateMask; moel@371: [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] moel@371: public string Info; moel@371: public int TimeoutOrVersion; moel@371: [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] moel@371: public string InfoTitle; moel@371: public int InfoFlags; moel@371: } moel@371: moel@371: public enum NotifyIconMessage : int { moel@371: Add = 0x0, moel@371: Modify = 0x1, moel@371: Delete = 0x2 moel@371: } moel@371: moel@371: [DllImport("shell32.dll", CharSet = CharSet.Auto)] moel@371: [return: MarshalAs(UnmanagedType.Bool)] moel@371: public static extern bool Shell_NotifyIcon(NotifyIconMessage message, moel@371: NotifyIconData pnid); moel@371: moel@371: [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] moel@371: public static extern bool TrackPopupMenuEx(HandleRef hmenu, int fuFlags, moel@371: int x, int y, HandleRef hwnd, IntPtr tpm); moel@371: moel@371: [StructLayout(LayoutKind.Sequential)] moel@371: public struct Point { moel@371: public int x; moel@371: public int y; moel@371: } moel@371: moel@371: [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] moel@371: public static extern bool GetCursorPos(ref Point point); moel@371: moel@371: [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] moel@371: public static extern bool SetForegroundWindow(HandleRef hWnd); moel@371: } moel@363: } moel@363: } moel@363: }