JUCE app's flash in TaskBar at Startup


#1

Hello !

Under Windows 7, it is possible to “pin” applications to the taskbar. When launching certain JUCE applications from such a shortcut, they seem to fail to gain the focus. The corresponding taskbar tab starts flashing orange, and if others Windows are displayed on the screen, the JUCE application’s window may be hidden behind them. I’ve also seen the problem when lauching a JUCE application by double-clicking on a file associated with an application (ie : double-click on *.jucer opens Introjucer.exe) When launched “normally” by double-clicking on the *.exe, or by lauching it from Visual IDE, with or without debugger, the problem does not show up.

I have the problem with one of my own juce app, and also with the Introjucer. JuceDemo and some others JUCE apps behave fine. So far, I wasn’t able to reproduce the problem with a simple Hello-World-like JUCE-app, so I really have no clue what my problematic app and the IntroJucer have in common…
Other annoying fact : the problematic apps only seem to have the problem only “sometimes”… For example : the Introjucer is behaving weird ; I reboot ; it behaves fine again, but now some other app is being odd. It seems to change at random…
Anyone else having that problem ? In particular with Introjucer ? Any idea ?

A few more info :
regarding JUCE version, I was using a version which is a few month old (definitely pre-quake), so the problem’s probably been here unnoticed for a while. I’ve updated to the tip, but it doesn’t change anything.
The problem shows up under Win7sp1 32 & 64 bit, compiled with Visual Studio 2008. The problematic JUCE app in which we noticed the problem is ported to Mac, but the Mac guys haven’t encountered the problem (which isn’t so surprising, since obviously the taskbar is OS dependent !) so it appears to be a Windows-specific issue…

I’ll keep investigating this… Anyone with an idea is more than welcome ! Tks in advance for your help !

Cheers !

Val


#2

Hi again…

I’ve had some time to investigate a bit… Seems like the problem is in the Win7 OS and only there. And juce has nothing to do with it. Anyway, here’s how I solved it, if it helps someone…

#ifdef JUCE_WINDOWS
    FLASHWINFO fwi;
    fwi.cbSize = sizeof(fwi);
    fwi.hwnd = static_cast<HWND>(mainWindow->getWindowHandle());
    fwi.dwFlags = FLASHW_STOP;
    fwi.uCount = 0;
    fwi.dwTimeout = 0;
    FlashWindowEx(&fwi); // Prevents the blinking in taskbar

    const HWND hwnd = static_cast<HWND>(mainWindow->getPeer()->getNativeHandle());
    ShowWindow (hwnd, SW_MINIMIZE);
    ShowWindow (hwnd, SW_SHOWNORMAL); // gives the focus to the app, that sometimes doesn't want to take it...
#endif // JUCE_WINDOWS

Note that :

    SetMinimize(true);
    SetMinimize(false);

doesn’t work, since these juce methods are too smart : ie, they do nothing when the OS says the window is already in the state we want. Since the OS is lying, we have to force it to do what we want, hence the ugly platform-dependant hwnd-based code…

Hope it helps…
Cheers !

Val


#3

Interesting… Do you just run that code snippet after making the window visible?


#4

Yes…
Here’s some code from my “main.cpp”, initially created by the jucer, so you have the context.

class MyApplication  : public JUCEApplication
{
	[...]

	void initialise (const String& /*commandLine*/)
	{
		// Do your application's initialisation code here...
		ApplicationProperties::getInstance()->setStorageParameters([...]);

		CCustomLookAndFeel::SetDefaultLookAndFeelToCustom();
		CCustomLookAndFeel::getDefaultLookAndFeel().setUsingNativeAlertWindows(true);
		mainWindow = new MainAppWindow();

	#ifdef JUCE_WINDOWS
		{
			FLASHWINFO fwi;
			fwi.cbSize		= sizeof(fwi);
			fwi.hwnd		= static_cast<HWND>(mainWindow->getWindowHandle());
			fwi.dwFlags		= FLASHW_STOP;
			fwi.uCount		= 0;
			fwi.dwTimeout	= 0;
			FlashWindowEx(&fwi);	// Prevents the blinking in taskbar

			const HWND hwnd = static_cast<HWND>(mainWindow->getPeer()->getNativeHandle());
			ShowWindow (hwnd, SW_MINIMIZE);
			ShowWindow (hwnd, SW_SHOWNORMAL); // gives the focus to the app, that sometimes doesn't want to take it...
		}
	#endif // JUCE_WINDOWS

	}

private:
	[...]
};

… whereas my constructor for MainAppWindow goes sth like :

MainAppWindow::MainAppWindow()
	: DocumentWindow (JUCEApplication::getInstance()->getApplicationName(),
					  Colours::black,
					  DocumentWindow::allButtons)
{
	setUsingNativeTitleBar(true);
	
	setResizable(true, false);
	setResizeLimits([...]);
	setVisible (true);

	// some more init code...
	[...]
}

Cheers

Val


#5

The flashing is caused by the call to SetForegroundWindow((HWND) h) in juce_win32_Windowing.cpp (see http://msdn.microsoft.com/en-us/library/ms633539.aspx ). Replacing it with SetActiveWindow((HWND) h); solves it, and does not seem to break anything.


#6

It has been many years since I wrote that bit, but I clearly remember spending a lot of time tweaking the exact function that was used to bring things to the front, as all these ancient win32 functions have very slightly different behaviours and there were all kinds of subtle contexts in which things didn't quite work as you'd expect them to. So I'd be reluctant to change this as it's almost certain that someone's app would suddenly start behaving in a very slightly different way..

 


#7

Ok, I understand. I'll post a note here if I run into some regression when SetForegroundWindow is replaced by SetActiveWindow