我创建了一个Win32窗口应用程序,它偶尔会在屏幕上移动,有点像宠物。当它移动时,它会在两个位图之间切换,以显示它移动的“动画”。实现过程涉及多个WM_TIMER
消息:一个计时器移动窗口,另一个计时器在窗口移动时更改位图和窗口区域(仅显示位图而不显示透明部分),另一个计时器更改窗口移动的方向。
窗口本身运行非常流畅,但当我打开多个示例时,动画和移动开始滞后-在2个窗口时不太明显,但3个示例及以上导致每个窗口开始滞后非常明显。移动和动画是波涛汹涌的,甚至偶尔冻结。
我试过删除部分代码以查明问题的原因,显然只有在放入以下代码的一部分时才会发生这种情况(我用注解将其标记出来):
HBITMAP hBitMap = NULL;
BITMAP infoBitMap;
hBitMap = LoadBitmap(GetModuleHandle(NULL), IDB_BITMAP2);
if (hBitMap == NULL)
{
MessageBoxA(NULL, "COULD NOT LOAD PET BITMAP", "ERROR", MB_OK);
}
HRGN BaseRgn = CreateRectRgn(0, 0, 0, 0);
HDC winDC = GetDC(hwnd);
HDC hMem = CreateCompatibleDC(winDC);
GetObject(hBitMap, sizeof(infoBitMap), &infoBitMap);
HDC hMemOld = SelectObject(hMem, hBitMap);
COLORREF transparentCol = RGB(255, 255, 255);
for (int y = 0; y < infoBitMap.bmHeight; y++) //<<<< THIS SECTION ONWARDS
{
int x, xLeft, xRight;
x = 0;
do {
xLeft = xRight = 0;
while (x < infoBitMap.bmWidth && (GetPixel(hMem, x, y) == transparentCol))
{
x++;
}
xLeft = x;
while (x < infoBitMap.bmWidth && (GetPixel(hMem, x, y) != transparentCol))
{
x++;
}
xRight = x;
HRGN TempRgn;
TempRgn = CreateRectRgn(xLeft, y, xRight, y + 1);
int ret = CombineRgn(BaseRgn, BaseRgn, TempRgn, RGN_OR);
if (ret == ERROR)
{
MessageBoxA(NULL, "COMBINE REGION FAILED", "ERROR", MB_OK);
}
DeleteObject(TempRgn);
}
while (x < infoBitMap.bmWidth);
}
SetWindowRgn(hwnd, BaseRgn, TRUE); //<<<<---- UNTIL HERE
BitBlt(winDC, 0, 0, infoBitMap.bmWidth, infoBitMap.bmHeight, hMem, 0, 0, SRCCOPY);
SelectObject(hMem, hMemOld);
DeleteDC(hMem);
ReleaseDC(hwnd, winDC);
注解部分是我用来消除窗口客户端区域中显示的位图透明部分的代码,它在应用每次更改位图以显示动画时运行。
如果我删除该代码,应用程序运行得非常好,所以我怀疑这是导致问题的原因。有人知道为什么这段代码会导致延迟,而且只在多个示例打开的情况下?有没有办法处理这种延迟?
2条答案
按热度按时间9udxz4iz1#
在每次更新中,您都在迭代每个像素(如果我错了,请纠正我),这是一个相当慢的过程(相对而言)。
一个更好的选择是使用类似下面的代码:https://stackoverflow.com/a/3970218/19192256来创建遮罩颜色,并简单地使用遮罩来移除透明像素。
3lxsmp7m2#
创建多个区域并将它们连接起来是一个非常慢且资源/cpu密集的操作。2相反,使用
ExtCreateRegion()
从一个矩形数组创建一个区域。或者,完全不用使用区域,只需在窗口上正常显示位图,然后用唯一的颜色填充窗口的所需区域,可以使用
SetLayeredWindowAttributes()
使其透明,如@Substitute的答案所述。