Контролировать альфа -смешивание и прозрачность событий в Win API и Direct 2D (пример циркулярного окна)C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Контролировать альфа -смешивание и прозрачность событий в Win API и Direct 2D (пример циркулярного окна)

Сообщение Anonymous »

Я пытаюсь создать круговое окно, используя API Win32 и Direct2d в C ++. Из того, что я понимаю, единственный способ достичь этого - создать окно ws_popup и обработать все рисунки вручную. Моя цель состоит в том, чтобы окно включало в себя индивидуальную тень вокруг него. Эта тень должна быть окрашена с прозрачностью, чтобы за ним оставались настольные окна или другие окна. Кроме того, он должен быть прозрачным для мышиных событий, позволяя пользователям взаимодействовать с другими приложениями через затененную область. /code> позволяет обнаружить события мыши только в областях, окрашенных Direct2D, эффективно включает в себя круговое окно. Тем не менее, покраска с прозрачностью (альфа -значения), кажется, не работает, как и ожидалось, чем смешиваясь с фоном за окном, она смешивается с твердым черным фоном. Тем не менее, я смог сделать окно прозрачным для событий мыши, добавив результат ws_ex_transparent . p>
Другой подход, который я рассматривал, - это избегание ws_ex_layered и вместо этого используя dwmextendframeintoclientarea () . Этот метод допускает правильное смешивание прозрачности, но ws_ex_transparent больше не работает, а это означает, что события мыши не игнорируются в прозрачных областях. Кроме того, я заметил некоторое мерцание при перемещении окна извне экрана обратно, что делает этот подход менее идеальным. Я не нашел способ, чтобы события мыши проходили через:
< /p>
Вот эффект мерцания, который я обнаружил, и мне не нравится: < /p>

Вот мой полный код, переменная isdwm используется для переключения с одного подхода на другой: < /p>

Код: Выделить всё

#include 
#include 
#include 
#include 

#pragma once
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "dwrite.lib")
#pragma comment(lib, "Dwmapi.lib")

#define INIT_X_RATIO    0.7f
#define INIT_Y_RATIO    0.7f
#define BORDER_SIZE     2       // pixels
#define SHADOW_OFF      100     // pixels

ID2D1Factory* fact;
ID2D1HwndRenderTarget* renderTarget;
ID2D1SolidColorBrush* brush;
ID2D1RadialGradientBrush* pRadialGradientBrush;

D2D1::ColorF ColorRefToColorF(COLORREF color);
void paint_frame(HWND hwnd);
bool init_d2d1(HWND hwnd);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void CreateConsole();

int x, y, w, h;
bool isDWM = false; // Set to true to use DWM and see semi-transparent painting
LPCTSTR cursors[] = {IDC_SIZENESW, IDC_SIZENWSE};

D2D1::ColorF ColorRefToColorF(COLORREF color){
float r = GetRValue(color) / 255.0f;
float g = GetGValue(color) / 255.0f;
float b = GetBValue(color) / 255.0f;
return D2D1::ColorF(r, g, b);
}

void paint_frame(HWND hwnd) {
UINT dpi = GetDpiForSystem();
float ratio = (float)dpi / 96.0f;
float shadow_off = SHADOW_OFF / ratio / 2.0f;
D2D1_SIZE_F rtSize = renderTarget->GetSize();
renderTarget->BeginDraw();
renderTarget->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.0f));

// Create shadow circle
float cx = rtSize.width / 2.0f;
float cy = rtSize.height / 2.0f;
float rad = min(rtSize.width, rtSize.height) / 2.0f - shadow_off;
D2D1_ELLIPSE circle = D2D1::Ellipse(
D2D1::Point2F(cx, cy + shadow_off),
rad,
rad
);
brush->SetColor(D2D1::ColorF(0.01f, 0.01f, 0.01f, 0.5f));
renderTarget->FillEllipse(circle, brush);

// Paint border circle
circle.point = D2D1::Point2F(cx, cy - shadow_off);
COLORREF borderColor = GetSysColor(COLOR_ACTIVEBORDER); // Get system border color
D2D1::ColorF d2dColor = ColorRefToColorF(borderColor);
brush->SetColor(d2dColor);
renderTarget->FillEllipse(circle, brush);

// Paint Content circle
rad -= BORDER_SIZE / ratio;
circle.radiusX = rad;
circle.radiusY = rad;
brush->SetColor(D2D1::ColorF(0.18f, 0.18f, 0.19f));
renderTarget->FillEllipse(circle, brush);

renderTarget->EndDraw();
}

bool init_d2d1(HWND hwnd) {
// Create factory
HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &fact);
if (hr != S_OK) return false;
RECT r;
GetClientRect(hwnd, &r);

// Create render target
hr = fact->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)),
D2D1::HwndRenderTargetProperties(hwnd, D2D1::SizeU(r.right, r.bottom)),
&renderTarget
);

if (hr != S_OK) return false;
renderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);

// Create brush
hr = renderTarget->CreateSolidColorBrush(D2D1::ColorF(0.0f, 0.0f, 0.0f, 1.0f), &brush);
if (hr != S_OK) return false;

return true;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}

case WM_PAINT: {
paint_frame(hwnd);
ValidateRect(hwnd, NULL);
break;
}

case WM_NCHITTEST:
return HTCAPTION;  // Enable dragging of the window

case WM_NCMOUSEMOVE: {
float xPos = (float) LOWORD(lParam);
float yPos = (float) HIWORD(lParam);
std::cout 

Подробнее здесь: [url]https://stackoverflow.com/questions/79409658/control-a-windows-alpha-blending-and-events-transparency-in-win-api-and-direct[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»