У меня есть окно, в котором иногда должно быть прозрачное отверстие, а иногда нет. В идеале мы должны использовать SetWindowRgn, но это отключает визуальные стили, которые не только выглядят некрасиво, но и некорректно рисуются с поддержкой DPI для каждого монитора, поэтому я пытаюсь использовать многослойное окно с цветовой клавишей.
При включении цветовой клавиши я сначала вызываю SetLayeredWindowAttributes(hWnd, colorkey, 0, LWA_COLORKEY)
, а затем отключаю окно, чтобы оно было перерисовано. На данный момент окно не должно содержать цвет ключа. Затем через некоторое время окно получает WM_PAINT
, и цвет ключа окрашивается, но в этот момент в окне должно быть установлено LWA_COLORKEY
, поэтому, опять же, я ожидаю, что цвет ключа не будет виден.
При отключении цветовой клавиши я сначала перекрашиваю окно (синхронно), чтобы оно не содержало цвет клавиши, а затем отключаю WS_EX_LAYERED
, поэтому, опять же, я никогда не ожидаю увидеть цвет клавиши.
Тем не менее, окно со следующей оконной процедурой постоянно мигает между зеленым, прозрачным и фоновым цветом, когда мышь перемещается по нему.
Похоже, что SetLayeredWindowAttributes
не вступает в силу немедленно (и даже до следующего WM_PAINT
). Как я могу убедиться, что этот атрибут вступил в силу перед перерисовкой, или как-то иначе предотвратить отображение цвета ключа?
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static auto const colorkey = RGB(0,255,0);
static auto const hbrush = CreateSolidBrush(colorkey);
static auto transparent = false;
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
if (transparent) {
RECT rect{30,30,500,500};
FillRect(hdc, &rect, hbrush);
}
EndPaint(hWnd, &ps);
}
break;
case WM_MOUSEMOVE:
if (transparent) {
transparent = false;
RedrawWindow(hWnd, nullptr /* lprcUpdate */, nullptr /* hrgnUpdate */, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, GetWindowLongPtr(hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
} else {
SetWindowLongPtr(hWnd, GWL_EXSTYLE, GetWindowLongPtr(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd, colorkey, 0, LWA_COLORKEY);
transparent = true;
InvalidateRect(hWnd, nullptr, TRUE);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}