Is it possible for Owner window in WPF be on top of Child window when you click on it while Owner window is below Child window?
here is example how I call child window:
Window2 window = new Window2();
window.Owner = this;
window.Show();
Parent/Owner window will always be under child window.
To get the behavior you want, you don't want to set the Owner on either window.
You, of course will have to handle the logic yourself when closing either of the windows to close your imaginary "child" window.
There may be some other logic you'll have to implement related to minimizing, maximizing, etc.
Many of the answers on this page involve nulling-out the Window.Owner property for some or all of the (non-MainWindow) windows in your System.Windows.Application. While this is a simple and easy fix that does indeed, in isolation, fix the issue of Window overlap, unfortunately it also inhibits a lot of useful application-wide functionality that WPF seems otherwise eager to provide in the areas of:
Application activation/deactivation (via mouse-click, desktop Alt-Tab switching, etc...),
correct observance of the Application.ShutdownMode property, and generally,
orderly cleanup, resource disposal, and exit of your Application upon shutdown.
It is possible fix the Window overlap issue while still preserving these system-wide WPF features by instead designating a special invisible window instance as your Application.MainWindow.
Modify your application so that the first Window it creates--which is the Window that gets assigned to Application.MainWindow--is a special dummy Window that is then made invisible by setting its Visibility to Visibility.Hidden or calling Window.Hide(). This will not hide its owned windows. Then, ensure that your desired "main" window containing your true content, plus all the other windows, owned by this invisible window.
Once hidden, the dummy Window will not show in the Windows 10 taskbar. You can set the Window.ShowInTaskbar property on whichever of the visible windows you deem appropriate to simulate apparent special designation, as required.
This approach allows any of the visible windows in your Application to be on top of the others, while still preserving WPF features and behaviors for system-wide app activation. For example, when the Application is activated (by clicking on any one of the windows, or via Alt-tab), all of the application's windows are together brought above any other desktop app windows, while still preserving the most recent "in-app" Z-order. WPF shutdown functionality is also preserved, including correct observation of the Application.ShutdownMode logic in accordance with the invisible MainWindow (or all the others) being closed.
I ran into a similar situation. I solved this by simply removing the owner after showing the window.
Window2 window = new Window2();
window.Owner = this;
window.Show();
window.Owner = null;
Edit:
Someone replied to this, and while looking at it, I decided I wanted to make an extension method.
public static void ShowAsIfChildOf(this Window childWindow, Window parentWindow)
{
childWindow.Owner = parentWindow;
childWindow.Show();
childWindow.Owner = null;
}
Please note that the solution mentioned by Licht
Window2 window = new Window2();
window.Owner = this;
window.Show();
window.Owner = null;
seems to me to be the same as
Window2 window = new Window2();
window.Show();
i.e., as if no ownership relationship has been set, i.e., when you close the owner window the owned windows do not close, etc., and may not be a solution when one would wish to have all of the ownership relationship features except "An owner window can never cover an owned window."
Once this relationship is established, the following behaviours are exhibited:
If an owner window is minimized, all its owned windows are minimized as well.
If an owned window is minimized, its owner is not minimized.
If an owner window is maximized, both the owner window and its owned windows are restored.
An owner window can never cover an owned window.
Owned windows that were not opened using ShowDialog are not modal. The user can still interact with the owner window.
If you close an owner window, its owned windows are also closed.
The best solution here looks to me to be the one with hidden main dummy window described by Glenn Slayden, at the link below, though it would be nice if there was a simpler one.
https://stackoverflow.com/a/66110288/19683309
Don't set Owner for child window, then in MainWindow handle OnClosing event like this:
private void MainWindow_OnClosing(object? sender, CancelEventArgs e)
{
foreach (var window in Application.Current.Windows)
{
if (window is Window appWindow)
{
if(appWindow.Equals(Application.Current.MainWindow))
continue;
appWindow.Close();
}
}
}
Related
I'm building a Revit plugin. It consists of a dockable pane that (among other elements) has a button. I want to open a new, separate window when a user clicks this button.
At the moment, i create a new Window, but i don't know if that's the right way to go, because now i see two Revit icons on a task bar. I do not have experience as Revit user, i'm new to Revit development, so i'm not sure if this should be the case (two icons) and as silly as it sounds, i do not have admin rights to install random addins and get a feeling of expected user experience.
I create a Window using the following code:
ParametersMissingValueWindow parametersMissingValueWindow = new ParametersMissingValueWindow();
parametersMissingValueWindow.Show();
Based on the understanding of a dockable pane that i have, i think i do not want to create another dockable pane, but just a simple modeless dialog. I wasn't able to find any examples using WPF. Hence, any information whether this is the way to go or help on how to achieve this is highly appreciated.
The Show method takes an optional parent window argument. Specify the Revit main window as the parent window, and your modeless dialogue will be recognised as belonging to the running Revit process. It is accessible from the MainWindowHandle property.
var MyWindow = new MyWindow();
HwndSource hwndSource = HwndSource.FromHwnd(UIApplication.MainWindowHandle);
Window wnd = hwndSource.RootVisual as Window;
if (wnd != null)
{
MyWindow.Owner = wnd;
//MyWindow.ShowInTaskbar = false;
MyWindow.Show();
}
It's not necessary to assign a value to ShowInTaskbar property, but it actually achieves what i wanted to do from the beginning (have only one program open in taskbar), so i left it as part of the solution, but commentted out.
Big thanks to Jeremy Tammik for pointing out the parent property.
You can use WPF to setup a window to use in revit.
MyWPF menu = new menu();
System.Windows.Window wind = new System.Windows.Window();
wind.ShowDialog(); //--> the window shows up and make stuff for revit
if you need the menu to be a dockable one check this source.
Perhaps is not up to date and you will need to adapt the code to the new api.
I have a form that i want to always be on top whenever it is opened in the application but i dont want it to be on top when the main form is minimized or another application is navigated. I want it to be on top only in my application.
Following the answer in the question : How to make a window always stay on top in .Net?
this.TopMost = true;
Makes the form on top but the form is still on top when another application is navigated to or the main form is closed.
Pls how do i make the form only on top in the application while enabling user to still work on the main form?
You are looking for an owned window. It is always on top of the owner and it gets minimized along with the owner. Good examples of owned windows are the various helper windows inside Visual Studio. You can undock them but they'll always stay on top of the VS main window.
You create an owned window by displaying it with the Show(owner) overload. Or by explicitly assigning its Owner property.
Set the top level and then set the owner, example below.
public Form1()
{
InitializeComponent();
Form2 f2 = new Form2();
//top level not really needed
f2.TopLevel = true;
f2.Show(this);
}
I have a little problem with my MDI Parent Window and the MDI Childs window. The problem is that i need 3 child window but only the first it'll be maximize, so i use this code:
UserAdmin usrWindow = new UserAdmin();
usrWindow.MdiParent = this;
usrWindow.WindowState = FormWindowState.Normal;
usrWindow.Show();
For the others 2 windows i use this code:
TaskAdmin tskWindow = new TaskAdmin ();
tskWindow.MdiParent = this;
tskWindow.Show();
I only need that the first windows is maximized, but when i open the others they open maximized too.
How can i do to open one maximized and others in the default size over the first?
Thanks
That is not possible, yet can be achieved with very very tricky (using WndProc override, custom event loops) and ugly code which will not work in different operation systems in the same manner (i.e WinXP/WinXPSP1/WinXPSP3/Vista/Win7)
Your TaskAdmin forms cannot have an MDIParent in this situation. You need to either float these forms over the MDIParent or place them in panels in the MDIParent, docked to a side.
I have a Windows Forms application that opens MDI child forms. When I select those forms, I need to set or render its windowstate to Maximized. The problem is, when I navigate between the open forms, it reverts back to the normal window state, and when I set the window state to maximized again, it shows the transition from normal to maximized state and it doesn't look nice.
How can a Windows application be created that have an MDI parent form that opens many MDI childs in maximized window state?
Here's an answer based on using the MDI "Parent Form and Child Form paradigm," with the following assumptions :
you have a MenuStrip control 'Dock = 'Top on your MDIParentForm, and you've implemented the automatic MDI &Window menu handler as described in : How to: Create an MDI Window List with MenuStrip
you are creating new child forms that :
a. do not have a MaximizeBox, MinimizeBox, etc., but may have ControlBox (for closing them)
b. these child forms may be resizable or not : we won't consider the implications of that here.
You want these MDIChildForms to display maximized in the MDIParent Form, but not to obscure the MDIParentForm's menu.
Okay : assuming you have all your child Forms fully designed, "waiting in the wings" : we might see some code like this in your MDIParentForm code :
// create instances of your child forms
Form2 f2 = new Form2();
Form3 f3 = new Form3();
Form4 f4 = new Form4();
Form5 f5 = new Form5();
private void MDIParentForm1_Load(object sender, EventArgs e)
{
f2.Text = "subForm1";
f3.Text = "subForm2";
f4.Text = "subForm3";
f5.Text = "subForm4";
f2.MdiParent = this;
f3.MdiParent = this;
f4.MdiParent = this;
f5.MdiParent = this;
f2.Dock = DockStyle.Fill;
f3.Dock = DockStyle.Fill;
f4.Dock = DockStyle.Fill;
f5.Dock = DockStyle.Fill;
f2.Show();
f3.Show();
f4.Show();
f5.Show();
}
At this point, the dock style 'Fill applied to the child forms will make them full-screen, and keep them from obscuring the MDIParentForm menu : and the menu will allow you to auto-select which one is frontmost.
Now, if you want to do fancier stuff : like resizing the child Forms, tiling them, cascading them. You are going to have to change the 'Dock property of these child windows : and then you can make use of the built-in MDI paradigm window arranging facilities as described here : How to: Arrange MDI Child Forms
And if you want to create multiple instances of one type of pre-defined child form : How to Create MDI Child Forms ... see the example on how to use a 'New menu entry : may prove useful.
If you want the window state to always be maximized, I'd recommend switching away from an MDI Form. A TabControl may work better, in that case.
MDI forms have quite a few usability issues, which is why they are not commonly used anymore, and tend to be replaced with other controls/options.
After reading Reeds answer and especially your comment:
problem with tabcontrol is, i have a
lot of controls used per child form
Maybe this will help:
Don't put your controls into a Winform. Instead encapsulate them into a UserControl (maybe it already works by changing your inheritance from Form to UserControl).
Now put every UserControl on it's own TabPage and set its Dock property to Fill. Now you are able to change each UserControl on it's own, without any interference to another control on another TabPage (as far as you don't built in any connection).
If you intend to give up on MDI, you could have a look at docking frameworks like WeifenLuo or DigitalRune. These are free, for other options you can have a look here: http://windowsclient.net/downloads/folders/controlgallery/tags/Windows+Forms+Docking+Windows/default.aspx
EDIT:
If I remember well, DigitalRune allows the usage of windows forms as containers for docked content so the migration effort would be smaller.
When using System.Windows.Forms.ShowDialog(IWin32Window), should I be able to pass in an IWin32Window representing any window handle and have it be modal with respect to that window?
As part of an Internet Explorer 7 extension I'm trying to open a window modal with respect to an Internet Explorer tab. It's not the currently selected tab, but I can get the hwnd of the tab OK. However, when I pass this to ShowDialog my Form is shown, but it's not modal with respect to anything: I can still do things in Internet Explorer, including in the tab that's supposed to be the owner. My form is shown floating above the Internet Explorer windows and it stays on top, so it's not like it's just opened as a normal form, but it's not correctly modal.
Using Spy++, I can find my form and it's owner handle is correctly set.
Does this mean that something has gone wrong, or I'm doing something wrong? How do I make my form correctly modal?
FYI, I'm using this wrapper class to create an IWin32Window from a hwnd (thanks Ryan!):
/// <summary>
/// Wrapper class so that we can return an IWin32Window given a hwnd
/// </summary>
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
public WindowWrapper(IntPtr handle)
{
_hwnd = handle;
}
public IntPtr Handle
{
get { return _hwnd; }
}
private IntPtr _hwnd;
}
UPDATE: Using Internet Explorer 7 & .NET 2.0
UPDATE: Playing around some more with Spy++ and the handles it exposes, I find that if I use a different hwnd then I can make my window modal to the tab:
I was using the tab's hwnd as suggested by the IWebBrowser2.HWND doc, which in Spy++ appears as class TabWindowClass. It has a child of class Shell DocObject View, which has a child of Internet_Explorer_Server. If I use the hwnd of the Internet Explorer_Server then it works correctly, for example, when I click with the mouse on other tabs, Internet Explorer reacts normally. When I click with the mouse on the tab of interest, it plays the windows d'oh sound and doesn't do anything.
I don't yet know how to programatically get the Internet_Explorer_Server hwnd, but it should be possible.
Also, for what it's worth, while playing with other window handles I was generally able to make my form modal to other applications and dialogs. So I guess the answer to my question is 'many but not all handles'... possibly it depends on the application?
UPDATE: Another side-note: The original reason I wanted to make my form modal to the tab instead of the whole window is that when opening a MessageBox from my form, passing the form as owner, the MessageBox would not always open on top of my form. If a new Internet Explorer tab had just been opened but wasn't active then the MessageBox would be hidden and that tab would start flashing. However, since Internet Explorer was disabled with my form opened modal it wasn't possible to switch to that tab, so Internet Explorer would be frozen. I thought that opening my form modal to the tab would solve this, but I've found another solution is to avoid using MessageBox: if I use a second form and ShowDialog(this) from my first form then the second form correctly opens to the front. So it seems that Form.ShowDialog() works better than MessageBox.Show() in some cases. More discussion in Problems with modal dialogs and messageboxes.
ShowDialog() does two important things. It starts pumping a message loop so it acts modally to the calling code. And it disables any other windows in the application with a EnableWindow(false) API call. The latter is what is not happening in your case. Not entirely surprising, considering that the window that needs to be disabled is not a WF window.
You may need to call EnableWindow() yourself. Be sure to re-enable it in before the dialog closes or Windows will go hunting for another app's window to give the focus to.
Your code is correct. The problem you are likely running into though is that IE has a threading model related to its tabs. I don't know the exact details but the short version is that each tab can and likely is running on a different thread than other tabs.
The Modal'ness of a dialog is specific to the thread where the dialog is running. UI on other threads will be unaffected by a model dialog on another thread. It's entirely possible you are able to access tabs which are running on a different thread for this reason.
Here's a more concise version of Ryan/Rory's WindowWrapper code:
internal class WindowWrapper : IWin32Window
{
public IntPtr Handle { get; private set; }
public WindowWrapper(IntPtr hwnd) { Handle = hwnd; }
}
I have never tried this from an IE extension, but I have a hunch that IE may not "respect" a Win32-style modal window the same way it does a modal window raised from Javascript using window.open().
Have you tested this code against something other than IE, just to confirm it works the way it should for other applications?
here is a build in solution in .NET:
public static NativeWindow FromHandle(IntPtr handle)