我试图更好地理解Visual C ++的怪癖。因此,我来到舞台,我制作一个以空窗口开始的程序,但当你点击时,会出现一个红色和蓝色方块的检查板(它对眼睛不好,但是有用)。如果再次单击它们,方块也会在两种颜色之间切换。每个正方形是100x100像素,我在我的项目文件夹中有他们的图像文件(我知道我可以使用BitBlt
的最后两个整数agruments来使用半蓝色,半红色的单个图像,因此不需要toPaint
,但这不是问题)
这就是我现在的绘画例程(并且它工作正常,无论这里未声明的是全局变量):
case WM_PAINT:
{
// 'HDC hdc' declared before the switch statement
// 'PAINTSTRUCT ps' declared before the switch statement
// 'hWnd' is the first argument to WndProc()
hdc = BeginPaint(hWnd, &ps);
HBITMAP toPaint = NULL;
BITMAP bm;
// 'xcor' and 'ycor' are the coordinates of the last left-click
// 'int counters[][]' keeps track of the number of left-clicks in each square
// 'blue' and 'red' are HBITMAPs initialized in case WM_CREATE
if (counters[xcor / 100][ycor / 100] % 2 == (xcor / 100 + ycor / 100) % 2)
toPaint = blue;
else
toPaint = red;
HDC hdcMem = CreateCompatibleDC(hdc);
HGDIOBJ hbmOld = SelectObject(hdcMem, toPaint);
GetObject(toPaint, sizeof(bm), &bm);
BitBlt(hdc, xcor - xcor % 100, ycor - ycor % 100, 100, 100, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
EndPaint(hWnd, &ps);
break;
}
现在,每当我调整窗口大小时,无论是最大化还是只是拖动边缘,一切都会被重新绘制,并且由于只存储了一个左键单击,它只会绘制一个正方形,其余的将返回默认为灰色。因此,我决定抓住WM_SIZE
案例,并重新绘制已经绘制到那一点的所有正方形:
case WM_SIZE:
hdc = BeginPaint(hWnd, &ps);
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
// checks whether that square has been drawn before
if (counters[i][j] == 0)
continue;
HBITMAP toPaint = NULL;
BITMAP bm;
if (counters[i][j] % 2 == (i + j) % 2)
toPaint = blue;
else
toPaint = red;
HDC hdcMem = CreateCompatibleDC(hdc);
HGDIOBJ hbmOld = SelectObject(hdcMem, toPaint);
GetObject(toPaint, sizeof(bm), &bm);
BitBlt(hdc, i*100, j*100, 100, 100, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
}
}
EndPaint(hWnd, &ps);
break;
正如您所看到的,在第一次for
- 测试之后,最内层if
- 循环内的所有内容或多或少都与我WM_PAINT
案例中的内容完全相同,我认为这是一个好的迹象,这些行应该放入自己的函数调用,如DrawSquare(HWND hWnd, int i, int j, HDC handle, PAINTSTRUCT ps)
。但是,我无法弄清楚如何导航所有指针,引用和副本。我可以得到一些可以编译的东西,但之后它就不会画任何东西。
我怎么写这样的DrawSquare()
?
答案 0 :(得分:1)
嗯,这比我预想的要容易。使用
void DrawSquare(HWND hWnd, HDC hdc, int x, int y)
{
HBITMAP toPaint = NULL;
BITMAP bm;
if (counters[x][y] % 2 == (x + y) % 2)
toPaint = blue;
else
toPaint = red;
HDC hdcMem = CreateCompatibleDC(hdc);
HGDIOBJ hbmOld = SelectObject(hdcMem, toPaint);
GetObject(toPaint, sizeof(bm), &bm);
BitBlt(hdc, x * 100, y * 100, 100, 100, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
// Thanks to the comment below, to avoid memory leak
DeleteDC(hdcMem);
}
没有PAINTSTRUCT
工作得很好(因为我没有明确地使用它)。现在我的案例看起来像这样:
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
DrawSquare(hWnd, hdc, xcor / 100, ycor / 100);
EndPaint(hWnd, &ps);
break;
case WM_SIZE:
hdc = BeginPaint(hWnd, &ps);
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
if (counters[i][j] == 0)
continue;
DrawSquare(hWnd, hdc, i, j);
}
}
EndPaint(hWnd, &ps);
break;
这比我的好多了。