視窗抖動本質:快速隨機位移 Form.Left/Top,視覺上產生「震動」感覺。兩種常見節奏:
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace FormShakeDemo
{
public partial class MainForm : Form
{
private readonly Random _rnd = new Random();
private const int ShakeAmplitude = 10; // 抖動幅度 (像素)
private const int ShakeCount = 20; // 抖動次數
private const int DelayMs = 15; // 幀間隔 (ms)
public MainForm()
{
InitializeComponent();
}
// 模式 1:單步歸零 (MSN 風格)
private void btnShake1_Click(object sender, EventArgs e)
{
var original = Location;
for (int i = 0; i < ShakeCount; i++)
{
int dx = _rnd.Next(-ShakeAmplitude, ShakeAmplitude + 1);
int dy = _rnd.Next(-ShakeAmplitude, ShakeAmplitude + 1);
Location = new Point(original.X + dx, original.Y + dy);
Thread.Sleep(DelayMs); // 簡易阻塞,UI 凍結
Location = original; // 立即復原
}
}
// 模式 2:累積軌跡後歸零 (彈性感)
private async void btnShake2_Click(object sender, EventArgs e)
{
var original = Location;
Point current = original;
for (int i = 0; i < ShakeCount; i++)
{
int dx = _rnd.Next(-ShakeAmplitude, ShakeAmplitude + 1);
int dy = _rnd.Next(-ShakeAmplitude, ShakeAmplitude + 1);
current = new Point(current.X + dx, current.Y + dy);
Location = current;
await Task.Delay(DelayMs); // 非阻塞,UI 保持回應
}
Location = original; // 最後彈回
}
// 進階:非阻塞 + 取消權杖 + 緩動函數
private CancellationTokenSource _cts;
private async void btnShakeAdvanced_Click(object sender, EventArgs e)
{
_cts?.Cancel(); // 取消前一次
_cts = new CancellationTokenSource();
var token = _cts.Token;
var original = Location;
Point current = original;
try
{
for (int i = 0; i < ShakeCount; i++)
{
token.ThrowIfCancellationRequested();
int dx = _rnd.Next(-ShakeAmplitude, ShakeAmplitude + 1);
int dy = _rnd.Next(-ShakeAmplitude, ShakeAmplitude + 1);
current = new Point(current.X + dx, current.Y + dy);
Location = current;
await Task.Delay(DelayMs, token);
}
}
catch (OperationCanceledException) { /* 忽略 */ }
finally
{
if (!token.IsCancellationRequested) Location = original;
}
}
}
}
| 技術 | 說明 |
|---|---|
Form.Location | 設定視窗左上角螢幕座標,立即生效。 |
Thread.Sleep | 阻塞 UI 執行緒,簡單但會凍結介面 (模式 1)。 |
await Task.Delay | 非阻塞等待,釋放 UI 執行緒處理重繪/輸入 (模式 2/進階)。 |
CancellationToken | 支援中途取消抖動 (如使用者關閉視窗)。 |
| 隨機範圍 | Next(-A, A+1) 產生 [-A, A] 整數,含負值雙向抖動。 |
// 正弦波衰減:幅度隨時間遞減
double progress = (double)i / ShakeCount;
double amplitude = ShakeAmplitude * Math.Sin(progress * Math.PI) * (1 - progress);
int dx = (int)(_rnd.NextDouble() * 2 - 1) * amplitude;
// ... 同理 dy
// WPF 視窗抖動
var original = new Point(Left, Top);
for (int i = 0; i < count; i++)
{
Left = original.X + rnd.Next(-A, A+1);
Top = original.Y + rnd.Next(-A, A+1);
await Task.Delay(ms);
}
Left = original.X; Top = original.Y;
視窗抖動是提升使用者體驗 (新訊息提醒、錯誤警示) 的經典小技巧。核心在於 **`Location` 隨機位移 + `Task.Delay` 非阻塞節奏控制**。掌握取消權杖、緩動函數、邊界保護等細節,即能打造專業級的互動特效。