for Push.
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace KssSmaPlaLib.Forms
|
||||
{
|
||||
public static class ToastNotifier
|
||||
{
|
||||
private const int WS_EX_NOACTIVATE = 0x08000000;
|
||||
private const int WS_EX_TOPMOST = 0x00000008;
|
||||
|
||||
//public static void Show(Form owner, string message, Color backColor, int durationMs = 3000)
|
||||
//{
|
||||
// // 1. フォームの基本設定
|
||||
// Form toast = new Form
|
||||
// {
|
||||
// FormBorderStyle = FormBorderStyle.None,
|
||||
// StartPosition = FormStartPosition.Manual,
|
||||
// BackColor = backColor,
|
||||
// ShowInTaskbar = false,
|
||||
// TopMost = true,
|
||||
// Size = new Size(300, 60),
|
||||
// Opacity = 0,
|
||||
// Enabled = false // トースト自体は操作不能にしておく
|
||||
// };
|
||||
// Label lbl = new Label
|
||||
// {
|
||||
// Text = message,
|
||||
// ForeColor = Color.White,
|
||||
// Font = new Font("MS UI Gothic", 10, FontStyle.Bold),
|
||||
// Dock = DockStyle.Fill,
|
||||
// TextAlign = ContentAlignment.MiddleCenter
|
||||
// };
|
||||
// toast.Controls.Add(lbl);
|
||||
// // オーナーの右下に配置
|
||||
// toast.Location = new Point(
|
||||
// owner.Location.X + owner.Width - toast.Width - 20,
|
||||
// owner.Location.Y + owner.Height - toast.Height - 20
|
||||
// );
|
||||
// // 2. タイマーでアニメーションを管理
|
||||
// Timer timer = new Timer { Interval = 10 };
|
||||
// DateTime startTime = DateTime.Now;
|
||||
// timer.Tick += (s, e) =>
|
||||
// {
|
||||
// double elapsed = (DateTime.Now - startTime).TotalMilliseconds;
|
||||
// if (elapsed < 200) // 最初の0.2秒でフェードイン
|
||||
// {
|
||||
// toast.Opacity = elapsed / 200.0;
|
||||
// }
|
||||
// else if (elapsed < 200 + durationMs) // 指定時間はそのまま
|
||||
// {
|
||||
// toast.Opacity = 1.0;
|
||||
// }
|
||||
// else if (elapsed < 200 + durationMs + 200) // 最後の0.2秒でフェードアウト
|
||||
// {
|
||||
// toast.Opacity = 1.0 - (elapsed - (200 + durationMs)) / 200.0;
|
||||
// }
|
||||
// else // 終了処理
|
||||
// {
|
||||
// timer.Stop();
|
||||
// timer.Dispose();
|
||||
// toast.Close();
|
||||
// toast.Dispose();
|
||||
// }
|
||||
// };
|
||||
// // 3. 表示開始(ここを通った瞬間にメソッドは終了し、呼び出し元に戻ります)
|
||||
// toast.Show();
|
||||
// timer.Start();
|
||||
//}
|
||||
|
||||
//public static async Task ShowAsync(Form owner, string message, Color backColor, int durationMs = 3000)
|
||||
//{
|
||||
// // 1. フォームの作成
|
||||
// using (var toast = new Form
|
||||
// {
|
||||
// FormBorderStyle = FormBorderStyle.None,
|
||||
// StartPosition = FormStartPosition.Manual,
|
||||
// BackColor = backColor,
|
||||
// ShowInTaskbar = false,
|
||||
// TopMost = true,
|
||||
// Size = new Size(300, 60),
|
||||
// Opacity = 0
|
||||
// })
|
||||
// {
|
||||
// // フォーカスを奪わないための設定(WinAPIをラップしたCreateParamsの上書き)
|
||||
// // ※簡易的にリフレクションで設定するか、Formを継承したクラスを作るのが定石です
|
||||
// Label lbl = new Label
|
||||
// {
|
||||
// Text = message,
|
||||
// ForeColor = Color.White,
|
||||
// Font = new Font("MS UI Gothic", 10, FontStyle.Bold),
|
||||
// Dock = DockStyle.Fill,
|
||||
// TextAlign = ContentAlignment.MiddleCenter
|
||||
// };
|
||||
// toast.Controls.Add(lbl);
|
||||
// toast.Location = new Point(
|
||||
// owner.Location.X + owner.Width - toast.Width - 20,
|
||||
// owner.Location.Y + owner.Height - toast.Height - 20
|
||||
// );
|
||||
// // 表示(フォーカスを奪わずに表示)
|
||||
// toast.Show();
|
||||
// // フォーカスが移るのを防ぐための念押し(Activateさせない)
|
||||
// // 2. アニメーション(async/await の真骨頂)
|
||||
// for (int i = 0; i < 10; i++) { toast.Opacity += 0.1; await Task.Delay(10); }
|
||||
// await Task.Delay(durationMs);
|
||||
// for (int i = 0; i < 10; i++) { toast.Opacity -= 0.1; await Task.Delay(10); }
|
||||
// toast.Close();
|
||||
// }
|
||||
//}
|
||||
|
||||
public static async Task ShowAsync(Form owner, string message, Color backColor, int durationMs = 3000)
|
||||
{
|
||||
// 【重要】SignalRなどの別スレッドから呼ばれても安全なように、UIスレッドへ強制バトンタッチ
|
||||
if (owner.InvokeRequired)
|
||||
{
|
||||
owner.BeginInvoke(new Action(() => { _ = ShowAsync(owner, message, backColor, durationMs); }));
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. フォームの作成(usingは使わず、Closeに任せる)
|
||||
// フォーカスを奪わない(WS_EX_NOACTIVATE = 0x08000000)を仕込んだカスタムフォームをその場で定義
|
||||
var toast = new NoActivateForm
|
||||
{
|
||||
FormBorderStyle = FormBorderStyle.None,
|
||||
StartPosition = FormStartPosition.Manual,
|
||||
BackColor = backColor,
|
||||
ShowInTaskbar = false,
|
||||
TopMost = true,
|
||||
Size = new Size(300, 60),
|
||||
Opacity = 0
|
||||
};
|
||||
|
||||
Label lbl = new Label
|
||||
{
|
||||
Text = message,
|
||||
ForeColor = Color.White,
|
||||
Font = new Font("MS UI Gothic", 10, FontStyle.Bold),
|
||||
Dock = DockStyle.Fill,
|
||||
TextAlign = ContentAlignment.MiddleCenter
|
||||
};
|
||||
toast.Controls.Add(lbl);
|
||||
|
||||
// 右下のベストポジションに配置(オーナーフォーム基準)
|
||||
toast.Location = new Point(
|
||||
owner.Location.X + owner.Width - toast.Width - 20,
|
||||
owner.Location.Y + owner.Height - toast.Height - 20
|
||||
);
|
||||
|
||||
// 表示(フォーカスを絶対に奪わない)
|
||||
toast.Show();
|
||||
|
||||
// 2. アニメーション(async/await の真骨頂!)
|
||||
for (int i = 0; i < 10; i++) { toast.Opacity += 0.1; await Task.Delay(10); }
|
||||
|
||||
await Task.Delay(durationMs);
|
||||
|
||||
for (int i = 0; i < 10; i++) { toast.Opacity -= 0.1; await Task.Delay(10); }
|
||||
|
||||
// 閉じると同時に、WinFormsが自動でメモリを綺麗に解放(Dispose)してくれます
|
||||
toast.Close();
|
||||
}
|
||||
}
|
||||
|
||||
// 【職人技】フォーカスを絶対に奪わないフォーム(CreateParamsの上書き)
|
||||
public class NoActivateForm : Form
|
||||
{
|
||||
protected override CreateParams CreateParams
|
||||
{
|
||||
get
|
||||
{
|
||||
CreateParams cp = base.CreateParams;
|
||||
cp.ExStyle |= 0x08000000; // WS_EX_NOACTIVATE(クリックしてもフォーカスが移らない魔法のフラグ)
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user