# HG changeset patch
# User moel.mich
# Date 1343145870 0
# Node ID c1a0d321e6460974d90dfe8c5593f6e71597c03f
# Parent 8e4dedc41924348029f83736558110a3e8737a1c
Added a wrapper for the NotifyIconAdv to use the normal NotifyIcon class on Linux systems and the (fixed) custom implementation on Windows systems.
diff -r 8e4dedc41924 -r c1a0d321e646 GUI/NotifyIconAdv.cs
--- a/GUI/NotifyIconAdv.cs Mon Jul 23 21:54:35 2012 +0000
+++ b/GUI/NotifyIconAdv.cs Tue Jul 24 16:04:30 2012 +0000
@@ -16,115 +16,298 @@
using System.Windows.Forms;
namespace OpenHardwareMonitor.GUI {
- public class NotifyIconAdv : Component {
- private static int nextId = 0;
+ public class NotifyIconAdv : IDisposable {
- private object syncObj = new object();
- private Icon icon;
- private string text = "";
- private int id;
- private bool created;
- private NotifyIconNativeWindow window;
- private bool doubleClickDown;
- private bool visible;
- private MethodInfo commandDispatch;
+ private NotifyIcon genericNotifyIcon;
+ private NotifyIconWindowsImplementation windowsNotifyIcon;
- 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 NotifyIconAdv() {
+ int p = (int)Environment.OSVersion.Platform;
+ if ((p == 4) || (p == 128)) { // Unix
+ genericNotifyIcon = new NotifyIcon();
+ } else { // Windows
+ windowsNotifyIcon = new NotifyIconWindowsImplementation();
+ }
+ }
- public string BalloonTipText { get; set; }
- public ToolTipIcon BalloonTipIcon { get; set; }
- public string BalloonTipTitle { get; set; }
- public ContextMenu ContextMenu { get; set; }
- public ContextMenuStrip ContextMenuStrip { get; set; }
+ 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;
+ else
+ return windowsNotifyIcon.BalloonTipText;
+ }
+ set {
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.BalloonTipText = value;
+ else
+ windowsNotifyIcon.BalloonTipText = value;
+ }
+ }
+
+ public ToolTipIcon BalloonTipIcon {
+ get {
+ if (genericNotifyIcon != null)
+ return genericNotifyIcon.BalloonTipIcon;
+ else
+ return windowsNotifyIcon.BalloonTipIcon;
+ }
+ set {
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.BalloonTipIcon = value;
+ else
+ windowsNotifyIcon.BalloonTipIcon = value;
+ }
+ }
+
+ public string BalloonTipTitle {
+ get {
+ if (genericNotifyIcon != null)
+ return genericNotifyIcon.BalloonTipTitle;
+ else
+ return windowsNotifyIcon.BalloonTipTitle;
+ }
+ set {
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.BalloonTipTitle = value;
+ else
+ windowsNotifyIcon.BalloonTipTitle = value;
+ }
+ }
+
+ public ContextMenu ContextMenu {
+ get {
+ if (genericNotifyIcon != null)
+ return genericNotifyIcon.ContextMenu;
+ else
+ return windowsNotifyIcon.ContextMenu;
+ }
+ set {
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.ContextMenu = value;
+ else
+ windowsNotifyIcon.ContextMenu = value;
+ }
+ }
+
+ public ContextMenuStrip ContextMenuStrip {
+ get {
+ if (genericNotifyIcon != null)
+ return genericNotifyIcon.ContextMenuStrip;
+ else
+ return windowsNotifyIcon.ContextMenuStrip;
+ }
+ set {
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.ContextMenuStrip = value;
+ else
+ windowsNotifyIcon.ContextMenuStrip = value;
+ }
+ }
+
public object Tag { get; set; }
public Icon Icon {
get {
- return icon;
+ if (genericNotifyIcon != null)
+ return genericNotifyIcon.Icon;
+ else
+ return windowsNotifyIcon.Icon;
}
set {
- if (icon != value) {
- icon = value;
- UpdateNotifyIcon(visible);
- }
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.Icon = value;
+ else
+ windowsNotifyIcon.Icon = value;
}
}
public string Text {
get {
- return text;
+ if (genericNotifyIcon != null)
+ return genericNotifyIcon.Text;
+ else
+ return windowsNotifyIcon.Text;
}
set {
- if (value == null)
- value = "";
-
- if (value.Length > 63)
- throw new ArgumentOutOfRangeException();
-
- if (!value.Equals(text)) {
- text = value;
-
- if (visible)
- UpdateNotifyIcon(visible);
- }
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.Text = value;
+ else
+ windowsNotifyIcon.Text = value;
}
}
public bool Visible {
get {
- return visible;
+ if (genericNotifyIcon != null)
+ return genericNotifyIcon.Visible;
+ else
+ return windowsNotifyIcon.Visible;
}
set {
- if (visible != value) {
- visible = value;
- UpdateNotifyIcon(visible);
- }
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.Visible = value;
+ else
+ windowsNotifyIcon.Visible = value;
}
}
-
- public NotifyIconAdv() {
- BalloonTipText = "";
- BalloonTipTitle = "";
- commandDispatch = typeof(Form).Assembly.
- GetType("System.Windows.Forms.Command").GetMethod("DispatchID",
- BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public,
- null, new Type[] { typeof(int) }, null);
-
- id = ++NotifyIconAdv.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;
- ContextMenu = 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 Dispose() {
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.Dispose();
+ else
+ windowsNotifyIcon.Dispose();
}
public void ShowBalloonTip(int timeout) {
@@ -132,371 +315,493 @@
}
public void ShowBalloonTip(int timeout, string tipTitle, string tipText,
- ToolTipIcon tipIcon)
- {
- if (timeout < 0)
- throw new ArgumentOutOfRangeException("timeout");
+ ToolTipIcon tipIcon) {
+ if (genericNotifyIcon != null)
+ genericNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon);
+ else
+ windowsNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon);
+ }
+
+ private class NotifyIconWindowsImplementation : Component {
- if (string.IsNullOrEmpty(tipText))
- throw new ArgumentException("tipText");
+ private static int nextId = 0;
- if (DesignMode)
- return;
+ private object syncObj = new object();
+ private Icon icon;
+ private string text = "";
+ private int id;
+ private bool created;
+ private NotifyIconNativeWindow window;
+ private bool doubleClickDown;
+ private bool visible;
+ private MethodInfo commandDispatch;
- if (created) {
- NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData();
- if (window.Handle == IntPtr.Zero)
- window.CreateHandle(new CreateParams());
+ 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;
- 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;
+ public string BalloonTipText { get; set; }
+ public ToolTipIcon BalloonTipIcon { get; set; }
+ public string BalloonTipTitle { get; set; }
+ public ContextMenu ContextMenu { get; set; }
+ public ContextMenuStrip ContextMenuStrip { get; set; }
+ public object Tag { get; set; }
- NativeMethods.Shell_NotifyIcon(
- NativeMethods.NotifyIconMessage.Modify, data);
- }
- }
-
- private void ShowContextMenu() {
- if (ContextMenu == null && ContextMenuStrip == null)
- return;
-
- NativeMethods.Point p = new NativeMethods.Point();
- NativeMethods.GetCursorPos(ref p);
- NativeMethods.SetForegroundWindow(
- new HandleRef(window, window.Handle));
-
- if (ContextMenu != null) {
- ContextMenu.GetType().InvokeMember("OnPopup",
- BindingFlags.NonPublic | BindingFlags.InvokeMethod |
- BindingFlags.Instance, null, ContextMenu,
- new Object[] { System.EventArgs.Empty });
-
- NativeMethods.TrackPopupMenuEx(
- new HandleRef(ContextMenu, ContextMenu.Handle), 72,
- p.x, p.y, new HandleRef(window, window.Handle),
- IntPtr.Zero);
-
- NativeMethods.PostMessage(
- new HandleRef(window, window.Handle), WM_NULL, 0, 0);
- return;
- }
-
- if (ContextMenuStrip != null)
- 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();
- data.CallbackMessage = WM_TRAYMOUSEMESSAGE;
- data.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;
+ public Icon Icon {
+ get {
+ return icon;
}
-
- data.Flags |= NativeMethods.NotifyIconDataFlags.Tip;
- data.Tip = text;
-
- if (showNotifyIcon && icon != null) {
- if (!created) {
- 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 = false;
- do {
- deleted = NativeMethods.Shell_NotifyIcon(
- NativeMethods.NotifyIconMessage.Delete, data);
- if (!deleted) {
- System.Threading.Thread.Sleep(200);
- i++;
- }
- } while (!deleted && i < 40);
- created = false;
+ set {
+ if (icon != value) {
+ icon = value;
+ UpdateNotifyIcon(visible);
}
}
}
- }
- private void ProcessMouseDown(ref Message message, MouseButtons button,
- bool doubleClick)
- {
- if (doubleClick) {
- if (DoubleClick != null)
- DoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0));
+ public string Text {
+ get {
+ return text;
+ }
+ set {
+ if (value == null)
+ value = "";
- if (MouseDoubleClick != null)
- MouseDoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0));
+ if (value.Length > 63)
+ throw new ArgumentOutOfRangeException();
- doubleClickDown = true;
+ if (!value.Equals(text)) {
+ text = value;
+
+ if (visible)
+ UpdateNotifyIcon(visible);
+ }
+ }
}
- if (MouseDown != null)
- MouseDown(this,
- new MouseEventArgs(button, doubleClick ? 2 : 1, 0, 0, 0));
- }
-
- private void ProcessMouseUp(ref Message message, MouseButtons button) {
- if (MouseUp != null)
- MouseUp(this, new MouseEventArgs(button, 0, 0, 0, 0));
-
- if (!doubleClickDown) {
- if (Click != null)
- Click(this, new MouseEventArgs(button, 0, 0, 0, 0));
-
- if (MouseClick != null)
- MouseClick(this, new MouseEventArgs(button, 0, 0, 0, 0));
- }
- doubleClickDown = false;
- }
-
- private void ProcessInitMenuPopup(ref Message message) {
- if (ContextMenu != null &&
- (bool)ContextMenu.GetType().InvokeMember("ProcessInitMenuPopup",
- BindingFlags.NonPublic | BindingFlags.InvokeMethod |
- BindingFlags.Instance, null, ContextMenu,
- new Object[] { message.WParam })) {
- return;
- }
- 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;
+ public bool Visible {
+ get {
+ return visible;
+ }
+ set {
+ if (visible != value) {
+ visible = value;
+ UpdateNotifyIcon(visible);
}
- 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:
- if (MouseMove != null)
- MouseMove(this,
- new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0));
- return;
- case WM_LBUTTONDOWN:
- ProcessMouseDown(ref message, MouseButtons.Left, false);
- return;
- case WM_LBUTTONUP:
- ProcessMouseUp(ref message, MouseButtons.Left);
- return;
- case WM_LBUTTONDBLCLK:
- ProcessMouseDown(ref message, MouseButtons.Left, true);
- return;
- case WM_RBUTTONDOWN:
- ProcessMouseDown(ref message, MouseButtons.Right, false);
- return;
- case WM_RBUTTONUP:
- if (ContextMenu != null || ContextMenuStrip != null)
- ShowContextMenu();
- ProcessMouseUp(ref message, MouseButtons.Right);
- return;
- case WM_RBUTTONDBLCLK:
- ProcessMouseDown(ref message, MouseButtons.Right, true);
- return;
- case WM_MBUTTONDOWN:
- ProcessMouseDown(ref message, MouseButtons.Middle, false);
- return;
- case WM_MBUTTONUP:
- ProcessMouseUp(ref message, MouseButtons.Middle);
- return;
- case WM_MBUTTONDBLCLK:
- ProcessMouseDown(ref message, MouseButtons.Middle, true);
- return;
- case NIN_BALLOONSHOW:
- if (BalloonTipShown != null)
- BalloonTipShown(this, EventArgs.Empty);
- return;
- case NIN_BALLOONHIDE:
- case NIN_BALLOONTIMEOUT:
- if (BalloonTipClosed != null)
- BalloonTipClosed(this, EventArgs.Empty);
- return;
- case NIN_BALLOONUSERCLICK:
- if (BalloonTipClicked != null)
- BalloonTipClicked(this, EventArgs.Empty);
- return;
- default:
- return;
- }
+ }
}
- if (message.Msg == NotifyIconAdv.WM_TASKBARCREATED) {
- lock (syncObj) {
- created = false;
- }
+ public NotifyIconWindowsImplementation() {
+ BalloonTipText = "";
+ BalloonTipTitle = "";
+
+ commandDispatch = typeof(Form).Assembly.
+ GetType("System.Windows.Forms.Command").GetMethod("DispatchID",
+ BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public,
+ null, new Type[] { typeof(int) }, null);
+
+ id = ++NotifyIconWindowsImplementation.nextId;
+ window = new NotifyIconNativeWindow(this);
UpdateNotifyIcon(visible);
}
- window.DefWndProc(ref message);
- }
-
- private class NotifyIconNativeWindow : NativeWindow {
- private NotifyIconAdv reference;
- private GCHandle referenceHandle;
-
- internal NotifyIconNativeWindow(NotifyIconAdv component) {
- this.reference = component;
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ if (window != null) {
+ icon = null;
+ text = "";
+ UpdateNotifyIcon(false);
+ window.DestroyHandle();
+ window = null;
+ ContextMenu = 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);
}
- ~NotifyIconNativeWindow() {
- if (base.Handle != IntPtr.Zero)
- NativeMethods.PostMessage(
- new HandleRef(this, base.Handle), WM_CLOSE, 0, 0);
+ public void ShowBalloonTip(int timeout) {
+ ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon);
}
- public void LockReference(bool locked) {
- if (locked) {
- if (!referenceHandle.IsAllocated) {
- referenceHandle = GCHandle.Alloc(reference, GCHandleType.Normal);
- return;
- }
- } else {
- if (referenceHandle.IsAllocated)
- referenceHandle.Free();
+ public void ShowBalloonTip(int timeout, string tipTitle, string tipText,
+ ToolTipIcon tipIcon) {
+ if (timeout < 0)
+ throw new ArgumentOutOfRangeException("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);
}
}
- protected override void OnThreadException(Exception e) {
- Application.OnThreadException(e);
+ private void ShowContextMenu() {
+ if (ContextMenu == null && ContextMenuStrip == null)
+ return;
+
+ NativeMethods.Point p = new NativeMethods.Point();
+ NativeMethods.GetCursorPos(ref p);
+ NativeMethods.SetForegroundWindow(
+ new HandleRef(window, window.Handle));
+
+ if (ContextMenu != null) {
+ ContextMenu.GetType().InvokeMember("OnPopup",
+ BindingFlags.NonPublic | BindingFlags.InvokeMethod |
+ BindingFlags.Instance, null, ContextMenu,
+ new Object[] { System.EventArgs.Empty });
+
+ NativeMethods.TrackPopupMenuEx(
+ new HandleRef(ContextMenu, ContextMenu.Handle), 72,
+ p.x, p.y, new HandleRef(window, window.Handle),
+ IntPtr.Zero);
+
+ NativeMethods.PostMessage(
+ new HandleRef(window, window.Handle), WM_NULL, 0, 0);
+ return;
+ }
+
+ if (ContextMenuStrip != null)
+ ContextMenuStrip.GetType().InvokeMember("ShowInTaskbar",
+ BindingFlags.NonPublic | BindingFlags.InvokeMethod |
+ BindingFlags.Instance, null, ContextMenuStrip,
+ new Object[] { p.x, p.y });
}
- protected override void WndProc(ref Message m) {
- reference.WndProc(ref m);
- }
- }
+ private void UpdateNotifyIcon(bool showNotifyIcon) {
+ if (DesignMode)
+ return;
- 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;
+ lock (syncObj) {
+ window.LockReference(showNotifyIcon);
- private const int NIN_BALLOONSHOW = 0x402;
- private const int NIN_BALLOONHIDE = 0x403;
- private const int NIN_BALLOONTIMEOUT = 0x404;
- private const int NIN_BALLOONUSERCLICK = 0x405;
+ NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData();
+ data.CallbackMessage = WM_TRAYMOUSEMESSAGE;
+ data.Flags = NativeMethods.NotifyIconDataFlags.Message;
- private static int WM_TASKBARCREATED =
- NativeMethods.RegisterWindowMessage("TaskbarCreated");
+ if (showNotifyIcon && window.Handle == IntPtr.Zero)
+ window.CreateHandle(new CreateParams());
- private static class NativeMethods {
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern IntPtr PostMessage(HandleRef hwnd, int msg,
- int wparam, int lparam);
+ data.Window = window.Handle;
+ data.ID = id;
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern int RegisterWindowMessage(string msg);
+ if (icon != null) {
+ data.Flags |= NativeMethods.NotifyIconDataFlags.Icon;
+ data.Icon = icon.Handle;
+ }
- [Flags]
- public enum NotifyIconDataFlags : int {
- Message = 0x1,
- Icon = 0x2,
- Tip = 0x4,
- State = 0x8,
- Info = 0x10
+ data.Flags |= NativeMethods.NotifyIconDataFlags.Tip;
+ data.Tip = text;
+
+ if (showNotifyIcon && icon != null) {
+ if (!created) {
+ 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 = false;
+ do {
+ deleted = NativeMethods.Shell_NotifyIcon(
+ NativeMethods.NotifyIconMessage.Delete, data);
+ if (!deleted) {
+ System.Threading.Thread.Sleep(200);
+ i++;
+ }
+ } while (!deleted && i < 40);
+ created = false;
+ }
+ }
+ }
}
- [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;
+ private void ProcessMouseDown(ref Message message, MouseButtons button,
+ bool doubleClick) {
+ if (doubleClick) {
+ if (DoubleClick != null)
+ DoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0));
+
+ if (MouseDoubleClick != null)
+ MouseDoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0));
+
+ doubleClickDown = true;
+ }
+
+ if (MouseDown != null)
+ MouseDown(this,
+ new MouseEventArgs(button, doubleClick ? 2 : 1, 0, 0, 0));
}
- public enum NotifyIconMessage : int {
- Add = 0x0,
- Modify = 0x1,
- Delete = 0x2
+ private void ProcessMouseUp(ref Message message, MouseButtons button) {
+ if (MouseUp != null)
+ MouseUp(this, new MouseEventArgs(button, 0, 0, 0, 0));
+
+ if (!doubleClickDown) {
+ if (Click != null)
+ Click(this, new MouseEventArgs(button, 0, 0, 0, 0));
+
+ if (MouseClick != null)
+ MouseClick(this, new MouseEventArgs(button, 0, 0, 0, 0));
+ }
+ doubleClickDown = false;
}
- [DllImport("shell32.dll", CharSet = CharSet.Auto)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool Shell_NotifyIcon(NotifyIconMessage message,
- NotifyIconData pnid);
-
- [DllImport("user32.dll", 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 int x;
- public int y;
+ private void ProcessInitMenuPopup(ref Message message) {
+ if (ContextMenu != null &&
+ (bool)ContextMenu.GetType().InvokeMember("ProcessInitMenuPopup",
+ BindingFlags.NonPublic | BindingFlags.InvokeMethod |
+ BindingFlags.Instance, null, ContextMenu,
+ new Object[] { message.WParam })) {
+ return;
+ }
+ window.DefWndProc(ref message);
}
- [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
- public static extern bool GetCursorPos(ref Point point);
+ 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:
+ if (MouseMove != null)
+ MouseMove(this,
+ new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0));
+ return;
+ case WM_LBUTTONDOWN:
+ ProcessMouseDown(ref message, MouseButtons.Left, false);
+ return;
+ case WM_LBUTTONUP:
+ ProcessMouseUp(ref message, MouseButtons.Left);
+ return;
+ case WM_LBUTTONDBLCLK:
+ ProcessMouseDown(ref message, MouseButtons.Left, true);
+ return;
+ case WM_RBUTTONDOWN:
+ ProcessMouseDown(ref message, MouseButtons.Right, false);
+ return;
+ case WM_RBUTTONUP:
+ if (ContextMenu != null || ContextMenuStrip != null)
+ ShowContextMenu();
+ ProcessMouseUp(ref message, MouseButtons.Right);
+ return;
+ case WM_RBUTTONDBLCLK:
+ ProcessMouseDown(ref message, MouseButtons.Right, true);
+ return;
+ case WM_MBUTTONDOWN:
+ ProcessMouseDown(ref message, MouseButtons.Middle, false);
+ return;
+ case WM_MBUTTONUP:
+ ProcessMouseUp(ref message, MouseButtons.Middle);
+ return;
+ case WM_MBUTTONDBLCLK:
+ ProcessMouseDown(ref message, MouseButtons.Middle, true);
+ return;
+ case NIN_BALLOONSHOW:
+ if (BalloonTipShown != null)
+ BalloonTipShown(this, EventArgs.Empty);
+ return;
+ case NIN_BALLOONHIDE:
+ case NIN_BALLOONTIMEOUT:
+ if (BalloonTipClosed != null)
+ BalloonTipClosed(this, EventArgs.Empty);
+ return;
+ case NIN_BALLOONUSERCLICK:
+ if (BalloonTipClicked != null)
+ BalloonTipClicked(this, EventArgs.Empty);
+ return;
+ default:
+ return;
+ }
+ }
- [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
- public static extern bool SetForegroundWindow(HandleRef hWnd);
+ if (message.Msg == NotifyIconWindowsImplementation.WM_TASKBARCREATED) {
+ lock (syncObj) {
+ created = false;
+ }
+ UpdateNotifyIcon(visible);
+ }
+
+ window.DefWndProc(ref message);
+ }
+
+ private class NotifyIconNativeWindow : NativeWindow {
+ private NotifyIconWindowsImplementation reference;
+ private GCHandle referenceHandle;
+
+ internal NotifyIconNativeWindow(NotifyIconWindowsImplementation component) {
+ this.reference = component;
+ }
+
+ ~NotifyIconNativeWindow() {
+ if (base.Handle != IntPtr.Zero)
+ NativeMethods.PostMessage(
+ new HandleRef(this, base.Handle), WM_CLOSE, 0, 0);
+ }
+
+ public void LockReference(bool locked) {
+ if (locked) {
+ if (!referenceHandle.IsAllocated) {
+ referenceHandle = GCHandle.Alloc(reference, GCHandleType.Normal);
+ return;
+ }
+ } 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 int WM_TASKBARCREATED =
+ NativeMethods.RegisterWindowMessage("TaskbarCreated");
+
+ private static class NativeMethods {
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ public static extern IntPtr PostMessage(HandleRef hwnd, int msg,
+ int wparam, int lparam);
+
+ [DllImport("user32.dll", 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("shell32.dll", CharSet = CharSet.Auto)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool Shell_NotifyIcon(NotifyIconMessage message,
+ NotifyIconData pnid);
+
+ [DllImport("user32.dll", 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 int x;
+ public int y;
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
+ public static extern bool GetCursorPos(ref Point point);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
+ public static extern bool SetForegroundWindow(HandleRef hWnd);
+ }
}
}
}
diff -r 8e4dedc41924 -r c1a0d321e646 OpenHardwareMonitor.csproj
--- a/OpenHardwareMonitor.csproj Mon Jul 23 21:54:35 2012 +0000
+++ b/OpenHardwareMonitor.csproj Tue Jul 24 16:04:30 2012 +0000
@@ -73,9 +73,7 @@
-
- Component
-
+
UserControl