|
Hi, I have a process that contains a form. This process creates another process that has its own form. I want to set the owner of the child process form to be the form of the parent process. Is it possible? BTW, the reason I want to do it is that I want the second form to always be on top of the parent form. Is there any other way to guarantee this without setting the owner form (I don't want to use top-most windows...)?. Thanks, Alon.
| | Alonbo Sunday, October 04, 2009 8:28 AM | You might want to try to SetParent function. See pinvoke.net for a good example on how to platform invoke the SetParent function.
Geert van Horrik - CatenaLogic
Visit my blog: http://blog.catenalogic.com
Looking for a way to deploy your updates to all your clients? Try Updater! - Marked As Answer bynobugzMVP, ModeratorSunday, October 04, 2009 12:41 PM
-
| | Geert van Horrik Sunday, October 04, 2009 9:47 AM | You might want to try to SetParent function. See pinvoke.net for a good example on how to platform invoke the SetParent function.
Geert van Horrik - CatenaLogic
Visit my blog: http://blog.catenalogic.com
Looking for a way to deploy your updates to all your clients? Try Updater! - Marked As Answer bynobugzMVP, ModeratorSunday, October 04, 2009 12:41 PM
-
| | Geert van Horrik Sunday, October 04, 2009 9:47 AM | What you are trying to do is strictly forbidden by the Windows SDK docs, the parent window must belong to the same process. There are however app compat hacks in Windows that might make it work for you. They were designed to support Windows 3.x programs where this wasn't a problem because 3.x didn't support multitasking. Specifically Office programs are known to not support this. You'll have to try.
Hans Passant. | | nobugz Sunday, October 04, 2009 12:41 PM | OK, so if it is forbidden, how can I assure that form A (created by process A) is always on top of Form B (created by process B) without using TopMost property?
| | Alonbo Sunday, October 04, 2009 2:18 PM | As far as I know, using SetParent with handles from different processes is an undocumented feature and not allowed by Microsft. | | Alonbo Sunday, October 04, 2009 2:20 PM | Hi Alon,
Since you didn't say when the form created by the child process is on top of the "parent" form, should or should not the parent form being able to have input focus, here I assume what you want is something works like a modal dialog. The following code starts a Notepad process, and makes sure the Notepad window is always in front of the MainForm. The basic idea is to intercept the activate messages of the MainForm, insert the MainForm after the Notepad window in the Z order and set the Notepad window foreground.
public partial class MainForm : Form
{
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ReleaseCapture();
private const uint SWP_NOSIZE = 0x0001;
private const uint SWP_NOMOVE = 0x0002;
private const int WM_ACTIVATE = 0x0006;
private const int WM_MOUSEACTIVATE = 0x0021;
private const int MA_NOACTIVATEANDEAT = 4;
public MainForm()
{
InitializeComponent();
}
Process notepad = null;
private void MainForm_Load(object sender, EventArgs e)
{
notepad = Process.Start("notepad.exe");
notepad.WaitForInputIdle();
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_MOUSEACTIVATE:
SetBehind();
m.Result = new IntPtr(MA_NOACTIVATEANDEAT);
return;
case WM_ACTIVATE:
SetBehind();
m.Result = IntPtr.Zero;
return;
}
base.WndProc(ref m);
}
private void SetBehind()
{
if (notepad != null &&
!notepad.HasExited)
{
ReleaseCapture();
SetWindowPos(this.Handle,
notepad.MainWindowHandle,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(notepad.MainWindowHandle);
}
}
}
Please let me know if this is what you want.
Regards, Jie MSDN Subscriber Support in Forum If you have any feedback on our support, please contact msdnmg[at]microsoft.com
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
If you have any feedback, please tell us.
The CodeFx Project
My Blog (in Simplified Chinese) | | Wang, Jie Monday, October 05, 2009 7:43 AM | What you are trying to do is strictly forbidden by the Windows SDK docs, the parent window must belong to the same process. There are however app compat hacks in Windows that might make it work for you. They were designed to support Windows 3.x programs where this wasn't a problem because 3.x didn't support multitasking. Specifically Office programs are known to not support this. You'll have to try.
Hans Passant.
Then shall we unmark Geert's SetParent solution as an answer?
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
If you have any feedback, please tell us.
The CodeFx Project
My Blog (in Simplified Chinese) | | Wang, Jie Monday, October 05, 2009 7:45 AM | Hi Jie,
Thanks for your reply. I like your solution but I think something is still missing in my case-
I know that there are more messages for activating the window (other than the two you've mentioned in your code).
Do you know where can I find more information on these missing messages?
Thanks in advance,
Alon.
| | Alonbo Tuesday, October 06, 2009 9:11 AM | Hi Alon, Another message I can think of is WM_ACTIVATEAPP. Yes, I've only tested the sample code with mouse and keyboard, not 100% sure if it works fine with other input devices (pen? touch?). You may also want to check the description of WM_ACTIVATE and WM_MOUSEACTIVATE, making sure they covers your requirements or not. The links to the MSDN Library online contains all the messages and you can find out more from there. Hope this helps. Regards, Jie MSDN Subscriber Support in Forum If you have any feedback on our support, please contact msdnmg[at]microsoft.com
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
If you have any feedback, please tell us.
The CodeFx Project
My Blog (in Simplified Chinese) | | Wang, Jie Tuesday, October 06, 2009 10:29 AM | Hi Jie, I found a problem with your suggestion: When FormA is the real parent of FormB (this was my intention from the first place) - they are always 'attached', meanning nothing can come between them. The following scenario (using your suggestion) cause a third form to come between the first two: 1. run the sample (both form and notepad are opened) 2. run windows explorer 3. put windows explorer on top of the first two forms. 4. switch to notepad -->windows explorer is located between the two forms
I need that the form and notepad to always come together and if notepad is selected - the original form jumps (in Z order) to be behind notepad.
any suggestion? Thanks, Alon.
| | Alonbo Tuesday, October 06, 2009 3:04 PM | Hi Alon,
Yes, I'm aware of that. If we were working on a native C/C++ project, then we can use hooks to monitor the child process and make sure the two windows stick together. However, we can't do that in .NET because we don't want to inject CLR into other processes.
I can't think of a better solution right now. Althought the word "Timer" is hopping up and down somewhere in my mind, I don't want to do that ugly workaround - periodically check the Z order and fix it if some other window is inserted between our windows.
Or if you have control over the child application, maybe making some changes to the child app code so it will be aware of the parent app can also solve the problem.
Regards, Jie MSDN Subscriber Support in Forum If you have any feedback on our support, please contact msdnmg[at]microsoft.com
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
If you have any feedback, please tell us.
The CodeFx Project
My Blog (in Simplified Chinese) | | Wang, Jie Wednesday, October 07, 2009 9:11 AM | Hi, Does SetWindowPos ensures that when it sets Z order of a window - it is right beneath the other window? if so, I can (as you said) - create a C/C++ 'server' that ensures the Z order of the windows (hooks to the applications and 'listens' to WM_ACTIVATEAPP or something like this). Thanks, Alon.
| | Alonbo 20 hours 3 minutes ago |
|