在带有背景图像的表单上高效移动WinForms按钮

Mar*_*tim 0 c# winforms

我正在创建一个工业触摸屏计算机的应用程序,没有硬件吹嘘.该触摸屏计算机的操作者应该能够在具有背景图像的表格上解锁和拖动按钮.

但是,正如许多人已经知道的那样,使用背景图像移动父控件上的控件并不漂亮.拖动速度很慢,而不是经历平滑的拖动,操作员将在鼠标指针唤醒时看到一个按钮跳过,当您将指针移动到屏幕上时.

这是移动按钮的当前代码:

private void btnButton_MouseMove(object sender, MouseEventArgs e)
{
    // Do not proceed unless it is allowed to move buttons
    if (!this._AllowButtonsToBeMoved)
        return;

    if (this._IsBeingDragged)
    {
        var btn = (sender as Button);
        var newPoint = btn.PointToScreen(new Point(e.X, e.Y));
        newPoint.Offset(this._ButtonOffset);
        btn.Location = newPoint;
    }
}
Run Code Online (Sandbox Code Playgroud)

我不打算解决这个确切的问题,我宁愿消除它以节省一些时间.为了消除这种情况,我希望实现的是一种更有效的方式来移动盒子.我想移动一个虚线矩形而不是按钮,然后将它放在我想要按钮的位置必须比在屏幕上拖动按钮更有效,导致谁知道有多少重绘操作.

有没有人有更好的建议?如果没有,那么我非常感谢有关如何在屏幕上创建和移动这个矩形的指示,因为我很难找到关于如何在好的Google上进行此操作的良好信息来源.

更新,26/11/13

我正在尝试Luaan关于覆盖表单的OnPaint的建议,但是我不确定如何在此代码中添加按钮的渲染.有任何想法吗?

protected override void OnPaint(PaintEventArgs e)
{
    if (_IsBeingDragged)
    {
        e.Graphics.DrawImage(this._FormPaintBuffer, new Point(0, 0));
    }
    else
    {
        base.OnPaint(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 5

这是Winforms程序员友好的标准情况.任何游戏程序员都要特别注意的细节,但很容易错过.它允许你设置一个BackgroundImage,它会占用你扔的任何东西.除非您需要快速渲染图像,否则通常可以正常工作.就像你在这种情况下做的那样.

你需要做两件事才能让它快50倍:

  • 自己调整位图大小以适合表单的ClientSize,因此每次需要绘制图像时都不必重复进行.默认的Graphics.InterpolationMode属性值可以生成非常漂亮的图像,但它并不便宜.请注意,这可能会占用大量内存,因为它不会自动完成.

  • 注意图像的像素格式.只有一个可以快速绘制,可以直接与视频适配器连接,而不会将每个像素的值转换为帧缓冲区格式.这是过去10多年来使用的所有视频适配器上的PixelFormat.Format32bppPArgb.差别很大,它比其他所有产品快十倍.您永远不会从使用绘图程序创建的位图中获取该格式,因此需要显式转换它.再次注意记忆命中.

要获得两者,只需要一点点代码:

private static Bitmap Resample(Image img, Size size) {
    var bmp = new Bitmap(size.Width, size.Height, 
                         System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
    using (var gr = Graphics.FromImage(bmp)) {
        gr.DrawImage(img, new Rectangle(Point.Empty, size));
    }
    return bmp;
}
Run Code Online (Sandbox Code Playgroud)

在不太可能的情况下,你仍然有绘画痕迹或口吃,你需要考虑一个非常不同的方法.就像在Winforms设计师中使用的一样.您可以在原始图层上使用图层,一个额外的无边框透明窗口.你得到一个TransparencyKey属性.