首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# WinForms 實作 MSN 風格視窗抖動特效

     編輯:關於C#

原理簡析

視窗抖動本質:快速隨機位移 Form.Left/Top,視覺上產生「震動」感覺。兩種常見節奏:

  1. 單步歸零:每次位移後立即復原,頻率極高,感覺像「原地顫抖」。
  2. 累積位移後歸零:連續位移形成軌跡,最後才復原,感覺像「被撞擊後彈回」。

完整實作程式碼


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

注意事項與最佳實務

  • 多螢幕:抖動可能移出螢幕可見區,建議 `Screen.GetWorkingArea(this)` 邊界檢查。
  • DPI 感知:高 DPI 下像素幅度需乘以縮放比例。
  • 無障礙:提供關閉動畫選項 (系統設定 `VisualEffects` 或應用程式內部旗標)。
  • 效能:頻繁設定 `Location` 觸發 `WM_WINDOWPOSCHANGED` 重繪,過度使用可能閃爍,`DelayMs ≥ 10` 通常足夠。

WPF 版本提示


// 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` 非阻塞節奏控制**。掌握取消權杖、緩動函數、邊界保護等細節,即能打造專業級的互動特效。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved