I think the previous post from LightAndSoundLTD is correct; you’ll need to set the window attribute for the Desktop Window Manager. You don’t need to rewrite any part of JUCE, but you will need to add some Windows-specific code to your app to set the DWMWA_WINDOW_CORNER_PREFERENCE window attribute. Docs here:
https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_window_corner_preference
Setting that attribute gave me a window with rounded corners and a drop shadow.
If you don’t want the thin dark border around the window, set the DWMWA_BORDER_COLOR attribute:
I think this cleaner; I don’t have to make the window transparent and I only had to override a single look-and-feel method. You can also have a native title bar:
I still had to call setDropShadowEnabled(false) in my main window constructor to get this to work properly. As far as I can tell, setDropShadowEnabled does not enable or disable the OS shadow; instead, it sets a flag that tells the peer to create a DropShadower that paints the shadow (see LookAndFeel::createDropShadowerForComponent).
Code is below; check out parentHierachyChanged().
Matt
class MainWindow : public juce::DocumentWindow, public juce::LookAndFeel_V4
{
public:
MainWindow(juce::String name)
: DocumentWindow(name, juce::Colours::yellow, DocumentWindow::allButtons)
{
setUsingNativeTitleBar(false);
setDropShadowEnabled(false);
setContentNonOwned(&mainComponent, false);
setResizable(true, false);
centreWithSize(500, 500);
setVisible(true);
getCurrentColourScheme().setUIColour(juce::LookAndFeel_V4::ColourScheme::widgetBackground, juce::Colours::yellow);
Component::setColour(juce::DocumentWindow::ColourIds::textColourId, juce::Colours::black);
setLookAndFeel(this);
}
~MainWindow()
{
setLookAndFeel(nullptr);
}
#if JUCE_WINDOWS
static uint32_t colourToColorRef(juce::Colour colour)
{
uint32_t colorRef = colour.getBlue();
colorRef |= (colorRef << 8) | colour.getGreen();
return (colorRef << 8) | colour.getRed();
}
void parentHierarchyChanged() override
{
if (auto peer = getPeer(); peer != nullptr && juce::SystemStats::getOperatingSystemType() >= juce::SystemStats::Windows11)
{
auto windowHandle = (HWND)peer->getNativeHandle();
auto value = DWMWCP_ROUND;
auto hr = DwmSetWindowAttribute(windowHandle, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value));
jassert(SUCCEEDED(hr));
COLORREF transparentBorderColor = colourToColorRef(juce::Colours::yellow);
hr = DwmSetWindowAttribute(windowHandle, DWMWA_BORDER_COLOR, &transparentBorderColor, sizeof(transparentBorderColor));
}
}
#endif
void closeButtonPressed() override
{
JUCEApplication::getInstance()->systemRequestedQuit();
}
void drawResizableFrame(juce::Graphics& g, int w, int h, const juce::BorderSize<int>&) override
{
}
private:
class MainComponent : public juce::Component
{
public:
MainComponent() = default;
~MainComponent() override = default;
void paint(juce::Graphics& g) override
{
g.fillAll(juce::Colours::yellow);
}
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainComponent)
} mainComponent;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainWindow)
};