1

I want to draw grid as in the below picture.enter image description here

I know a trick to draw this by draw 6 vertical and horizontal lines instead of 6 x 6 small rectangle.

But if I want to have smaller zoom (zoom for viewing picture), the lines are many. For example, say my view window is of size 800 x 600 and viewing a picture of size 400 x 300 (so zoom in is 2). There will be 400 x 300 rectangle of size 2 x 2 (each rectangle represents a pixel).

If I draw each cell (in a loop, say 400 x 300 times), it is very slow (when I move the window...). Using the trick solves the problem.

By I am still curious if there is a better way to do this task in winapi, GDI(+). For example, a function like DrawGrid(HDC hdc, int x, int y, int numOfCellsH, int numOfCellsV)?

A further question is: If I don't resize, move the window or I don't change the zoom in, the grid won't be changed. So even if I update the picture continuously (capture screen), it is uncessary to redraw the grid. But I use StretchBlt and BitBlt to capture the screen (to memory DC then hdc of the window), if I didn't redraw the grid in memory DC, then the grid will disappear. Is there a way to make the grid stick there and update the bitmap of the screen capture?

ps: This is not a real issue. Since I want to draw the grid when zoom is not less than 10 (so each cell is of size 10 x 10 or larger). In this case, there will be at most 100 + 100 = 200 lines to draw and it is fast. I am just curious if there is a faster way.

4

2 回答 2

0

您是否考虑过使用CreateDIBSection,这将允许您使用指针,以便您可以快速操作 R、G、B 值,例如以下创建 256x256x24 位图并以 64 像素间隔绘制绿色方块:

BITMAPINFO BI = {0};
BITMAPINFOHEADER &BIH = BI.bmiHeader;
BIH.biSize = sizeof(BITMAPINFOHEADER);
BIH.biBitCount  = 24;
BIH.biWidth     = 256;
BIH.biHeight    = 256;
BIH.biPlanes    = 1;
LPBYTE pBits = NULL;
HBITMAP hBitmap = CreateDIBSection(NULL, &BI, DIB_RGB_COLORS, (void**) &pBits, NULL, 0);
LPBYTE pDst = pBits;
for (int y = 0; y < 256; y++)
{
    for (int x = 0; x < 256; x++)
    {
        BYTE R = 0;
        BYTE G = 0;
        BYTE B = 0;
        if (x % 64 == 0) G = 255;
        if (y % 64 == 0) G = 255;
        *pDst++ = B;
        *pDst++ = G;
        *pDst++ = R;
    }
}
HDC hMemDC = CreateCompatibleDC(NULL);
HGDIOBJ hOld = SelectObject(hMemDC, hBitmap);
BitBlt(hdc, 0, 0, 256, 256, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOld);
DeleteDC(hMemDC);
DeleteObject(hBitmap);
于 2012-09-07T12:38:59.967 回答
0

一般来说,这类图形操作的主要限制因素是填充率和函数调用的数量。

填充率是机器改变像素值的速度。通常,blit(复制矩形区域)非常快,因为它们经过高度优化并且旨在以缓存友好的顺序访问内存。但是一个 blit 会触及该区域中的所有像素。如果您要过度绘制或者如果这些像素中的大多数并不真正需要更改,那么仅绘制您需要的像素可能会更有效,即使这对缓存不太友好。

如果您通过制作 n 个东西来绘制 n 个基元,那么随着 n 变大,这可能是一个限制因素,并且寻找一个可以让您一次绘制多条(或全部)线的 API 调用可能是有意义的。

您的“技巧”演示了这两种优化。与 100 个矩形相比,绘制 20 条线的调用次数更少,而且它触及的像素也少得多。随着窗口的增长或网格大小的减小,线条方法的调用次数和触摸的像素都将线性增加,而矩形方法将增长为 n^2。

在触及最小像素数方面,我认为您不能做得更好。但我想如果你要画很多线,函数调用的数量可能会成为一个因素。我不知道 GDI+,但在普通的 GDI 中,有类似的函数PolylinePolyPolyline可以让你在一次调用中绘制多条线。

于 2012-09-07T16:29:23.813 回答