.Net Winforms 图片框自定义拖拽很麻烦

.Net Winforms picture box custom drag is twitchy

我正在制作一个应用程序,我在其中加载了一堆 256x256 像素的地图块,并用 magick.net 将它们拼接在一起,然后将它们显示在图片框中。我添加了一个使用图片框控件上的鼠标事件来旋转图像(并像我一样加载新图片块)的功能,如下所示:

// Set true when mouse should slew the picture in the picture box
private bool isSlewing = false;
// last position of the mouse in map space when slewing
private float lastX = 0;
private float lastY = 0;

private void Pb_MouseMove(object sender, MouseEventArgs e)
{
    // slew while mouse is down.
    if (isSlewing)
    {
        Tuple<float, float> mouseMapCoordinates = MouseToMap(e.X, e.Y);

        Slew(mouseMapCoordinates.Item1 - lastX, mouseMapCoordinates.Item2 - lastY);
        lastX = mouseMapCoordinates.Item1;
        lastY = mouseMapCoordinates.Item2;
    }
}

private void Pb_MouseDown(object sender, MouseEventArgs e)
{
    isSlewing = true;
    Tuple<float, float> mouseMapCoordinates = MouseToMap(e.X, e.Y);

    lastX = mouseMapCoordinates.Item1;
    lastY = mouseMapCoordinates.Item2;
}

private void Pb_MouseUp(object sender, MouseEventArgs e)
{
    isSlewing = false;
}

// Slews map image by dx and dY
public void Slew(float dX, float dY)
{
    X -= dX;
    Y -= dY;
}

// Converts mouse coordinates into map coordinates
private Tuple<float,float> MouseToMap(int mouseX, int mouseY)
{
    // works
}

X 和 Y 是通过将布尔值 needsUpdate 设置为 true 使图片框无效的属性。计时器是 运行 并且每 200 毫秒调用一次更新函数,该函数基于 X 和 Y 构建图片。还有一个缩放功能,但现在不重要,而且工作正常。

问题是,当我单击并拖动地图时,原则上它可以正常工作,但有时地图会“跳”回之前的鼠标位置。

我只是不知道如何着手找出导致它的原因或如何解决它。
我希望整个程序开始时响应更快一些,感觉很迟钝,这就是为什么我首先引入计时器的原因,这样它就不会在我移动时每秒对每个小变化进行数十次更新鼠标一点点。

我认为这与某种竞争条件有关,即在一个转换和下一个转换之间设置 lastXlastY,并在两者之间更新绘图。更新函数需要几毫秒才能完成,因为它从磁盘加载图像并合成它们,最后将它们绘制回图片框。

完整代码可在 github 获得。地图数据不包括在内,但可以使用资产中的脚本下载。为了进行测试,我建议从那里的 json 文件中删除除一张地图之外的所有地图。所有地图数据总共约3GB。

我尝试在 Pb_MouseMove 中的 if 语句块周围放置 lock(),但这没有任何帮助。

问题在于将鼠标坐标转换为 slew 之外的地图 space,因为地图 space 会随着视口移动。要解决此问题,请将原始鼠标位置保存在 lastXlastY 中,将鼠标坐标的原始增量放入 slew 函数中,然后乘以比例因子。比例因子是每个像素使用多少个地图坐标单位。