PDA

View Full Version : Getting the handle of the window



Luc4
14th May 2010, 16:24
Hi! I wrote an application which starts some processes using the QProcess class. I noticed that, trying to get the handle of the main window when no process is started results in the correct handle, otherwise I get 0. Any idea why this is happening? The child process has a completely different PID from the original one...
Thanks!

wysota
14th May 2010, 16:49
Please provide a minimal compilable application reproducing the problem.

Luc4
14th May 2010, 17:10
I'll try to produce one. I forgot to mention that I'm working under Windows CE.

Luc4
14th May 2010, 19:31
I created one now and it seems to be ok. I don't know in which occasions it happens. Anyway, my application should receive at its handle a ShowWindow and a SetForegroundWindow, but it seems no event is received. I supposed it was related to the fact the handle was 0, but it seems even if the handle is ok, I get no event in the event(QEvent* event) method anyway. Is there any other way to know when those two windows functions are called to my main window handle?
Thanks for your help!

Luc4
15th May 2010, 14:20
OK, I analyzed the logs and I noticed the handle was 0 in case the window whose handle was retrieved was hidden. Is this behavior expected? I needed the handle to show the window and to bring it to the foreground. This was an attempt to have some messages in my qt application after ShowWindow and SetForegoundWindow were sent to my window.

wysota
15th May 2010, 14:46
How exactly do you retrieve the handle?

Luc4
15th May 2010, 14:56
I didn't write the application which does this, but, I've seen the code, and it is a C# application which uses the .NET framework. It creates a Process object using the static method GetProcessById, where the ID is the PID of the process of my Qt application. Then, it gets the handle using the property MainWindowHandle, which, according to the documentation, returns 0 for the windows which are hidden and not in the taskbar. My window is hidden but I don't know if it is in the taskbar (I'm testing on a Windows CE without the taskbar).

Anyway, the real problem I'm trying to solve is to sense somehow from my Qt application when those functions (ShowWindow or SetForegroundWindow) are sent to my mainwindow. I can even show the window if it is not possible to keep it hidden. I tried to hide it because I thought that the show event was not sent to my application because it wasn't hidden.

wysota
15th May 2010, 15:54
Why not use QWidget::winId() and convert that to a windows handle? I'm sure your handle is invalid before the window is first shown. Qt tries to defer creating the handle as much as possible and for child windows it tries to never create them at all. Either call winId() to explicitely create the handle and then use your program or call winId() and then convert it to a handle when you need it.

Luc4
15th May 2010, 16:16
mmh... If I'm uderstanding correctly you mean that I should send a show signal using winId(). Unfortunately I cannot modify the C# application which sends to my application the ShowWindow and the SetForegroundWindow. I need somehow to catch through Qt when those functions are sent to my window. I supposed ShowWindow should raise a QEvent::Show event in my evet(QEvent* event) function, but I get nothing. No event is sent to that function. I placed a log in there. Maybe it arrives somewhere else?
Thanks for your time!

wysota
15th May 2010, 16:35
Ok, let's start from the beginning, because I think I misunderstood what you were doing. What is the ultimate effect you want to obtain? What is the role of the C# application in all this?

Luc4
15th May 2010, 19:26
Ok, the problem is that I have some windows open, the first W1 is this C# application, then, over that window there is a window W2, which is my window of Qt application I'm writing. Then, in this Qt application, I run another application as a QProcess, with a window W3 (this can be another Qt application or something else). The order of the windows is W1, W2 and W3, where W3 is the topmost.

It happens that, in response to some events, window W1, which is the one written in C# behind all the others, comes over all the others. Then, that window sends a signal of ShowWindow and SetForegroundWindow to my Qt process (which owns W2), which comes again over W1. I need to handle this situation to show the process I started (which I called W3). I want W3 to be visible again,

Unfortunately, I noticed that once W1 calls those two functions, my Qt window W2 comes correctly over, but I get no event. I cannot find a way to handle that situation so I can bring over W3 somehow. I opened this topic as I supposed no QEvent::Show was received as W2 was visible. So I tried to hide it so that a show event could be received. Unfortunately, I discovered that the C# application got a handle 0 when the window W2 was hidden.

The restriction is that I can't recompile the C# application unfortunately. I didn't write it.

Thanks for any advice and for your answers!

EDIT: I forgot to mention a strange behavior I noticed. When W1 calls those two functions and W2 comes over, I get that, clicking on the portion of the screen where W3 was (it is not visible now), makes W3 visible again, just like only a repaint was needed. Isn't this strange? Anyway, I don't think this is Qt related.

wysota
15th May 2010, 19:55
This is all a bit weird design, I have to admit :) A window instead of lowering itself is artificially raising another window so that it can raise yet another window? Hmm... If you can't change this design, at least design W2 and W3 applications in a better way - provide some IPC mechanism to communicate between them and try to find a way for the first application to change its behaviour to something more sane :) The problem you are experiencing seems to be with W1 and not W2 so there isn't much you can do in W2 to change that.

squidge
15th May 2010, 23:57
If this is a Windows application, then maybe a better solution would be that App2 sets its Parent window property to that of App1, and App3 sets its Parent window property to that of App2, then the Windows will behave as if they were all in the same app and you don't have to do any of this monitoring events and bringing other processes windows to the front (which may fail on Windows7 without UAC compliance)

Luc4
16th May 2010, 13:02
This is all a bit weird design, I have to admit :) A window instead of lowering itself is artificially raising another window so that it can raise yet another window? Hmm... If you can't change this design, at least design W2 and W3 applications in a better way - provide some IPC mechanism to communicate between them and try to find a way for the first application to change its behaviour to something more sane :) The problem you are experiencing seems to be with W1 and not W2 so there isn't much you can do in W2 to change that.

I completely agree with you. This is not a good architecture, but I cannot change W1. I can only work on W2 and W3, so I'm trying to find any way to understand when those two functions are called to bring up W2, without success...
I thought I could work with focusIn events. When ShowWindow and SetForegroundWindow are called, W2 comes over, and I suppose some focusIn events will arrive. Unfortunately I cannot predict to which widget they'll arrive, right?


If this is a Windows application, then maybe a better solution would be that App2 sets its Parent window property to that of App1, and App3 sets its Parent window property to that of App2, then the Windows will behave as if they were all in the same app and you don't have to do any of this monitoring events and bringing other processes windows to the front (which may fail on Windows7 without UAC compliance)

The problem is that W1 is C#, W2 is Qt and W3 can be whatever. I cannot change W1, so it is calling ShowWindow and SetForegroundWindow to W2. This means that anything I can do, I suppose, cannot change the fact that W2 is overlapping W3 :) This is quite a mess, I know :D

Many thanks for your help guys!