65.9K
CodeProject 正在变化。 阅读更多。
Home

减少页面错误

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.73/5 (3投票s)

2018年12月26日

CPOL

1分钟阅读

viewsIcon

5715

downloadIcon

57

使用原生 GDI 将减少页面错误。

引言

我的应用程序出现大量的页面错误。根据我在线上找到的信息,这不太可能导致任何问题,但这引起了我的兴趣去调查:是什么导致了大量的页面错误,以及是否有办法减少它。

背景

几年前,我试图让我的12岁的儿子对编程感兴趣(抱歉,甚至保留了原始名称MyFirstGame)。因此,我们设计了一个简单的游戏。
请注意:这篇文章不是关于这个游戏 - 我只是用这个游戏来调查页面错误的数量。在玩游戏时,使用标准的.NET图形对象,你会得到大约25000个页面错误/秒。

Using the Code

代码有一个简单的棋盘(5行,4列)。正方形随机放置在每一行,玩家应该点击黑色正方形使其消失。如果你没有点击它,并且它到达底部,你就输了,如果你点击了白色正方形,你就输了。棋盘在Form1对象内的“Draw”方法中使用标准.NET绘制。

当你点击“使用GDI”时,会使用gdi32.dll - 在Draw2方法中。你会看到页面错误急剧减少。

(为了更容易观察,我每秒在屏幕上显示页面错误,无需打开任务管理器。)

此外,使用GDI绘制的平均速度大约快10倍。

Draw方法如下所示

private void Draw(Graphics g)
{
    if (checkBoxUseGDI.Checked)
    {
        Draw2(g);
        return;
    }

    graphics.Clear(Color.White);

    int left = 0;
    int top = board.Top;
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            Rectangle rect = new Rectangle(left, top, 100, 150);

            if (board.Cells[i, j] > -1)
            {
                graphics.FillRectangle(Brushes.Black, rect);
            }

            graphics.DrawRectangle(Pens.Black, rect);

            left += 100;
        }

        top += 150;
        left = 0;
    }
    g.DrawImage(bitmap, 0, 0);
}

Draw2方法如下所示

private void Draw2(Graphics g)
{
    IntPtr hdc2 = g.GetHdc();
    IntPtr hdc = GDI.CreateCompatibleDC(hdc2);
    IntPtr hBitmap = GDI.CreateCompatibleBitmap(hdc, 401, 601);
    GDI.SelectObject(hdc, hBitmap);
    IntPtr brushWhite = GDI.CreateSolidBrush(0xFFFFFF);
    GDI.FillRgn(hdc, GDI.CreateRectRgn(0, 0, 401, 601), brushWhite);
    GDI.DeleteObject(brushWhite);
    IntPtr brushBlack = GDI.CreateSolidBrush(0x0);

    int left = 0;
    int top = board.Top;
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            GDI.Rectangle(hdc, left, top, left + 101, top + 151);

            if (board.Cells[i, j] > -1)
            {
                GDI.FillRgn(hdc, GDI.CreateRectRgn(left, top, left + 101, top + 151), brushBlack);
            }

            left += 100;
        }

        top += 150;
        left = 0;
    }
    GDI.DeleteObject(brushBlack);

    GDI.BitBlt(hdc2, 0, 0, 401, 601, hdc, 0, 0, GDI.TernaryRasterOperations.SRCCOPY);
    g.ReleaseHdc(hdc2);

    GDI.DeleteDC(hdc);
    GDI.DeleteObject(hBitmap);
}

关注点

我发现这个网站很有帮助:http://pinvoke.net/default.aspx

历史

  • 2018年12月26日:初始版本
© . All rights reserved.