How do bring a WPF Window to front? - wpf

I have created a single-instance application and want to activate an already opened window if the user starts the app multiple times. This works fine however I have the problem, that if the already opened window is beyond another applications window, I must bring it to front.
I have tried window.Focus() and window.Show() but both of them seem not to work. As a workaround I use …
bool oldTopMost = window.Topmost;
window.Topmost = true;
window.Topmost = oldTopMost;
window.Focus();
… this does the job but looks to me very ugly. Has anyone a better solution for this?

You could use Window.Activate instead:
window.Activate();
This is the WPF equivelent to calling SetForegroundWindow.

Related

WPF User Control On MFC Dialog Showing Hidden Every Once and a While

I am running into a very strange problem that I wanted to see if anyone else has seen. I have a C++ application (compile with CLR support) that has a MFC dialog which hosts a WPF user control. Every once and a while, the WPF user control will not appear when the dialog opens. The control is there as I can press a button on that user control. Obviously, I cannot see it, but the button still responds to a click event if I click the area where the button is supposed to be.
The strange part in all this is how sporadic it happens. Sometimes it happens the first time the user goes into the dialog after starting the application. Other times, it will happen after successfully going into the dialog a few times. We have deinitely not found any pattern to when it will happen. It just happens once and a while. Also, we have seen this across all different operating systems - XP, Vista and Win7.
To correct the problem, simply closing the application and relaunching it norally cures it.
In terms of the code, the standard approach for WPF user controls on MFC dialogs is being used:
// Create the initial object
System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters ("BatchSelectionContainer");
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->Height = height;
sourceParams->Width = width;
sourceParams->ParentWindow = System::IntPtr(parent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD;
BatchSelectionDialogGlobals::gHwndSource = gcnew System::Windows::Interop::HwndSource(*sourceParams);
BatchSelectionDialogGlobals::gHwndSource->AddHook(gcnew HwndSourceHook(ChildHwndSourceHook));
// Save a reference to the new frame
BatchSelectionDialogGlobals::BatchSelectionFrame = gcnew ProteinSimple::ParticleDetection::Console::BatchSelection();
// Establish an event handler for the buttons
BatchSelectionDialogGlobals::BatchSelectionFrame->EnableExecuteButton += gcnew ProteinSimple::ParticleDetection::Console::BatchSelection::GeneralHandler(&BatchSelectionDialog::EnableExecuteButton);
BatchSelectionDialogGlobals::BatchSelectionFrame->DisableExecuteButton += gcnew ProteinSimple::ParticleDetection::Console::BatchSelection::GeneralHandler(&BatchSelectionDialog::DisableExecuteButton);
// Finalize the visual parts and return the handle
BatchSelectionDialogGlobals::gHwndSource->RootVisual = BatchSelectionDialogGlobals::BatchSelectionFrame;
return (HWND) BatchSelectionDialogGlobals::gHwndSource->Handle.ToPointer();
This is certainly a strange one. I have some of my users that have never seen it, while others it happens many times a day.
It feels like a bug in MFC in how it displays the WPF control. However, I have searched on-line and have never heard anybody describe this problem. The code is not throwing any exceptions, so I am not sure what the problem could be.
I am stumped and would appreciate any insight into the problem.
WPF doesn't draw the stuff as windows-controls as MFC or WinForms do draw - you can check it using Spy++. That's why its not possible/easy to mix WPF and MFC.

Several parts of UI are not painted

We have a very strange behaviour of a WPF application. Sometimes (not very ofen), some parts of the user interface are simply not painted.
Just recently the save button and a text box on the configuration view didn't show up. Even more strange is that after a relogin, what results in a new view instance, the problem is still present.
Sometimes it helps to hover the mouse over the position where the missing controls usually are to get them visible. But switching the tab page and then back to the original one with the missing controls they are all missing again. Other controls won't show up by hoovering the mouse over them.
Another problem is that dialogs are sometimes screwed up. Parts of the dialog are displaced vertically. But when e.g. a text box inside the dialog gets the focus, it is painted correctly while the rest of the dialog stays displaced.
I don't have the slightest clue what causes this problem. Any idea is welcome.
[Edit 1] So far we have seen this always on Windows XP. Windows 7 seems to be Ok. Also switching to Software-Rendering seems to fix the problem on Windows XP but I'm not sure on this.
The problem was solved by switching the RenderMode to SoftwareOnly. It seems to be a .NET 4 issue when running on Windows XP:
public class MyWindow : Window
{
protected void SetSoftwareRendering()
{
System.Windows.Interop.HwndSource hwndSource = PresentationSource.FromVisual( this ) as System.Windows.Interop.HwndSource;
System.Windows.Interop.HwndTarget hwndTarget = hwndSource.CompositionTarget;
hwndTarget.RenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
}
}
Alternatively one can write
System.Windows.Media.RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
All windows are inherited from MyWindow and can decide wether or not they want the software rendering. Currently we don't use this flexibility and have it enabled on all instances.
If this happens in other WPF applications too it might be your hardware, driver, OS or .NET software.
If not, the only option is to try and reproduce in a minimal case and on several machines.
Are you able to make a minimal version that has the problem en post the code?

How can I restart WPF application?

How can I restart WPF application from code? in Windows Forms there is Application.Restart, where for whatever reason Microsoft decided not to add this method in WPF.
I hate the discompatability between WPF and WindowsForms! like:
window.Visibility = System.Windows.Visibility.Hidden;
What's wrong with that?
window. Visible = false;
Visibility
For controls and panels, there is a huge difference between Visibility.Collapsed and Visiblity.Hidden. Hidden reserves the space of the invisible element, Collapse frees the used space. This can make a big difference in an UI.
Using the same enumeration for the visibility of the window-class is IMO first of all a question of holding a constancy in the class-library, but may be it makes also some other finer differences.
Restart
If there is a possibility to directly restart the app, I don't know. What you can try is to use App.Current.Shutdown() to close the app and start a new instance through System.Diagnostics.Process.Start() where the path to the app can be taken from System.Reflection.Assembly.GetEntryAssembly(). `.

Need to control "Z Order" of windows within WPF Application

I have an application that, due to OpenGL airspace issues, has to host several controls in separate, exclusive windows. This is working quite well, but I am setting all of the windows to TopMost = true, which means that they do stay showing even when they lose focus, but they also overlay other applications. Also, it kind of binds me to using only one window at a time for this. Activate() doesn't work either.
I found that setting the windows' owners to the main app window allowed them to always float on top.
Inside the control that mediates the content and measurement of the child window:
InnerWindow.Owner = Window.GetWindow(this);
this being the windowHostControl hosting this window.
I use to combine Activate() and Focus() methods to show a hidden Window. Can you try using Focus() and let us know if this is working ?

What causes a window to not appear in the taskbar until it's Alt-Tabbed to in Vista?

When our app is started programatically (either through custom action in MSI installer or when starting a new instance) in Windows Vista (also happens in Windows 7 Beta) it won't appear in the taskbar and isn't focused. Alt-tabbing to it will make it appear in the taskbar properly and stay there.
What causes this? I've seen this in some other apps before as well, but not sure why. Out app is .NET WinForms app. Never see this happen in XP, only Vista and 7
Edit: Well, it seems like the only time this happens reproducibly is when it's run by the installer, I believe there's other times it occurs, but I might just be crazy. The launching code is a bit complex to post because we handle various command line launch parameters and it launches a signin form before actually launching the main app etc.
Has anyone had to deal with this scenario before and worked it out?
Try checking your main application form "Form Border" property.
If it's ToolWindow (Fixed or Sizable), try changing it to FixedDialog for example.
This solved the problem in my case.
The usual reason for this is that your main application window doesn't have the window styles that let Windows know it's a main application window (rather than a tool window or a dialog box). So Windows is having to guess based on how the app was started, etc.
Use Spy++ to complare the window styles (especially extended styles) if your window to that of some other window that doesn't have this problem. Are you missing the WS_EX_APPWINDOW style? Are any other styles/extended styles different from other top level windows?
G.So's answer made me find the solution for my problem, wich was caused by the fact that i had my form sizable from launch, but set to borderless in the load void.
If anyone is interested in how i managed to keep the switch to borderless and have it pop up as it should in the taskbar without any dirty hacks.. here it is..
Make a new event from the form on the form's "Shown" event, and put your line of code for switching to borderless in here. Problem solved :)
private void Form1_Shown(object sender, EventArgs e)
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
}
and for the lazy ones ;) >>>>
this.Shown += new EventHandler(Form1_Shown);
Thanks again G.So for clearing up what could cause this in the first place.
I stuggled with this issue as well, and found like a previous commenter said, you cannot have anything in the form's Load() event that changes that FormBorderStyle property. Move anything that changes it to the Shown() event.
Well, one solution is to use a hack like this. That's really not what it's for.
Usually the decision of whether a window will be in the taskbar or not is based on the border styles it uses. The article I linked to provides a bit more detail. The article's comment about the window having an owner or not is quite possible highly relevant to your issue, since the window might somehow be getting a different owner when launched by the installer.
That article is in VB but it's all based around API calls so the info it provides is pretty language independent.
Never see this happen in XP, only Vista and 7
Maybe it's a bug in Vista...?
What happens if you call SetForegroundWindow() (or equivalent in .Net)?
Edit
I did of course mean "BringWindowToTop()".
Or do both.
We had this same problem and fixed it by setting the form property showintaskbar property to true.
Weird that all windows os's dont run apps in the same way!
In our situation, this was tracked down to the form's text property being changed within the Load event.
After putting this inside a BeginInvoke, this odd behaviour no longer happened.
Hope this helps anyone else.
Example
private void Form_Load(object sender, EventArgs e)
{
...
...
...
// this needs to be inside a BeginInvoke otherwise it messes with the taskbar visibility
this.BeginInvoke(new Action(() =>
{
this.Text = "Something new";
}));
...
...
...
}
We encountered the same issue, also in Windows 8. Sometimes the form was receiving correctly the focus, but say just ~30% of the time.
We tried different solutions, but actually the one that worked was the following:
private void OnFormShown(object sender, EventArgs e)
{
// Tell Windows that the Form is a main application window
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
// Even if true, enforce the fact that we will the application on the taskbar
this.ShowInTaskbar = true;
// Put the window to the front and than back
this.BringToFront();
this.TopMost = true;
this.TopMost = false;
// 'Steal' the focus.
this.Activate();
}
Moreover, we ensure also not to set the title of the form during the Load event.

Resources