From 0c544409dd33c004e30d44ebae939e370b417c22 Mon Sep 17 00:00:00 2001 From: ivan100sic Date: Tue, 20 Oct 2020 15:19:10 +0200 Subject: [PATCH] Good progress on D2D --- src/modules/fancyzones/lib/ZoneWindow.cpp | 13 +- .../fancyzones/lib/ZoneWindowDrawing.h | 171 +++++++++++++++++- 2 files changed, 177 insertions(+), 7 deletions(-) diff --git a/src/modules/fancyzones/lib/ZoneWindow.cpp b/src/modules/fancyzones/lib/ZoneWindow.cpp index 689735dec..cf6efe5d7 100644 --- a/src/modules/fancyzones/lib/ZoneWindow.cpp +++ b/src/modules/fancyzones/lib/ZoneWindow.cpp @@ -158,6 +158,7 @@ private: void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept; LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept; void OnPaint(HDC hdc) noexcept; + void OnPaintD2D() noexcept; void OnKeyUp(WPARAM wparam) noexcept; std::vector ZonesFromPoint(POINT pt) noexcept; void CycleActiveZoneSetInternal(DWORD wparam, Trace::ZoneWindow::InputMode mode) noexcept; @@ -181,6 +182,7 @@ private: std::atomic m_animating; OnThreadExecutor m_paintExecutor; ULONG_PTR gdiplusToken; + std::unique_ptr m_zoneWindowDrawing; }; ZoneWindow::ZoneWindow(HINSTANCE hinstance) @@ -240,6 +242,7 @@ bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monit MakeWindowTransparent(m_window.get()); + m_zoneWindowDrawing = std::make_unique(m_window.get()); // Ignore flashZones /* if (flashZones) @@ -596,12 +599,12 @@ LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept case WM_PRINTCLIENT: { - OnPaint(reinterpret_cast(wparam)); + // OnPaint(reinterpret_cast(wparam)); } break; case WM_PAINT: { - OnPaint(NULL); + OnPaintD2D(); } break; @@ -659,6 +662,12 @@ void ZoneWindow::OnPaint(HDC hdc) noexcept } } +void ZoneWindow::OnPaintD2D() noexcept +{ + m_zoneWindowDrawing->DrawActiveZoneSet(m_activeZoneSet->GetZones(), m_highlightZone, m_host); + m_zoneWindowDrawing->Render(); +} + void ZoneWindow::OnKeyUp(WPARAM wparam) noexcept { bool fRedraw = false; diff --git a/src/modules/fancyzones/lib/ZoneWindowDrawing.h b/src/modules/fancyzones/lib/ZoneWindowDrawing.h index 62aed1873..e3d837f5e 100644 --- a/src/modules/fancyzones/lib/ZoneWindowDrawing.h +++ b/src/modules/fancyzones/lib/ZoneWindowDrawing.h @@ -34,11 +34,172 @@ namespace ZoneWindowDrawingNS class ZoneWindowDrawing { + struct DrawableRect + { + D2D1_RECT_F rect; + D2D1_COLOR_F borderColor; + D2D1_COLOR_F fillColor; + }; + HWND m_window; - winrt::com_ptr m_host; + RECT m_clientRect; + // winrt::com_ptr m_host; + ID2D1HwndRenderTarget* m_renderTarget; + + std::mutex m_sceneMutex; + std::vector m_sceneRects; + std::vector m_sceneLabels; + + void DrawBackdrop() + { + m_renderTarget->Clear(D2D1::ColorF(0.f, 0.f, 0.f, 0.f)); + } + + static ID2D1Factory* GetD2DFactory() + { + static ID2D1Factory* pD2DFactory = 0; + if (!pD2DFactory) + { + D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &pD2DFactory); + } + return pD2DFactory; + + // TODO: Destroy factory + } + + static D2D1_COLOR_F ConvertColor(COLORREF color) + { + return D2D1::ColorF(GetRValue(color) / 255.f, + GetGValue(color) / 255.f, + GetBValue(color) / 255.f, + 1.f); + } + + static D2D1_RECT_F ConvertRect(RECT rect) + { + return D2D1::RectF(rect.left, rect.top, rect.right, rect.bottom); + } public: - ZoneWindowDrawing(HWND window); - void StartAnimation(unsigned millis); - void DrawActiveZoneSet(const std::vector>& zones, const std::vector& highlightZones); -}; \ No newline at end of file + ZoneWindowDrawing(HWND window) + { + m_window = window; + + // Obtain the size of the drawing area. + GetClientRect(window, &m_clientRect); + + // Create a Direct2D render target + GetD2DFactory()->CreateHwndRenderTarget( + D2D1::RenderTargetProperties( + D2D1_RENDER_TARGET_TYPE_DEFAULT, + D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)), + D2D1::HwndRenderTargetProperties( + window, + D2D1::SizeU( + m_clientRect.right - m_clientRect.left, + m_clientRect.bottom - m_clientRect.top)), + &m_renderTarget); + } + + void Render() + { + std::unique_lock lock(m_sceneMutex); + + m_renderTarget->BeginDraw(); + DrawBackdrop(); + + for (const auto& drawableRect : m_sceneRects) + { + ID2D1SolidColorBrush* borderBrush = NULL; + ID2D1SolidColorBrush* fillBrush = NULL; + // TODO: hresult and null checks + m_renderTarget->CreateSolidColorBrush(drawableRect.borderColor, &borderBrush); + m_renderTarget->CreateSolidColorBrush(drawableRect.fillColor, &fillBrush); + + if (fillBrush) + { + m_renderTarget->FillRectangle(drawableRect.rect, fillBrush); + fillBrush->Release(); + } + + if (borderBrush) + { + m_renderTarget->DrawRectangle(drawableRect.rect, borderBrush); + borderBrush->Release(); + } + } + + m_renderTarget->EndDraw(); + } + + void StartAnimation(unsigned millis) + { + + } + + void DrawActiveZoneSet(const std::vector>& zones, + const std::vector& highlightZones, + winrt::com_ptr host) + { + std::unique_lock lock(m_sceneMutex); + + m_sceneRects = {}; + + auto borderColor = ConvertColor(host->GetZoneBorderColor()); + auto inactiveColor = ConvertColor(host->GetZoneColor()); + auto highlightColor = ConvertColor(host->GetZoneHighlightColor()); + + inactiveColor.a = host->GetZoneHighlightOpacity() / 255.f; + highlightColor.a = host->GetZoneHighlightOpacity() / 255.f; + + std::vector isHighlighted(zones.size(), false); + for (size_t x : highlightZones) + { + isHighlighted[x] = true; + } + + // First draw the inactive zones + for (auto iter = zones.begin(); iter != zones.end(); iter++) + { + int zoneId = static_cast(iter - zones.begin()); + winrt::com_ptr zone = iter->try_as(); + if (!zone) + { + continue; + } + + if (!isHighlighted[zoneId]) + { + DrawableRect drawableRect{ + .rect = ConvertRect(zone->GetZoneRect()), + .borderColor = borderColor, + .fillColor = inactiveColor + }; + + m_sceneRects.push_back(drawableRect); + } + } + + // Draw the active zones on top of the inactive zones + for (auto iter = zones.begin(); iter != zones.end(); iter++) + { + int zoneId = static_cast(iter - zones.begin()); + winrt::com_ptr zone = iter->try_as(); + if (!zone) + { + continue; + } + + if (isHighlighted[zoneId]) + { + DrawableRect drawableRect{ + .rect = ConvertRect(zone->GetZoneRect()), + .borderColor = borderColor, + .fillColor = highlightColor + }; + + m_sceneRects.push_back(drawableRect); + } + } + } +};