Другой подход, который я рассматривал, - это избегание 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]