[AlwaysOnTop] Round corners on Windows 11 (#19109)

* check window corners

* draw rounded rectangle

* draw rounded corners

* switch between rounded and not rounded rects

* added enabled corners setting

* update corner
This commit is contained in:
Seraphima Zykova
2022-07-01 17:56:45 +02:00
committed by GitHub
parent 35bb4280d0
commit d201ae4335
14 changed files with 175 additions and 28 deletions

View File

@@ -86,17 +86,26 @@ void FrameDrawer::Show()
Render();
}
void FrameDrawer::SetBorderRect(RECT windowRect, COLORREF color, int thickness)
void FrameDrawer::SetBorderRect(RECT windowRect, COLORREF color, int thickness, int radius)
{
const auto newSceneRect = DrawableRect{
.rect = ConvertRect(windowRect),
auto newSceneRect = DrawableRect{
.borderColor = ConvertColor(color),
.thickness = thickness
.thickness = thickness,
};
if (radius != 0)
{
newSceneRect.roundedRect = ConvertRect(windowRect, thickness, radius);
}
else
{
newSceneRect.rect = ConvertRect(windowRect, thickness);
}
const bool colorUpdated = std::memcmp(&m_sceneRect.borderColor, &newSceneRect.borderColor, sizeof(newSceneRect.borderColor));
const bool thicknessUpdated = m_sceneRect.thickness != newSceneRect.thickness;
const bool needsRedraw = colorUpdated || thicknessUpdated;
const bool cornersUpdated = m_sceneRect.rect.has_value() != newSceneRect.rect.has_value() || m_sceneRect.roundedRect.has_value() != newSceneRect.roundedRect.has_value();
const bool needsRedraw = colorUpdated || thicknessUpdated || cornersUpdated;
RECT clientRect;
if (!SUCCEEDED(DwmGetWindowAttribute(m_window, DWMWA_EXTENDED_FRAME_BOUNDS, &clientRect, sizeof(clientRect))))
@@ -104,7 +113,7 @@ void FrameDrawer::SetBorderRect(RECT windowRect, COLORREF color, int thickness)
return;
}
m_sceneRect = newSceneRect;
m_sceneRect = std::move(newSceneRect);
const auto renderTargetSize = D2D1::SizeU(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
@@ -170,24 +179,38 @@ D2D1_COLOR_F FrameDrawer::ConvertColor(COLORREF color)
1.f);
}
D2D1_RECT_F FrameDrawer::ConvertRect(RECT rect)
D2D1_ROUNDED_RECT FrameDrawer::ConvertRect(RECT rect, int thickness, int radius)
{
return D2D1::RectF((float)rect.left, (float)rect.top, (float)rect.right, (float)rect.bottom);
auto d2d1Rect = D2D1::RectF((float)rect.left + thickness, (float)rect.top + thickness, (float)rect.right - thickness, (float)rect.bottom - thickness);
return D2D1::RoundedRect(d2d1Rect, (float)radius, (float)radius);
}
D2D1_RECT_F FrameDrawer::ConvertRect(RECT rect, int thickness)
{
return D2D1::RectF((float)rect.left + thickness, (float)rect.top + thickness, (float)rect.right - thickness, (float)rect.bottom - thickness);
}
void FrameDrawer::Render()
{
if (!m_renderTarget)
if (!m_renderTarget || !m_borderBrush)
{
return;
}
m_renderTarget->BeginDraw();
m_renderTarget->Clear(D2D1::ColorF(0.f, 0.f, 0.f, 0.f));
if (m_borderBrush)
{
// The border stroke is centered on the line.
m_renderTarget->DrawRectangle(m_sceneRect.rect, m_borderBrush.get(), static_cast<float>(m_sceneRect.thickness * 2));
}
// The border stroke is centered on the line.
if (m_sceneRect.roundedRect)
{
m_renderTarget->DrawRoundedRectangle(m_sceneRect.roundedRect.value(), m_borderBrush.get(), static_cast<float>(m_sceneRect.thickness * 2));
}
else if (m_sceneRect.rect)
{
m_renderTarget->DrawRectangle(m_sceneRect.rect.value(), m_borderBrush.get(), static_cast<float>(m_sceneRect.thickness * 2));
}
m_renderTarget->EndDraw();
}