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