Steuern Sie die Alpha -Mischung und die Ereignistransparenz eines Fensters in Win -API und Direct 2D (Beispiel für zirkuC++

Programme in C++. Entwicklerforum
Guest
 Steuern Sie die Alpha -Mischung und die Ereignistransparenz eines Fensters in Win -API und Direct 2D (Beispiel für zirku

Post by Guest »

Ich versuche, ein kreisförmiges Fenster mit der Win32 -API und Direct2D in C ++ zu erstellen. Soweit ich weiß, besteht die einzige Möglichkeit, dies zu erreichen, indem ich ein WS_POPUP Fenster erstellt und die gesamte Zeichnung manuell bearbeitet. Mein Ziel ist es, dass das Fenster einen benutzerdefinierten Schatten um ihn herum beinhaltet. Dieser Schatten sollte durch Transparenz gemalt werden, damit der Desktop oder andere Fenster dahinter sichtbar bleiben. Darüber hinaus muss es für Mausereignisse transparent sein, sodass Benutzer mit anderen Anwendungen über den Schattenbereich interagieren können. /Code> Ermöglicht die Erkennung von Mausereignissen nur in Bereichen mit Direct2D und aktiviert effektiv ein kreisförmiges Fenster. Das Malen mit Transparenz (Alpha -Werte) scheint jedoch nicht wie erwartet zu funktionieren - als mit dem Hintergrund hinter dem Fenster zu mischen, mischt es sich mit einem soliden schwarzen Hintergrund ein. Trotzdem konnte ich das Fenster für Mausereignisse transparent machen, indem ich das WS_EX_TRALPARENT -Flag hinzufügte. p>
Ein anderer Ansatz, den ich in Betracht gezogen habe, war die Vermeidung von WS_EX_Layered und stattdessen verwenden dwMextendFrameIntoclientArea () . Diese Methode ermöglicht eine ordnungsgemäße Transparenzmischung, aber WS_EX_TRALPARENT funktioniert nicht mehr, was bedeutet, dass Mausereignisse in transparenten Bereichen nicht ignoriert werden. Zusätzlich bemerkte ich, dass das Fenster das Fenster von außerhalb des Bildschirms wieder in die Sichtweise bewegte, was diesen Ansatz weniger ideal macht. < /P>
Ergebnis mit DWM. Ich habe keinen Weg gefunden, die Mausereignisse durchlaufen zu lassen:
< /p>
Hier ist der Flicker -Effekt, den ich entdeckt habe, und ich mag nicht: < /p>

Hier ist mein vollständiger Code, der variable ISDWM wird verwendet, um von einem Ansatz zum anderen zu wechseln: < /p>

Code: Select all

#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

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post