PDA

View Full Version : How to raise application from background?



oficjalne100
22nd February 2011, 12:34
Hi

I am writting kind of text editor program. So the main feature is "running only one instance" and raising app from background when user invoke it with file name as parameter. Already I have done comunication via local socket (between already running app and new starting app), but I have no idea how to raise it from background when it obtain file name from socket. I use QWidget::raise() and QWidget::activateWindow() but it does not work, the only effect is blinking program icon on task bar.

In other words I want the same behaviour (raise program from background) as Chrome or any text editor when it is already running as "only one instance" and when user invoke it with file name or URL as parameter.

System: Windows 7 32bit.

agarny
22nd February 2011, 12:54
As you noticed, activateWindow() is not what you need on Windows. Personally, I do the following:

// Retrieve your application's window Id

WId mwWinId = winId();

// Restore your application, should it be minimized

if (IsIconic(mwWinId))
SendMessage(mwWinId, WM_SYSCOMMAND, SC_RESTORE, 0);

// Bring your application to the foreground

DWORD foregroundThreadPId = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
DWORD mwThreadPId = GetWindowThreadProcessId(mwWinId, NULL);

if (foregroundThreadPId != mwThreadPId) {
// Your application's thread process Id is not that of the foreground window, so
// attach the foreground thread to your application's, set your application to the
// foreground, and detach the foreground thread from your application's

AttachThreadInput(foregroundThreadPId, mwThreadPId, true);

SetForegroundWindow(mwWinId);

AttachThreadInput(foregroundThreadPId, mwThreadPId, false);
} else {
// Your application's thread process Id is that of the foreground window, so
// just set your application to the foreground

SetForegroundWindow(mwWinId);
}

oficjalne100
22nd February 2011, 18:42
Thank you for reply!

But consider case when my app is not minimized on task bar and not at the foreground. In that case my app will not be raised from background! So this is not complete solution.

agarny
22nd February 2011, 18:45
But consider case when my app is not minimized on task bar and not at the foreground. In that case my app will not be raised from background! So this is not complete solution.May I ask you whether you have actually tried the code I posted? For your information, I use that code in my application and it does exactly what you are after (I have even double-checked with my application).

oficjalne100
22nd February 2011, 19:07
Ofcourse I copy paste your code in to my app and I was trying it. My test procedure was as follow: 1) run my app from file manager 2) run cmd.exe in the same directory 3) type program name and file name as parameter and hit Enter. Then not minimized app is not raised but only blinking on taskbar. In the same situation Chrome raises properly. My system is Windows 7 32bit.

agarny
22nd February 2011, 19:18
Well, I don't know exactly how you are using my code, but I can guarantee you that it works. So, I am assuming you are doing something wrong somewhere. Out of curiosity, you mentioned wanting to run only one instance of your application at any given time. How do you go about that? Are you using QtSingleApplication? I personally do and then make the following connection:
QObject::connect(&app, SIGNAL(messageReceived(const QString&)),
&win, SLOT(singleAppMsgRcvd(const QString&)));with singleAppMsgRcvd() containing the code I posted, and as I said this works perfectly fine for me, so...

oficjalne100
22nd February 2011, 19:39
My app must receive parameters from command line as well run another instance when it is invoke without any parameters. QtSingleApplication is new to me but after quick look at it's documentation I think it is not best solution for me. I create custom Application class with local socket and with signal showMainWindow() which I emit to main window raiseWindow() after obtaining file name from socket. I do exactly the same as it is in demo Browser from Qt demos. And in true I have the same behaviour (this is bad).

agarny
22nd February 2011, 20:19
My app must receive parameters from command line as well run another instance when it is invoke without any parameters. QtSingleApplication is new to me but after quick look at it's documentation I think it is not best solution for me. I create custom Application class with local socket and with signal showMainWindow() which I emit to main window raiseWindow() after obtaining file name from socket. I do exactly the same as it is in demo Browser from Qt demos. And in true I have the same behaviour (this is bad).You are not making sense to me, so I am going to leave you to it. Just in case, though, QtSingleApplication inherits from QApplication which can definitely deal with parameters. Anyway, I know it all works fine for me (incl. with parameters), so too bad for you indeed that you can't get things to work.

oficjalne100
12th March 2011, 15:49
There is interesting article which describe this problem clearly: http://blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx. It describes clearly, that your solution can't work, or if work then it is windows inconsistence. Any way your code do not make what I want under Windows 7.

agarny
12th March 2011, 17:57
There is interesting article which describe this problem clearly: http://blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx. It describes clearly, that your solution can't work, or if work then it is windows inconsistence. Any way your code do not make what I want under Windows 7.Please read that article again and you might (finally!) realise that my solution can and does work. What I, and many other people, do is partly explained by the guy in his article. What is true, though, is that it goes against Windows' preferred behaviour (since Windows XP?), but I know what is good for my application while Microsoft doesn't.

stampede
12th March 2011, 18:52
I know what is good for my application
Be careful, in this case this is danger close to "I know what is good for the user". IMHO there is nothing more annoying than application that pops at you out of nowhere, so this time I can agree with Microsoft, simple taskbar notification is less intrusive.

agarny
12th March 2011, 19:04
Be careful, in this case this is danger close to "I know what is good for my user". IMHO there is nothing more annoying than application that pops at you out of nowhere, so this time I can agree with Microsoft, simple taskbar notification is less intrusive.I agree with you with nothing more annoying than an application popping up out of nowhere, but here this is done in case there is already an instance of the application running and the user starting a second instance of that application. In such a case, I want to the first instance to be shown to the user and the second instance closed. In this particular case, I think it's completely fine to go against the default Windows' behaviour.

Otherwise, about "I know what is good for my user"... well, though my application is going to be used by many people, I will also happen to be one of those people. So, it's not, here, a matter of the programmer not being a user and, yet, thinking s/he knows better than the user. Also, I have done the above in the previous version of my application (which is written in Delphi and therefore only runs on Windows, hence my switching to Qt to have it cross-platform).

stampede
12th March 2011, 19:37
So, it's not, here, a matter of the programmer not being a user and, yet, thinking s/he knows better than the user.
As you've said, you are one of many users, and it's impossible to know what is the best for all of them. If I were using your app, I'd prefer notification in taskbar (yes, I'm the client from hell :))
I can accept raise from background if I explicitly click on the icon in explorer (or start via cmd), but only then. If an application steals the focus without my clear permission, then well ... /dev/null awaits ;)
Sorry for little off topic btw.

squidge
12th March 2011, 20:57
Isn't that what agarny is doing? The application is only popping up if you double click the application on your desktop (or start bar, or wherever).

What he didn't want is double clicking the icon and the previous instance just flashing on the task bar. To me, that would be unacceptable. If I'm clicking the icon, I want the application to be in the foreground and not wink at me.

oficjalne100
12th March 2011, 21:37
Ok! I find the working solution for this problem. I describe this in the case somebody want do it.

First of all there is mentioned article: http://blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx. It describes Microsoft point of view. There are two ways to solve this problem: use SetForegroundWindow in second runing process, or use AllowSetForegroundWindow in second runing proces in couple with SetForegroundWindow in first proces. I choose the latter variant because it does not mess in my project. So I do following steps:

1. In first process (Proc1) open local socket and listen on it.
2. In second process (Proc2) connect to the local socket Proc1.
3. In Proc1 write to socket the proces ID.
4. In Proc2 read proces ID and call AllowSetForegroundWindow.
5. In Proc2 write list of file names that should be opened in Proc1.
6. In Proc1 open each file and call SetForegroundWindow.

stampede
12th March 2011, 21:44
@squidge: You are right, I should read the topic more carefully. I was thinking about programmatically raising up from background in general whole time. My bad.

agarny
13th March 2011, 03:18
As you've said, you are one of many users, and it's impossible to know what is the best for all of them. If I were using your app, I'd prefer notification in taskbar (yes, I'm the client from hell :))
I can accept raise from background if I explicitly click on the icon in explorer (or start via cmd), but only then. If an application steals the focus without my clear permission, then well ... /dev/null awaits ;)
Sorry for little off topic btw.Well... this is exactly the situation we are talking about here. I mean, having the user explicitly clicking the icon in explorer or start the application from the command line...

Rajesh.Rathod
10th October 2013, 09:30
The first solution code provided by agarny is working fine for me, Thanks to agarny for your solution.