WM_PAINT Message in Debug vs. Release


#1

Hey All,

I'm creating a child dialog (TopLevelWindow w/ an AnimatedAppComponent) in a CView class (which doubly inherits Component) which is created OnActivateView as such:


setSize(getWidth(), getHeight());
mainWindow = new MainWindow("NEW WINDOW", false);
mainWindow->addToDesktop(mainWindow->getDesktopWindowStyleFlags(), pActivateView->m_hWnd);
mainWindow->centreWithSize(mainWindow->getWidth(), mainWindow->getHeight());
mainWindow->setVisible(true);

What this results in is that in Debug mode, it works 100% as a child, within the dialog. I use Spy++ and can see all windows messages such as WM_MOUSEMOVE being sent and accepted by the window. I can also see the WM_PAINT call being sent periodically, updating the window. However, in Release mode, I can see, using Spy++, all commands BUT WM_PAINT being sent periodically. As a result, the dialog appears to just hang (since JUCE relies on the window to repaint consistently). I have compared all project configurations from the original JUCE project with this one and also with my Debug project settings and they match up 100%. The only explanation is that in Release mode, with the above code, the JUCE Timer isn't becoming active which is in charge of repainting?

I then change the line:

mainWindow = new MainWindow("NEW WINDOW", false);

to

mainWindow = new MainWindow("NEW WINDOW", true);

and now the dialog works 100% in both Debug and Release. However, the dialog isn't a child anymore, it's a modeless dialog, which is definitely unwanted (separate entries in task bar; handling of shutdown becomes more complicated, etc).

The MainWindow is defined as:


class MainWindow : public TopLevelWindow
{
public:
    ScopedPointer<Component> maincontent;
    MainWindow(String name = "", bool bAddToDesktop = true) :
        TopLevelWindow(name, bAddToDesktop)
    {
        setSize(getParentWidth(), getParentHeight());
        maincontent = createMainContentComponent();
        addAndMakeVisible(maincontent);
        setDropShadowEnabled(false);
    }
    virtual ~MainWindow()
    {
        maincontent = nullptr;
    }
    void paint(Graphics& g)
    {
        //[UserPrePaint] Add your own custom painting code here..
        //[/UserPrePaint]
        g.fillAll(Colours::white);
        //[UserPaint] Add your own custom painting code here..
        //[/UserPaint]
    }
    /* Note: Be careful if you override any DocumentWindow methods - the base
    class uses a lot of them, so by overriding you might break its functionality.
    It's best to do all your work in your content component instead, but if
    you really have to override any DocumentWindow methods, make sure your
    subclass also calls the superclass's method.
    */
private:
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainWindow) // Constant assertions about memory leaks at application quit
};

I am unsure where to go from here to get the child dialog to be a child dialog and be functional in Release mode. Could someone point me in the right direction?


#2

Really can't think of anything in the juce windowing code that would behave differently in release/debug mode! Maybe you're looking in the wrong place and it's an uninitialised variable or something in the code that creates the window?


#3

That's kind of my expectation. When I close out the dialogs in debug, I find that I get multiple assertions over variables and such leaking (JUCE assertions - I don't get any in Windows). I have followed through the dialogs and ensured that all my destructors are being called and all variables (ScopedPointers) are getting set to nullptr. However, even for dialogs that I have confirmed they have been destroyed, I find that JUCE still considers them as leaking. I've gotten around this by getting rid of the leak detector but that's not ideal since this is a great feature of JUCE.

When I call the few lines of code above to create my MainWindow, is there anything else that I should call to ensure JUCE and all subsequent processes and threads are also initialized? I think that's probably where my problem occurs, as well as having a suitable destructor that is able to shut it all down properly so I don't have the assertions that I do? Considering I'm not utilizing a JUCEApplication and everything is being done on the back-end..


#4

If you're going off-piste and running your own startup/shutdown system then we can't really help much, but you probably want to look at things like ScopedJuceInitialiser_GUI


#5

That was it. I didn't catch that component in the class list! For your reference in case others ask about integrating both JUCE and MFC and are using JUCE components as childs:

I added a member variable into my CWinApp class:

ScopedJuceInitialiser_GUI* libraryInitialiser; // JUCE libs

And then within my CWinApp::InitInstance(), as the very first line, I instantiated the member:

libraryInitialiser = new ScopedJuceInitialiser_GUI();

And then on my CWinApp::ExitInstance() class, I deleted it:

delete libraryInitialiser;

This has fixed all my problems. Thanks a ton!