Я прокручивал пользовательские окна с помощью API окон. В связи с этим я работал с Extended Layered Windows. У меня есть окно, и оно работает. Однако при изменении размера окна при вызове метода redraw/UpdateLayeredWindow (и UpdateLayeredWindowIndirect) появляется нечетное мерцание/сбой [(Снимок экрана)] [1]. Что-то я здесь делаю неправильно?Visual-C Win32 API Многоуровневое окно мерцания
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(mainDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(mainDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(mainDC, bmp);
FillRect(mainDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(mainDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(mainDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, mainDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(mainDC, oldbrush);
SelectObject(mainDC, oldBmp);
SelectObject(mainDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
}
На всякий случай, сообщение Windows Proc.
long __stdcall WndProc(HWND window, unsigned int msg, WPARAM wp, LPARAM lp) {
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = "Hello, World!";
RECT rect_window;
GetWindowRect(window, &rect_window);
switch (msg) {
case WM_SYSKEYDOWN:
MessageBeep(MB_ICONERROR);
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NCHITTEST:;
int x = LOWORD(lp);
int y = HIWORD(lp);
if (x > rect_window.left && x<rect_window.right && y>rect_window.top && y < rect_window.top + 25)
return HTCAPTION;
if (x>=rect_window.left-3 && x<=rect_window.left+3)
return HTLEFT;
if (x >= rect_window.right - 3 && x <= rect_window.right + 3)
return HTRIGHT;
if (y >= rect_window.top - 3 && y <= rect_window.top + 3)
return HTTOP;
if (y >= rect_window.bottom - 3 && y <= rect_window.bottom + 3)
return HTBOTTOM;
break;
case WM_LBUTTONDOWN:
break;
case WM_SIZE:
redrawBaseWindow(window);
break;
case WM_PAINT:
break;
}
return DefWindowProc(window, msg, wp, lp);
}
Редактировать: Gif of the glitch
Изменить 2: Используя значение CreateCompatibleDC в UpdateLayeredWindow [Кроме того, не работает]
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(mainDC);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(memDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(memDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(memDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(memDC, bmp);
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(memDC, oldbrush);
SelectObject(memDC, oldBmp);
SelectObject(memDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
ReleaseDC(NULL,mainDC);
ReleaseDC(NULL,memDC);
}
Редактировать 3: DeleteDC на CreateCompatibleDC устройстве, а также создание растрового изображения на экране DC, а не CompatibleDC
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(mainDC);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(memDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(memDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(memDC, bmp);
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(memDC, oldbrush);
SelectObject(memDC, oldBmp);
SelectObject(memDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
DeleteDC(memDC);
ReleaseDC(NULL,mainDC);
}
Оригинальный мерцающий фиксированный. Спасибо [Jonathan Pottar] Другая ошибка однако: This
Создайте анимированный скриншот gif, я не вижу проблемы с вашим изображением. – Lothar
Будет делать только мгновение – UnknownRobotik
Выбор другого растрового изображения в DC, полученный из 'GetDC', немного нечетный, и я не уверен, что поддерживается передача DC в' UpdateLayeredWindow'. Обычное использование - это выбрать ваш растровый рисунок в память DC, полученный из «CreateCompatibleDC», визуализировать его и обновить окно от него. У вас также есть утечка ресурсов GDI (не вызывающая 'ReleaseDC'). –