日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WinForm实现类似QQ停靠,显示隐藏过程添加特效效果

發布時間:2024/4/17 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WinForm实现类似QQ停靠,显示隐藏过程添加特效效果 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這可能是個老題長談的問題了,只是在項目中會用到這個效果,所以今天做個記錄。大家見了別噴我。在項目中的需求是這樣的。

打開程序,在屏幕的右下角會顯示一個窗體,一般情況下該窗體會隱藏停靠在右邊,只露出很小部分,當鼠標移動到這個很小部分時,窗體全部顯示,顯示過程是從右邊滑動到左邊,當鼠標離開窗體時,窗體需要隱藏在右邊,只露出很小部分,隱藏過程是從左邊滑動到右邊。

實現此類效果我碰到的連個難點是:1、如何判斷鼠標離開了窗體?2、窗體顯示隱藏過程中效果如何表現平滑(就是給人一種流暢感覺)?

1、判斷鼠標離開窗體我開始想的是在WndProc方法中來獲取鼠標坐標然后根據窗體的Location來判斷,可能是小弟愚笨,該方法沒有處理好,運行后界面卡住了。然后我只有用個計時器,每隔幾秒獲取一下鼠標坐標在根據窗體的Location來判斷。獲取坐標有個API方法GetCursorPos,有資料表明此方法是最優效率的,那我們就用它好了。

2、顯示隱藏效果開始想的也是改變窗體坐標來實現,但是這個方法做出來的效果比較差,畫面感覺不流暢,后來查到可以用API方法AnimateWindow來實現這個效果,因此我們來認識一下AnimateWindow()方法;

此方法需要傳遞三個參數:

第一個參數:傳入需要顯示特效的窗體的句柄。

第二個參數:完成特效所花時間,單位:毫秒,也就是說你可以指定多少時間內完成指定的特效

第三個參數:指定特效類型,此參數可以指定多個,多個之間用|隔開。這里列舉了一般的9個特效。有這9個基本夠用了。

關于這個方法的詳細資料我就不一一列舉了,大家在網上搜搜,很多資料的。下面進入正題。

1、建一個winform項目,命名:DockFormsApplication,名字大家可以自定義的。

2、建完后項目中會有個默認創建好的窗體Form1,修改Form1的text屬性為:“仿QQ停靠,加特效”

3、添加API方法AnimateWindow()和該方法需要的一些特效參數, 特效參數命名是我自己隨便命名的,大家就不要深究了,至于為什么要這么命名,我自己也不知道,反正能用就行

注意:AnimateWindow()方法需要引用using System.Runtime.InteropServices;

/// <summary>/// //從左到右/// </summary>public const Int32 AW_HOR_LEFT_RIGHT = 0x00000001;/// <summary>/// 從右到左/// </summary>private const Int32 AW_HOR_RIGHT_LEFT = 0x00000002;/// <summary>/// 從上到下/// </summary>private const Int32 AW_VER_UP_DOWN = 0x00000004;/// <summary>/// 從下到上/// </summary>private const Int32 AW_VER_DOWN_UP = 0x00000008;/// <summary>/// 從中間到四周/// </summary>private const Int32 AW_CENTER = 0x00000010;/// <summary>/// 隱藏窗口/// </summary>private const Int32 AW_HIDE = 0x00010000;/// <summary>/// 顯示窗口/// </summary>private const Int32 AW_ACTIVATE = 0x00020000;/// <summary>/// 使用滑動類型。缺省則為滾動動畫類型。當使用AW_CENTER標志時,這個標志就被忽略/// </summary>private const Int32 AW_SLIDE = 0x00040000;/// <summary>/// 改變透明度/// </summary>private const Int32 AW_BLEND = 0x00080000;/// <summary>/// 特效花費時間 單位:毫秒/// </summary>private int _speed = 500;[DllImport("user32.dll")]public static extern void AnimateWindow(IntPtr hwnd, int stime, int style);//顯示效果

3、添加API方法GetCursorPos用于獲取鼠標坐標。此方法需要傳入一個坐標對象。該對象是一個二維結構。存儲坐標的X值和Y值。

/// <summary>/// 鼠標坐標/// </summary>private Point _cursorPoint;//API獲取鼠標坐標[DllImport("user32.dll")]public static extern bool GetCursorPos(out Point pt);

4、設置窗體顯示在右下角,并且重寫WndProc方法禁止鼠標拖動和雙擊標題欄最大化

private void Form1_Load(object sender, EventArgs e){//設置窗體顯示位置 右下角int workY = Screen.PrimaryScreen.WorkingArea.Height - Height;int X = Screen.PrimaryScreen.Bounds.Width - Width;this.Location = new Point(X, workY);}//重寫WndProc方法,禁止拖動和雙擊標題欄最大化protected override void WndProc(ref Message m){if (m.Msg == 0x231){this.SuspendLayout();}else if (m.Msg == 0x232){this.ResumeLayout();}else if (m.Msg == 0xA1 && m.WParam.ToInt32() == 2)//禁止拖動 {return;}base.WndProc(ref m);}

后來發現,更改窗體屬性:FormBorderStyle值為:FixedSingle也可以達到禁止拖動的效果

5、因為要每隔幾秒獲取鼠標坐標判斷鼠標是否在窗體范圍內,因此需要一個計時器。考慮到性能神馬的,我比較喜歡使用System.Threading.Timer,下面就是計時器嗦必須的幾個變量

??? 注意:這里我需要說明一下,由于AnimateWindow()方法控制窗體特效只能窗體顯示和隱藏兩種狀態,每個特效完成后窗體要么隱藏,要么顯示,如何使特效過后窗體一直顯示,我想了個折中辦法,只要你隱藏了,我就再把你顯示出來,因此在計時器中需要對窗體進行操作,如此則需要跨線程訪問窗體,因此就需要使用委托了,然后Invoke就可以了。

//線程暫停時間 單位:毫秒private int _timespan = 1000;private System.Threading.Timer _timer;private delegate void LoadListDelegate();private LoadListDelegate _loaddelegate;

6、程序邏輯需要的幾個變量

/// <summary>/// 窗體是否顯示,true——顯示、false——隱藏/// </summary>private bool _isActive = true;/// <summary>/// 停靠在邊緣時,顯示窗體的寬度/// </summary>private const int _smallX = 5;

7、添加兩個方法,顯示窗體和隱藏窗體的兩個方法

/// <summary>/// 隱藏窗體/// </summary>private void SetHide(){if (_isActive){AnimateWindow(this.Handle, _speed, AW_HOR_LEFT_RIGHT | AW_SLIDE | AW_HIDE);int X = Screen.PrimaryScreen.Bounds.Width - _smallX;int Y = this.Location.Y;this.Location = new Point(X, Y);AnimateWindow(this.Handle, 10, AW_BLEND | AW_ACTIVATE);_isActive = false;}}/// <summary>/// 顯示窗體/// </summary>private void SetActivate(){if (!_isActive){AnimateWindow(this.Handle, 10, AW_BLEND | AW_HIDE);int X = Screen.PrimaryScreen.Bounds.Width - Width;int Y = this.Location.Y;this.Location = new Point(X, Y);AnimateWindow(this.Handle, _speed, AW_HOR_RIGHT_LEFT | AW_SLIDE | AW_ACTIVATE);_isActive = true;}}

8、添加方法,判斷鼠標是否在窗體范圍內,如果在范圍內,則顯示窗體,如果不在范圍內,則停靠在右邊并隱藏窗體

private void LoadControl(){#region 控制窗體顯示和隱藏//獲取當前鼠標坐標GetCursorPos(out _cursorPoint);//根據 窗體當前狀態,判斷窗體接下來是顯示還是隱藏。if (_isActive){//當前窗體為顯示,則接下來是隱藏//如果鼠標坐標不在窗體范圍內,則設置窗體隱藏,否則不處理if (_cursorPoint.X < this.Location.X || _cursorPoint.Y < this.Location.Y){SetHide();}}else{//當前窗體為隱藏,則接下來是顯示//如果鼠標坐標在窗體范圍內,則設置窗體顯示,否則不處理if (_cursorPoint.X >= this.Location.X && _cursorPoint.Y >= this.Location.Y){SetActivate();}}#endregion}

9、添加計時器,每隔1秒判斷當前鼠標位置,因為用到委托,因此需要在構造方法中添加一行代碼_loaddelegate = LoadControl;用于指定委托的方法:

private void Form1_Load(object sender, EventArgs e){//設置窗體顯示位置 右下角int workY = Screen.PrimaryScreen.WorkingArea.Height - Height;int X = Screen.PrimaryScreen.Bounds.Width - Width;this.Location = new Point(X, workY);//窗體打開的時候就開始計時器 BeginTimer();}private void BeginTimer(){TimerCallback tcBack = new TimerCallback(InvokTimer);_timer = new System.Threading.Timer(tcBack, null, 5000, _timespan);}private void InvokTimer(object state){if (this.InvokeRequired){this.Invoke(_loaddelegate);}}

10、為了窗體一打開和關閉時有特效顯示,需要重寫OnLoad方法和實現Form1_Closing方法

protected override void OnLoad(EventArgs e){base.OnLoad(e);//從右到左滑動AnimateWindow(this.Handle, _speed, AW_HOR_RIGHT_LEFT | AW_SLIDE | AW_ACTIVATE);}private void Form1_FormClosing(object sender, FormClosingEventArgs e){//淡出效果AnimateWindow(this.Handle, 1000, AW_BLEND | AW_HIDE);}

到此,所有代碼編寫完成,如果想要有更好的體驗,可以設置一下窗體的以下屬性值:

this.MaximizeBox = false;//取消最大化按鈕this.MinimizeBox = false;//取消最小化按鈕this.ShowInTaskbar = false;//任務欄不顯示窗體圖標this.TopMost = false;//設置窗體總是顯示在最前面


完整代碼如下:

全部代碼 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Threading;namespace DockFormsApplication {public partial class Form1 : Form{#region 屬性 API特效窗體顯示和隱藏/// <summary>/// //從左到右/// </summary>public const Int32 AW_HOR_LEFT_RIGHT = 0x00000001;/// <summary>/// 從右到左/// </summary>private const Int32 AW_HOR_RIGHT_LEFT = 0x00000002;/// <summary>/// 從上到下/// </summary>private const Int32 AW_VER_UP_DOWN = 0x00000004;/// <summary>/// 從下到上/// </summary>private const Int32 AW_VER_DOWN_UP = 0x00000008;/// <summary>/// 從中間到四周/// </summary>private const Int32 AW_CENTER = 0x00000010;/// <summary>/// 隱藏窗口/// </summary>private const Int32 AW_HIDE = 0x00010000;/// <summary>/// 顯示窗口/// </summary>private const Int32 AW_ACTIVATE = 0x00020000;/// <summary>/// 使用滑動類型。缺省則為滾動動畫類型。當使用AW_CENTER標志時,這個標志就被忽略/// </summary>private const Int32 AW_SLIDE = 0x00040000;/// <summary>/// 改變透明度/// </summary>private const Int32 AW_BLEND = 0x00080000;/// <summary>/// 特效花費時間 單位:毫秒/// </summary>private int _speed = 500;[DllImport("user32.dll")]public static extern void AnimateWindow(IntPtr hwnd, int stime, int style);//顯示效果/// <summary>/// 鼠標坐標/// </summary>private Point _cursorPoint;//API獲取鼠標坐標[DllImport("user32.dll")]public static extern bool GetCursorPos(out Point pt);//線程暫停時間 單位:毫秒private int _timespan = 1000;private System.Threading.Timer _timer;private delegate void LoadListDelegate();private LoadListDelegate _loaddelegate;/// <summary>/// 窗體是否顯示,true——顯示、false——隱藏/// </summary>private bool _isActive = true;/// <summary>/// 停靠在邊緣時,顯示窗體的寬度/// </summary>private const int _smallX = 5;#endregionpublic Form1(){InitializeComponent();this.MaximizeBox = false;//取消最大化按鈕this.MinimizeBox = false;//取消最小化按鈕this.ShowInTaskbar = false;//任務欄不顯示窗體圖標this.TopMost = false;//設置窗體總是顯示在最前面 _loaddelegate = LoadControl;}private void Form1_Load(object sender, EventArgs e){//設置窗體顯示位置 右下角int workY = Screen.PrimaryScreen.WorkingArea.Height - Height;int X = Screen.PrimaryScreen.Bounds.Width - Width;this.Location = new Point(X, workY);//窗體打開的時候就開始計時器 BeginTimer();}protected override void OnLoad(EventArgs e){base.OnLoad(e);//從右到左滑動AnimateWindow(this.Handle, _speed, AW_HOR_RIGHT_LEFT | AW_SLIDE | AW_ACTIVATE);}private void Form1_FormClosing(object sender, FormClosingEventArgs e){_timer.Dispose();//淡出效果AnimateWindow(this.Handle, 1000, AW_BLEND | AW_HIDE);}//重寫WndProc方法,禁止拖動和雙擊標題欄最大化protected override void WndProc(ref Message m){if (m.Msg == 0x231){this.SuspendLayout();}else if (m.Msg == 0x232){this.ResumeLayout();}else if (m.Msg == 0xA1 && m.WParam.ToInt32() == 2)//禁止拖動 {return;}base.WndProc(ref m);}/// <summary>/// 隱藏窗體/// </summary>private void SetHide(){if (_isActive){AnimateWindow(this.Handle, _speed, AW_HOR_LEFT_RIGHT | AW_SLIDE | AW_HIDE);int X = Screen.PrimaryScreen.Bounds.Width - _smallX;int Y = this.Location.Y;this.Location = new Point(X, Y);AnimateWindow(this.Handle, 10, AW_BLEND | AW_ACTIVATE);_isActive = false;}}/// <summary>/// 顯示窗體/// </summary>private void SetActivate(){if (!_isActive){AnimateWindow(this.Handle, 10, AW_BLEND | AW_HIDE);int X = Screen.PrimaryScreen.Bounds.Width - Width;int Y = this.Location.Y;this.Location = new Point(X, Y);AnimateWindow(this.Handle, _speed, AW_HOR_RIGHT_LEFT | AW_SLIDE | AW_ACTIVATE);_isActive = true;}}private void LoadControl(){#region 控制窗體顯示和隱藏//獲取當前鼠標坐標GetCursorPos(out _cursorPoint);//根據 窗體當前狀態,判斷窗體接下來是顯示還是隱藏。if (_isActive){//當前窗體為顯示,則接下來是隱藏//如果鼠標坐標不在窗體范圍內,則設置窗體隱藏,否則不處理if (_cursorPoint.X < this.Location.X || _cursorPoint.Y < this.Location.Y){SetHide();}}else{//當前窗體為隱藏,則接下來是顯示//如果鼠標坐標在窗體范圍內,則設置窗體顯示,否則不處理if (_cursorPoint.X >= this.Location.X && _cursorPoint.Y >= this.Location.Y){SetActivate();}}#endregion}private void BeginTimer(){TimerCallback tcBack = new TimerCallback(InvokTimer);_timer = new System.Threading.Timer(tcBack, null, 5000, _timespan);}private void InvokTimer(object state){if (this.InvokeRequired){this.Invoke(_loaddelegate);}}} }

轉載于:https://www.cnblogs.com/springSky/archive/2013/02/04/2891345.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的WinForm实现类似QQ停靠,显示隐藏过程添加特效效果的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。