In my winforms application I am trying to get a main window handle, so I can set it as parent to my wpf modal window. I am not too experienced with winforms, so after a bit of googling I found two ways to get it.
System.Windows.Forms.Application.OpenForms[0].Handle
System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle
(1) seems to always return the same value which appears to be correct (at least my modal window behaves as expected), while (2) sometimes returns the same value as (1), but sometimes - an entirely different pointer, which does not seem to work (my modal window appears on top of every other window, not just the parent window).
Can someone explain the difference between the two methods? Is it normal that sometimes they return different results?
Edit:
In case anyone else is wondering: once you get the handle, you can use it by creating WindowInteropHelper
class:
public static void SetInteropParent(this Window wpfDialogWindow, IntPtr winformsParentHandle)
{
new WindowInteropHelper(wpdDialogWindow) { Owner = winformsParentHandle };
}
The latest version of Windows Forms is for . NET 6 using Visual Studio 2022 version 17.0. The . NET Framework 4 implementation that's supported by Visual Studio 2022, Visual Studio 2019, and Visual Studio 2017.
Back-end refers to stuff going on behind the scenes, i.e. not directly visible by the user, and front-end refers to the opposite - the stuff that's directly visible. Hence, WinForms is clearly a front-end thing.
Windows Forms controls are reusable components that encapsulate user interface functionality and are used in client-side, Windows-based applications. Not only does Windows Forms provide many ready-to-use controls, it also provides the infrastructure for developing your own controls.
It is certainly not unusual for Process.MainWindowHandle to return the wrong handle. The Process class has to make a guess at which window is the "main" one. There is no mechanism in the native winapi to designate a window as such. So Process makes a guess that the first window is the main one. This has a knack for going wrong in apps that use a splash screen or a login dialog, etc, or create a window on another thread.
Application.OpenForms doesn't have this problem, but has a failure mode, it will lose track of a window when it is recreated. Which happens when the program changes certain properties of the Form that can only be specified when the window is created. The ShowInTaskbar, TransparencyKey and Opacity properties are the most common troublemakers.
The most reliable way is to override the OnHandleCreated() method of the form you want to be the parent. Which is called whenever the Handle property changes. Do note that you want to make sure that this doesn't happen while your WPF window is active, that will kill the WPF window as well. Otherwise easy to observe of course :)
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
SetWpfInteropParentHandle(this.Handle);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With