I have a problem wrapping my head around the addToDesktop method on win32.
I need to attach a JUCE window to an already created native window. From what I gather from the source code the way it works is JUCE doesn’t take over that native window but rather it creates a child window and “parents” it to that native window. Unfortunately if I try to call GetParent((HWND) mainWindow->getWindowHandle()) I get 0. spy++ doesn’t show any parent/owner either.
The native parent window is WS_POPUP. Nothing particular about it.
The JUCE window is of class TopLevelWindow. Could this be the cause? Should I use another class instead? The main window constructor passes (“title”, false) to the TopLevelWindow constructor.
The other thing I’m concerned with is that I think UpdateLayeredWindow cannot be used to draw child windows, only the top level ones (right ?). So I guess there’s something more I need to do to prevent JUCE from trying to use that method on a child window as long as it’s not windows 8.
But first things first - I need to get that window actually attached to the host app’s window.
Would anyone care to point me in the right direction ?
Sounds like you’re doing the right things. Haven’t you tried stepping through in the debugger to see what’s happening inside addToDesktop()?
I’m not 100% sure, but that’s probably true. To avoid it, just make sure you setOpaque (true) on your component.
All right, I did a bit of research using just the basic app but with the MainWindow derived from TopLevelWindow and not the document window.
I turns out that when you call AddToDesktop(0, somenativeHWND) (or indeed if you just construct the TopLevelWindow with addToDesktop set to true) The Component::AddToDesktop method gets called 3 (yes, that’s three) times for that very component (I’m not including the shadow creating calls here).
The first time it’s called the correct nativeWindowToAttachTo value is passed and everything seems fine until it reaches the end where internalHierarchyChanged() is called which calls parentHierarchyChanged() which calls setDropShadowEnabled which calls… yup Component::AddToDesktop but this time nativeWindowToAttachTo is not passed so it’s assumed to be 0 so the TopLevelWindow is detached from the native window and simply put on the desktop.
Component::AddToDesktop is further called a third time for that window but I didn’t check where’s it called from.
I nailed it.
the addToDesktop method MUST be called with the first argument equal to whatever getDesktopWindowStyleFlags() returns otherwise the second call to that method will create the peer again because Component::addToDesktop is called again by TopLevelWindow::setDropShadowEnabled (called by Component::parentHierarchyChanged()) but this time the first arg equals getDesktopWindowStyleFlags() so styleWanted != currentStyleFlags so the peer gets created again but this time nativeWindowToAttachTo has the assumed value of nullptr so the window ultimately gets attached to desktop not the native window.
With the way it’s all written not only the first arg to TopLevelWindow:addToDesktop is effectively useless but it also opens a whole can of worms…
PS. I’m starting to like Win32 API now… Oh, wait! Did I actually say that?? Guess I did… :?
Sorry, I should have said that it’s actually really simple unless you’re trying to use the TopLevelWindow and derived classes… Because those classes take care of all the addToDesktop stuff automatically, then if you try adding them to the desktop in a custom way, you’ll end up fighting against all of their internal functionality. If you just derive from a simple Component, then you won’t have any such problems.
Yup, that’s what it looks like. Question is what’s the use of the second arg in the TopLevelWindow constructor If you set it to “false” ?? And why is there a public TopLevelWindow::AddToDesktop method with flags argument if it can only be called with flags = getDesktopWindowStyleFlags()??
If you set that to “false” and add it to another component, it acts as a lightweight child window. And TopLevelWindow::addToDesktop is an overload to do some kind of trickery. That’s why it’s all best avoided if possible.
In all fairness it does it’s job pretty well if the flags arg has the correct value. The window can benefit from all TopLevel / Resizable / Document Window functionality and it can still be embedded in a native app (albeit without shadows, I think).
Ok. So this is sorted then. 8)