first commit
This commit is contained in:
@@ -0,0 +1,861 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user