You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C# Windows Forms复刻可移动且关联文本框的选中方块功能?

实现方案:可选中、方向键移动的自定义WinForms方块控件

一、自定义方块控件核心实现

你的思路是对的,创建继承自Control的自定义控件是最优方案,以下是核心代码:

public class DraggableSquare : Control
{
    public bool IsSelected { get; set; }

    public DraggableSquare()
    {
        Size = new Size(40, 40);
        BackColor = Color.LightBlue;
        // 开启控件的选中与焦点支持,才能响应键盘事件
        SetStyle(ControlStyles.Selectable, true);
        TabStop = true;
    }

    // 重绘逻辑:选中时显示红色边框
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if (IsSelected)
        {
            using (var pen = new Pen(Color.Red, 2))
            {
                e.Graphics.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);
            }
        }
    }

    // 鼠标点击时标记选中并获取焦点
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        IsSelected = true;
        Focus();
        Invalidate(); // 触发重绘更新选中状态
    }

    // 方向键移动逻辑
    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        if (!IsSelected) return;

        int step = 5; // 每次移动步长
        switch (e.KeyCode)
        {
            case Keys.Up: Top -= step; break;
            case Keys.Down: Top += step; break;
            case Keys.Left: Left -= step; break;
            case Keys.Right: Left += step; break;
        }
        // 触发位置变化事件,用于同步文本框
        PositionChanged?.Invoke(this, EventArgs.Empty);
    }

    // 自定义位置变化事件
    public event EventHandler PositionChanged;
}

二、双向绑定文本框与方块位置

在主窗体中完成绑定逻辑,实现位置的双向同步:

1. 初始化控件

public partial class MainForm : Form
{
    private DraggableSquare _square;
    private TextBox _posTextBox;

    public MainForm()
    {
        InitializeComponent();
        InitControls();
    }

    private void InitControls()
    {
        // 创建并添加方块
        _square = new DraggableSquare();
        _square.Location = new Point(100, 100);
        _square.PositionChanged += OnSquarePositionChanged;
        Controls.Add(_square);

        // 创建并添加文本框
        _posTextBox = new TextBox();
        _posTextBox.Location = new Point(100, 200);
        _posTextBox.Size = new Size(150, 25);
        _posTextBox.Text = $"X:{_square.Left}, Y:{_square.Top}";
        _posTextBox.LostFocus += OnTextBoxLostFocus;
        Controls.Add(_posTextBox);
    }
}

2. 方块位置变化同步到文本框

private void OnSquarePositionChanged(object sender, EventArgs e)
{
    _posTextBox.Text = $"X:{_square.Left}, Y:{_square.Top}";
}

3. 文本框输入同步到方块位置

private void OnTextBoxLostFocus(object sender, EventArgs e)
{
    // 解析文本框内容(格式示例:X:100, Y:200)
    string input = _posTextBox.Text.Trim();
    string[] parts = input.Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries);
    if (parts.Length != 2) return;

    if (int.TryParse(parts[0].Replace("X:", ""), out int x) &&
        int.TryParse(parts[1].Replace("Y:", ""), out int y))
    {
        _square.Location = new Point(x, y);
        _square.Invalidate();
    }
}

三、多方块场景补充(可选)

如果存在多个方块,需在窗体中管理选中状态,点击空白处取消所有选中:

protected override void OnMouseDown(MouseEventArgs e)
{
    base.OnMouseDown(e);
    bool clickOnSquare = Controls.OfType<DraggableSquare>()
        .Any(s => s.ClientRectangle.Contains(s.PointToClient(e.Location)));
    if (!clickOnSquare)
    {
        foreach (var square in Controls.OfType<DraggableSquare>())
        {
            square.IsSelected = false;
            square.Invalidate();
        }
    }
}

关键注意点

  • 必须开启ControlStyles.Selectable并设置TabStop = true,控件才能获取焦点响应键盘事件。
  • 位置变化时触发自定义事件,确保文本框能实时同步。
  • 文本框解析要做异常处理,避免非法输入导致程序崩溃。

内容的提问来源于stack exchange,提问作者user20593243

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:33:09