2013/02/28

C#.Net 拖曳視窗

C#.NET 拖曳視窗指南

在 C#.NET Windows Forms 應用程式中,默認情況下視窗只能透過標題欄拖曳。但如果我們希望讓整個視窗可被拖動(例如無標題欄視窗),可以使用 MouseDownMouseMoveMouseUp 事件來實現。


1. 使用 MouseDown 事件拖曳視窗

C# 允許透過 User32.dll 提供的 SendMessageReleaseCapture 方法來模擬視窗拖動行為。

1.1 SendMessage 方法

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class DraggableForm : Form
{
    [DllImport("user32.dll")]
    private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    [DllImport("user32.dll")]
    private static extern bool ReleaseCapture();

    private const int WM_NCLBUTTONDOWN = 0xA1;
    private const int HTCAPTION = 0x2;

    public DraggableForm()
    {
        this.MouseDown += new MouseEventHandler(Form_MouseDown);
    }

    private void Form_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            ReleaseCapture();
            SendMessage(this.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
        }
    }
}

這段代碼的作用是:

  • ReleaseCapture():釋放當前視窗的滑鼠控制權。
  • SendMessage():向視窗發送移動請求,使其能夠隨滑鼠拖曳移動。
  • WM_NCLBUTTONDOWN:模擬滑鼠點擊標題欄的行為。

2. 無標題欄視窗拖曳

如果你的 Form 設置了 FormBorderStyle = None(無邊框模式),則可以使用 MouseMove 來進一步控制拖動。

using System;
using System.Drawing;
using System.Windows.Forms;

public class DraggableForm : Form
{
    private Point mouseOffset;
    private bool isMouseDown = false;

    public DraggableForm()
    {
        this.FormBorderStyle = FormBorderStyle.None;
        this.MouseDown += new MouseEventHandler(Form_MouseDown);
        this.MouseMove += new MouseEventHandler(Form_MouseMove);
        this.MouseUp += new MouseEventHandler(Form_MouseUp);
    }

    private void Form_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            mouseOffset = new Point(e.X, e.Y);
            isMouseDown = true;
        }
    }

    private void Form_MouseMove(object sender, MouseEventArgs e)
    {
        if (isMouseDown)
        {
            Point newLocation = this.PointToScreen(new Point(e.X, e.Y));
            this.Location = new Point(newLocation.X - mouseOffset.X, newLocation.Y - mouseOffset.Y);
        }
    }

    private void Form_MouseUp(object sender, MouseEventArgs e)
    {
        isMouseDown = false;
    }
}

這段代碼的作用是:

  • MouseDown:記錄滑鼠的初始位置。
  • MouseMove:根據滑鼠移動更新視窗位置。
  • MouseUp:結束拖動。

3. 結論

透過 SendMessageMouseMove 事件,我們可以輕鬆地在 C# Windows Forms 應用程式中實現 拖曳視窗 的功能,特別適用於無標題欄的自定義 UI。希望這篇文章能幫助你理解並實作 C# 拖曳視窗的技術。


參考資料