C#實現(xiàn)移動窗體的兩種共方法
引言
在C#Form窗體設(shè)計中,如果我們不需要使用默認邊框設(shè)計自己個性化的窗體(FromBorderStyle=none時),這時候你會發(fā)現(xiàn)拖動窗體的功能就沒有了,這里需要自己構(gòu)建方法讓用戶可以拖動整個窗體,這里我們使用前輩的方法實現(xiàn)和描述一下。即可以通過窗體中的控件事件來控制拖動整個窗體,也可以通過系統(tǒng)API 捕獲鼠標拖動窗體,下面就介紹這兩方法。
一、通過控件事件移動窗體
1、創(chuàng)建窗體界面
在項目中添加窗體,我這里添加一個窗體test1,并添加一個label作為操作目標,添加上自己的文字,顏色突顯一下。
2、添加控件事件
通過屬性欄中的事件添加三個事件,分別是鼠標的MouseDown、MouseMove以及MouseUp事件。
3、添加代碼
在窗體代碼中添加代碼,詳見下面代碼和注釋。
//鼠標是否拖動標志 private bool isDragging = false; //鼠標按下時的位置 private Point downPosition; //鼠標按下時的窗體位置 private Point lastFormPosition; /// <summary> /// 鼠標按下事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void label_MouseDown(object sender, MouseEventArgs e) { //判斷是否為鼠標左鍵按下 if (e.Button == MouseButtons.Left) { //置標志為true isDragging = true; //保存當前鼠標坐標 downPosition = Cursor.Position; //保存當前窗體坐標 lastFormPosition = this.Location; } } /// <summary> /// 鼠標移動事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void label_MouseMove(object sender, MouseEventArgs e) { //判斷鼠標左鍵是否按下 if (isDragging) { // 計算鼠標移動的偏移量 int moveX = Cursor.Position.X - downPosition.X; int moveY = Cursor.Position.Y - downPosition.Y; // 更新窗體的位置 this.Location = new Point(lastFormPosition.X + moveX, lastFormPosition.Y + moveY); } } /// <summary> /// 鼠標松開事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void label_MouseUp(object sender, MouseEventArgs e) { //如果是鼠標左鍵松開,則修改標志為false if (e.Button == MouseButtons.Left) { isDragging = false; } }
二、通過windowsAPI移動窗體
1、 構(gòu)建窗體和添加事件
構(gòu)建窗體和添加事件同上一個個方法,我就不詳細說明了,只是添加事件的主題更換成窗體test1。
2、代碼展示
構(gòu)建窗體和添加事件通過鼠標移動事件中,調(diào)用windows系統(tǒng)API的SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam)函數(shù),可以看到除控件外的部分都可以用來拖動整個窗體。
private const int HT_CAPTION = 0x2;//窗體標題 private const int WM_NCLBUTTONDOWN = 0xA1;//鼠標點擊的是非客戶區(qū) [DllImport("user32.dll")] public static extern bool ReleaseCapture(); [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); /// <summary> /// 窗體鼠標移動事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void test1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { //釋放鼠標捕獲 ReleaseCapture(); //非客戶區(qū)鼠標的拖動窗體消息 SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0); } }
三、其它方式
也可以直接通過系統(tǒng)鉤子, WndProc(ref Message m)重載實現(xiàn)。代碼如下:
internal static int WM_NCHITTEST = 0x84; internal static IntPtr HTCLIENT = (IntPtr)0x1; internal static IntPtr HTCAPTION = (IntPtr)0x2; internal static int WM_NCLBUTTONDBLCLK = 0x00A3; protected override void WndProc(ref Message m) { if (m.Msg == WM_NCLBUTTONDBLCLK) { return; } if (m.Msg == WM_NCHITTEST) { base.WndProc(ref m); if (m.Result == HTCLIENT) { m.HWnd = this.Handle; m.Result = HTCAPTION; } return; } base.WndProc(ref m); }
到此這篇關(guān)于C#移動窗體的兩種共方法的文章就介紹到這了,更多相關(guān)C#移動窗體內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c# DataTable與不同結(jié)構(gòu)實體類轉(zhuǎn)換的方法實例
這篇文章主要介紹了c#的DataTable與不同結(jié)構(gòu)實體類轉(zhuǎn)換的方法實例,在大數(shù)據(jù)量的情況下很實用,大家可以參考使用2013-11-11C# ArrayList、HashSet、HashTable、List、Dictionary的區(qū)別詳解
這篇文章主要介紹了C# ArrayList、HashSet、HashTable、List、Dictionary的區(qū)別的相關(guān)知識點內(nèi)容,有需要朋友們參考下。2019-08-08C#中的并發(fā)編程與.NET任務(wù)并行庫的使用示例和常見問題
在現(xiàn)代軟件開發(fā)中,.NET Framework通過引入任務(wù)并行庫(TPL)和并發(fā)集合類型,簡化了并發(fā)復(fù)雜性,提高程序的性能、可維護性和可擴展性,并發(fā)集合設(shè)計上允許多線程安全訪問,此外,TPL通過Task類簡化異步操作,正確使用這些工具可避免死鎖和競爭條件等常見問題2024-09-09