Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/Hardcodet/Wpf/TaskbarNotification/Interop/WindowMessageSink.cs

163 lines
4.0 KiB
C#

using System;
using System.ComponentModel;
namespace Hardcodet.Wpf.TaskbarNotification.Interop
{
public class WindowMessageSink : IDisposable
{
public const int CallbackMessageId = 1024;
private uint taskbarRestartMessageId;
private bool isDoubleClick;
private WindowProcedureHandler messageHandler;
internal string WindowId { get; private set; }
internal IntPtr MessageWindowHandle { get; private set; }
public NotifyIconVersion Version { get; set; }
public bool IsDisposed { get; private set; }
public event Action<bool> ChangeToolTipStateRequest;
public event Action<MouseEvent> MouseEventReceived;
public event Action<bool> BalloonToolTipChanged;
public event Action TaskbarCreated;
public WindowMessageSink(NotifyIconVersion version)
{
Version = version;
CreateMessageWindow();
}
private WindowMessageSink()
{
}
internal static WindowMessageSink CreateEmpty()
{
return new WindowMessageSink
{
MessageWindowHandle = IntPtr.Zero,
Version = NotifyIconVersion.Vista
};
}
private void CreateMessageWindow()
{
WindowId = "WPFTaskbarIcon_" + Guid.NewGuid().ToString();
messageHandler = OnWindowMessageReceived;
WindowClass lpWndClass = default(WindowClass);
lpWndClass.style = 0u;
lpWndClass.lpfnWndProc = messageHandler;
lpWndClass.cbClsExtra = 0;
lpWndClass.cbWndExtra = 0;
lpWndClass.hInstance = IntPtr.Zero;
lpWndClass.hIcon = IntPtr.Zero;
lpWndClass.hCursor = IntPtr.Zero;
lpWndClass.hbrBackground = IntPtr.Zero;
lpWndClass.lpszMenuName = string.Empty;
lpWndClass.lpszClassName = WindowId;
WinApi.RegisterClass(ref lpWndClass);
taskbarRestartMessageId = WinApi.RegisterWindowMessage("TaskbarCreated");
MessageWindowHandle = WinApi.CreateWindowEx(0, WindowId, "", 0, 0, 0, 1, 1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
if (MessageWindowHandle == IntPtr.Zero)
{
throw new Win32Exception("Message window handle was not a valid pointer");
}
}
private IntPtr OnWindowMessageReceived(IntPtr hWnd, uint messageId, IntPtr wParam, IntPtr lParam)
{
if (messageId == taskbarRestartMessageId)
{
this.TaskbarCreated?.Invoke();
}
ProcessWindowMessage(messageId, wParam, lParam);
return WinApi.DefWindowProc(hWnd, messageId, wParam, lParam);
}
private void ProcessWindowMessage(uint msg, IntPtr wParam, IntPtr lParam)
{
if (msg != 1024)
{
return;
}
switch (lParam.ToInt32())
{
case 512:
this.MouseEventReceived?.Invoke(MouseEvent.MouseMove);
break;
case 513:
this.MouseEventReceived?.Invoke(MouseEvent.IconLeftMouseDown);
break;
case 514:
if (!isDoubleClick)
{
this.MouseEventReceived?.Invoke(MouseEvent.IconLeftMouseUp);
}
isDoubleClick = false;
break;
case 515:
isDoubleClick = true;
this.MouseEventReceived?.Invoke(MouseEvent.IconDoubleClick);
break;
case 516:
this.MouseEventReceived?.Invoke(MouseEvent.IconRightMouseDown);
break;
case 517:
this.MouseEventReceived?.Invoke(MouseEvent.IconRightMouseUp);
break;
case 519:
this.MouseEventReceived?.Invoke(MouseEvent.IconMiddleMouseDown);
break;
case 520:
this.MouseEventReceived?.Invoke(MouseEvent.IconMiddleMouseUp);
break;
case 1026:
this.BalloonToolTipChanged?.Invoke(obj: true);
break;
case 1027:
case 1028:
this.BalloonToolTipChanged?.Invoke(obj: false);
break;
case 1029:
this.MouseEventReceived?.Invoke(MouseEvent.BalloonToolTipClicked);
break;
case 1030:
this.ChangeToolTipStateRequest?.Invoke(obj: true);
break;
case 1031:
this.ChangeToolTipStateRequest?.Invoke(obj: false);
break;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
~WindowMessageSink()
{
Dispose(disposing: false);
}
private void Dispose(bool disposing)
{
if (!IsDisposed)
{
IsDisposed = true;
WinApi.DestroyWindow(MessageWindowHandle);
messageHandler = null;
}
}
}
}