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

C# PictureBox 拖曳移動圖片完整範例:自訂游標與座標轉換

     編輯:關於C#

需求背景

在 WinForms 中實現圖片的滑鼠拖曳移動,不需重繪,僅調整 PictureBox.Location。關鍵在於座標系轉換(螢幕座標 ↔ 容器座標)與拖曳狀態管理。

完整程式碼

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

namespace WindowsApplication2
{
    public partial class Form1 : Form
    {
        // Base64 編碼的游標資料(省略完整字串)
        static string strDown = @"AAACAAEAICAAAAsACQAwAQAAFgAAACgAAAAgAAAAQAAAAAEAAQAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...";
        static string strUp = @"AAACAAEAICAAAAoACAAwAQAAFgAAACgAAAAgAAAAQAAAAAEAAQAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...";

        Cursor curUp = new Cursor(new MemoryStream(Convert.FromBase64String(strUp)));
        Cursor curDown = new Cursor(new MemoryStream(Convert.FromBase64String(strDown)));

        bool bDragging = false;
        Point pClicked;

        public Form1()
        {
            InitializeComponent();
            pictureBox1.Cursor = curUp;
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                bDragging = true;
                pClicked = new Point(e.X, e.Y); // 記錄滑鼠在 PictureBox 內的相對位置
                pictureBox1.Cursor = curDown;
            }
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (bDragging)
            {
                // 1. 取得滑鼠當前螢幕座標
                // 2. 轉為表單用戶區座標
                // 3. 減去點擊時的相對偏移,得到 PictureBox 新左上角
                Point screenPos = pictureBox1.PointToScreen(new Point(e.X, e.Y));
                Point clientPos = this.PointToClient(screenPos);
                clientPos.Offset(-pClicked.X, -pClicked.Y);
                pictureBox1.Location = clientPos;
            }
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            bDragging = false;
            pictureBox1.Cursor = curUp;
        }
    }
}

關鍵技術點解析

  1. 游標切換:使用 Base64 內嵌 .cur 資料,避免外部檔案相依。MouseDown 切換為「抓取」狀態,MouseUp 恢復。
  2. 座標轉換鏈:
    • e.X, e.Y:PictureBox 用戶區座標
    • PointToScreen → 螢幕絕對座標
    • PointToClient → 表單用戶區座標
    • Offset(-pClicked.X, -pClicked.Y) → 扣除點擊偏移,獲得 PictureBox 新 Location
  3. 拖曳旗標:bDragging 防止非拖曳時移動;pClicked 固定滑鼠在控件內的相對位置,避免控件「跳」到滑鼠左上角。

替代方案比較

  • WM_SYSCOMMAND + SC_MOVE:模擬標題列拖曳,適用於無框視窗移動,但對 PictureBox 等子控件效果較差(會有邊框閃爍)。
  • Control.Capture:設定 Capture = true 可接收滑鼠離開控件後的訊息,簡化邏輯,但需注意釋放捕獲。

結語

掌握座標系轉換(Screen ↔ Client ↔ Control)是 WinForms 拖曳功能的核心。本範例展示最基礎且穩健的實作,可直接套用至任何 Control 衍生類別。

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