264 lines
8.4 KiB
C#
264 lines
8.4 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Forms;
|
|
using System.ComponentModel;
|
|
using Microsoft.Win32;
|
|
using System.Diagnostics;
|
|
|
|
|
|
namespace ntfysh_client
|
|
{
|
|
public partial class NotificationDialog : Form
|
|
{
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
private static extern bool AnimateWindow(IntPtr hWnd, int time, int flags);
|
|
|
|
private const int ScreenMargin = 20;
|
|
|
|
private int _timeout = 0;
|
|
private System.Timers.Timer? displayTimeoutTimer = null;
|
|
private System.Windows.Forms.Timer? updateTimer = null;
|
|
private Stopwatch? shownStopwatch = null;
|
|
private ToolTipIcon? _icon;
|
|
private int _progress_value = 0;
|
|
private int progress
|
|
{
|
|
get { return this._progress_value; }
|
|
set
|
|
{
|
|
this._progress_value = value;
|
|
this.progressBar1.Value = value;
|
|
}
|
|
}
|
|
|
|
public bool IsVisible
|
|
{
|
|
get { return this.Visible; }
|
|
set { this.Visible = value; }
|
|
}
|
|
|
|
public NotificationDialog()
|
|
{
|
|
this.ShowInTaskbar = false;
|
|
this.IsVisible = false;
|
|
this.TopMost = true;
|
|
InitializeComponent();
|
|
InitializeWindowHidden();
|
|
}
|
|
|
|
public void ShowNotification(string title, string message, int timeout_ms = -1, ToolTipIcon? icon = null, bool showTimeOutBar = true, bool showInDarkMode = true)
|
|
{
|
|
if (this.IsVisible)
|
|
{
|
|
// close the current notification
|
|
this.handleTimeout(null, null);
|
|
}
|
|
// setup data
|
|
this._icon = icon;
|
|
if (this._icon != null)
|
|
{
|
|
this.iconBox.Image = ConvertToolTipIconToImage(_icon.Value);
|
|
}
|
|
this.tbTitle.Text = title;
|
|
this.tbMessage.Text = message;
|
|
|
|
// setup timers
|
|
if (this.displayTimeoutTimer != null)
|
|
{
|
|
this.displayTimeoutTimer.Stop();
|
|
this.displayTimeoutTimer.Dispose();
|
|
}
|
|
if (this.updateTimer != null)
|
|
{
|
|
this.updateTimer.Stop();
|
|
this.updateTimer.Dispose();
|
|
}
|
|
if (timeout_ms > 0)
|
|
{
|
|
this.displayTimeoutTimer = new System.Timers.Timer(timeout_ms);
|
|
displayTimeoutTimer.Elapsed += handleTimeout;
|
|
this.displayTimeoutTimer.Start();
|
|
|
|
if (showTimeOutBar)
|
|
{
|
|
this.progress = 100;
|
|
this.updateTimer = new System.Windows.Forms.Timer();
|
|
updateTimer.Interval = 100;
|
|
this.updateTimer.Tick += this.UpdateProgress;
|
|
this.updateTimer.Start();
|
|
|
|
this.shownStopwatch = new Stopwatch();
|
|
this.shownStopwatch.Start();
|
|
|
|
this.progressBar1.Visible = true;
|
|
this.lbTimeout.Visible = true;
|
|
this._timeout = timeout_ms;
|
|
} else
|
|
{
|
|
this.progressBar1.Visible = false;
|
|
this.lbTimeout.Visible = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.progressBar1.Visible = false;
|
|
this.lbTimeout.Visible = false;
|
|
}
|
|
|
|
// ok, show the window
|
|
this.Show();
|
|
this.SetWindowPosition();
|
|
}
|
|
|
|
private void UpdateProgress(object? sender, EventArgs e)
|
|
{
|
|
if (this.shownStopwatch == null)
|
|
{
|
|
return;
|
|
}
|
|
this.progress = (int)((this._timeout - this.shownStopwatch.ElapsedMilliseconds) * 100 / this._timeout);
|
|
this.lbTimeout.Text = $"{(int)(this._timeout - this.shownStopwatch.ElapsedMilliseconds) / 1000}";
|
|
}
|
|
|
|
protected override void SetVisibleCore(bool value)
|
|
{
|
|
this.SetWindowPosition();
|
|
if (value)
|
|
{
|
|
this.BringToFront();
|
|
AnimateWindow(
|
|
this.Handle,
|
|
time: 250,
|
|
flags: NFWinUserAnimateWindowConstnats.AW_SLIDE | NFWinUserAnimateWindowConstnats.AW_VER_NEGATIVE
|
|
);
|
|
}
|
|
base.SetVisibleCore(value);
|
|
}
|
|
|
|
protected override void OnShown(EventArgs e)
|
|
{
|
|
base.OnShown(e);
|
|
}
|
|
|
|
private void SetWindowPosition()
|
|
{
|
|
int workingtop = Screen.PrimaryScreen.WorkingArea.Height - this.Height;
|
|
this.Top = workingtop - NotificationDialog.ScreenMargin;
|
|
|
|
int workingleft = Screen.PrimaryScreen.WorkingArea.Width - this.Width;
|
|
this.Left = workingleft - NotificationDialog.ScreenMargin;
|
|
}
|
|
|
|
private void ui_hide_window(object? sender, EventArgs? e)
|
|
{
|
|
AnimateWindow(
|
|
this.Handle,
|
|
time: 250,
|
|
flags: NFWinUserAnimateWindowConstnats.AW_SLIDE | NFWinUserAnimateWindowConstnats.AW_VER_POSITIVE | NFWinUserAnimateWindowConstnats.AW_HIDE
|
|
);
|
|
this.IsVisible = false;
|
|
}
|
|
|
|
private void handleTimeout(object? sender, EventArgs? e)
|
|
{
|
|
this.cancelTimer();
|
|
if (this.InvokeRequired)
|
|
{
|
|
// on a background thread, so invoke on the UI thread
|
|
this.Invoke(new Action(() => this.ui_hide_window(sender, e)));
|
|
}
|
|
else
|
|
{
|
|
// in the UI thread, invoke directly
|
|
this.ui_hide_window(sender, e);
|
|
}
|
|
}
|
|
|
|
private Image? ConvertToolTipIconToImage(ToolTipIcon icon)
|
|
{
|
|
switch (icon)
|
|
{
|
|
case ToolTipIcon.Info:
|
|
return SystemIcons.Information.ToBitmap();
|
|
case ToolTipIcon.Warning:
|
|
return SystemIcons.Warning.ToBitmap();
|
|
case ToolTipIcon.Error:
|
|
return SystemIcons.Error.ToBitmap();
|
|
case ToolTipIcon.None:
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private void InitializeWindowHidden()
|
|
{
|
|
this.Opacity = 0;
|
|
this.ShowNotification("Title", "Message");
|
|
this.IsVisible = false;
|
|
this.Opacity = 1;
|
|
}
|
|
|
|
private void btnClose_Click(object sender, EventArgs e)
|
|
{
|
|
// immediate
|
|
this.IsVisible = false;
|
|
}
|
|
|
|
private class NFWinUserAnimateWindowConstnats
|
|
{
|
|
public const int AW_HOR_POSITIVE = 0x00000001;
|
|
public const int AW_HOR_NEGATIVE = 0x00000002;
|
|
public const int AW_VER_POSITIVE = 0x00000004;
|
|
public const int AW_VER_NEGATIVE = 0x00000008;
|
|
public const int AW_CENTER = 0x00000010;
|
|
public const int AW_HIDE = 0x00010000;
|
|
public const int AW_ACTIVATE = 0x00020000;
|
|
public const int AW_SLIDE = 0x00040000;
|
|
public const int AW_BLEND = 0x00080000;
|
|
}
|
|
|
|
private void window_MouseDown(object sender, EventArgs e)
|
|
{
|
|
this.cancelTimer();
|
|
}
|
|
|
|
private void cancelTimer()
|
|
{
|
|
if (this.InvokeRequired)
|
|
{
|
|
// on a background thread, so invoke on the UI thread
|
|
this.Invoke(new Action(() =>
|
|
{
|
|
this.lbTimeout.Visible = false;
|
|
this.progressBar1.Visible = false;
|
|
}));
|
|
}
|
|
else
|
|
{
|
|
// in the UI thread, invoke directly
|
|
this.lbTimeout.Visible = false;
|
|
this.progressBar1.Visible = false;
|
|
}
|
|
|
|
if (this.displayTimeoutTimer != null) // check if the timer has already been disposed
|
|
{
|
|
this.displayTimeoutTimer.Stop();
|
|
this.displayTimeoutTimer.Dispose();
|
|
this.displayTimeoutTimer = null;
|
|
}
|
|
if (this.updateTimer != null)
|
|
{
|
|
this.updateTimer.Stop();
|
|
this.updateTimer.Dispose();
|
|
this.updateTimer = null;
|
|
}
|
|
if (this.shownStopwatch != null)
|
|
{
|
|
this.shownStopwatch.Stop();
|
|
this.shownStopwatch = null;
|
|
}
|
|
}
|
|
}
|
|
}
|