Integrating JUCE VST into existing application - 2 issues


#1

Hello,

I have an existing Windows application and I’m using JUCE to add VST support to the application. It’s working really great (!!) except for 2 issues, one of which I’ve solved and one of which I haven’t. NOTE: I’m using the current developer branch of the software.

ISSUE #1:

When we create the effect, a new MessageManager() gets created. When we call createEditorIfNeeded() to show the editor window., a new Desktop gets created.

The MessageManager is easy to destroy – we simply call MessageManager::deleteInstance() and it frees itself properly.

The problem is that there doesn’t appear to be a way to destroy the Desktop. The Desktop inherits privately from DeletedAtShutdown, so we cannot call the Desktop::deleteAll() function. Since this isn’t a JUCE application, there doesn’t appear to be any way to delete the Desktop object.

I changed the inheritance of DeletedAtShutdown from private to public, then called Desktop::deleteAll(), and everything cleans up perfectly – no memory leaks at all on shutdown. So I would suggest you change this in the dev code, unless there’s another way I can delete the desktop that I haven’t discovered yet?

ISSUE #2:

This one seems a little harder. After we call createEditorIfNeeded(), we’re adding the editor to our own class that extends ResizableWindow, pretty much identical to how its done in the “Plugin Host” demo. This ResizeableWindow then gets added to the Desktop, which allows us to call getWindowHandle() (or getPeer->getNativeHandle()) to get a Windows handle to the window, and we can then add the window as a child window into our application.

This works great overall, but there’s a problem. The ResizableWindow, when it is added to the desktop, creates an entry on the Windows taskbar. The constructor for ResizableWindow() takes an addToDesktop flag. If I set this flag to false, and then call Component::addToDesktop myself and pass in 0 for the flags, the window still gets added to the taskbar. I stepped into the code to try to find out why this is happening. It appears that the peer is initially created with the flags that I pass in, but then there are several subsequent calls to addToDesktop, all made by the drop shadow (even if its disabled). Each of these calls to addToDesktop() calls TopLevelWindow::getDesktopWindowStyleFlags() to decide on the flags, and TopLevelWindow::getDesktopWindowStyleFlags() ALWAYS sets the styleFlag to “windowAppearsOnTaskbar” – there’s no flag for this.

There must be some way I can create a resizable window that isn’t on the taskbar, right? I’d certainly appreciate some guidance!

Thanks once again!
Dan


#2

By the way, I’ve been able to work around the Taskbar issue by modifying Component::addToDesktop(). There is a line in there that reads:

if (peer == nullptr || styleWanted != peer->getStyleFlags())

…and this line causes the existing peer to get replaced with a new peer, if the style flags are different. This is the reason why the flags I pass in are being ignored - the peer gets created properly. but then immediately gets replaced by the drop shadow code, even though I’ve disabled the drop shadow! So by preventing the peer from getting replaced, even if the style flags change, then my original flags are preserved.

I suppose I could override addToDesktop() so I can control the flags… I’ll try that.

Dan


#3

No, overriding addToDesktop() doesn’t work because the code in TopLevelWindow::setDropShadowEnabled specifically calls Component::addToDesktop():

    Component::addToDesktop (getDesktopWindowStyleFlags());

There doesn’t seem to be any way to fix this, elegantly, without changing JUCE.

Dan


#4

I think you should not create a Desktop at all. The desktop is a singleton to make sure

a) it is only created once
b) it is accessible from all places/scopes.

You either use the static methods, and if you need the desktop instance, you simply use:
Desktop* d = Desktop::getInstance();
see: Desktop::getInstance()
and for theory: wikibooks - singleton

HTH,
daniel


#5

Not sure how you’re getting into a mess, but it basically sounds like you’re trying too hard! You don’t need to create or destroy any of these classes, they’ll take care of themselves. If you’re not using a juce Application object then you may need to use a ScopedJuceInitialiser_GUI object, but if you find yourself hacking the code for things like DeletedAtShutdown then I think you’re probably way off-piste!


#6

Jules,

Thank you, ScopedJuceInitializer_GUI was exactly what I needed, and it’s working perfectly.

What about my second issue – is there any way to make a ResizeableWindow that doesn’t show up on the Windows taskbar?

Thanks!
Dan


#7

Use the ComponentPeer::windowAppearsOnTaskbar flag?


#8

Right, but as I tried to explain above, those flags are ignored. The reason why is because ResizeableWindow calls setDropShadowEnabled(), which calls TopLevelWindow::getDesktopWindowStyleFlags(), which looks like this:

int TopLevelWindow::getDesktopWindowStyleFlags() const
{
int styleFlags = ComponentPeer::windowAppearsOnTaskbar;

if (useDropShadow)       styleFlags |= ComponentPeer::windowHasDropShadow;
if (useNativeTitleBar)   styleFlags |= ComponentPeer::windowHasTitleBar;

return styleFlags;

}

As you can see, it sets styleFlags to ComponentPeer::windowAppearsOnTaskbar. Regardless of the flags I passed in when I added the ResizableWindow to the desktop, the drop-shadow always gets added with the windowAppearsOnTaskbar flag. The end result is that Component::addToDesktop() destroys the peer that was created without that windowAppearsOnTaskbar flag, and replaces it with a new peer which always appears on the taskbar.

In short, there’s no way to prevent a ResizableWindow from appearing on the taskbar, regardless of the flags that are passed in when adding the window to the desktop.

Dan


#9

Sorry, I didn’t explain very well - the flag will work if you actually use it, but in this case you’d probably need to override getDesktopWindowStyleFlags() and return your own flags, as this kind of thing is outside the remit of what the ResizableWindow class does.


#10

Jules,

Overriding the getDesktopWindowStyleFlags() function was the answer. Everything is working great now. Thanks for your help!

Dan