WPF irregular form and WindowsFormsHost control compatibility problem solution

  • 2020-12-09 00:58:59
  • OfStack

This article describes the example of WPF irregular form and WindowsFormsHost control compatibility problem solution. Share to everybody for everybody reference. The specific methods are as follows:

Here is 1, that connected with the irregular forms and WPF WindowsFormsHost control incompatible problems, gives a lot of online solution can't meet all the conditions, there are certain conditions, such as 1 piece of the irregular form compatible with WebBrowser control problems in WPF solution "(interested friends can baidu 1 of this article). The netizen's solution is also unique, why so say, his webBrowser control is put in 1 Form alone, let this Form and WPF in 1 Bord control association, synchronization movement, but when moving will appear flicker, and there will be white spots movement, user experience is certainly not good.

OK, 1 loop, but anyway, why is this problem? What causes the control embedded in WinForm to fail to display after setting transparent form in WPF? At first, I thought it was not loaded properly, and I needed to have UISPY. Through this software, I captured the current running program under 1, and found that the WinForm control embedded in WPF had been loaded, but I just didn't see it. It's depressing.

Miserable program, have a headache ah, is what causes, Internet information, find the http: / / msdn microsoft. com/zh - cn/library/aa970688 aspx, let me understand a lot of knowledge. Since the project will use transparent forms and make rounded forms, I intended to leave the Settings of window unchanged in WPF, that is, WindowStyle= "None" and AllowTransparent = "True" unchanged. I tried to make some Settings on WindowsFormsHost, but found that this was not the way to go. It's a waste of time.

The only way out is to change the train of thought, then put AllowTransparent = "false", then you can show, hehe... Of course, you have to modify the WPF form. How ugly it is! It has a border around it. How do go, how do, this also is 1 problem. Unfortunately, there is no way to use WPF's features.

OK, there is a way, the programmer is to solve, how to do, can only call Windows API, the outermost layer of the border has been removed. So what do we need? We have the train of thought, right? So let's do it. So I'm going to sort out 1 and I'm going to need these functions:

SetWindowLong sets the style of the value window
GetWindowLong gets the style of window
SetWindowRgn sets the workspace of window
CreateRoundRectRgn creates areas with rounded corners
SetLayeredWindowAttributes sets the hierarchy form to set the transparency

Baidu encyclopedia has a detailed explanation of them, but it gives the explanation of C++, so you need to convert the C++ things into C# things, about how to call C# C++ DLL file, Baidu and google have the answer you want, I will fill how much, but pay attention to the type of conversion and characters
The transformation of the set.
Here I put my good function for you to post, for the reader.

public class NativeMethods 
{
    /// <summary>
    /// With an outer border and a title windows The style of the
    /// </summary>
    public const long WS_CAPTION = 0X00C0000L;
 
    // public const long WS_BORDER = 0X0080000L;
 
    /// <summary>
    /// window Extension style Hierarchical display
    /// </summary>
    public const long WS_EX_LAYERED = 0x00080000L;
 
    /// <summary>
    /// with alpha The style of the
    /// </summary>
    public const long LWA_ALPHA = 0x00000002L;
 
    /// <summary>
    /// Color Settings
    /// </summary>
    public const long LWA_COLORKEY = 0x00000001L;
 
    /// <summary>
    /// window Basic style of
    /// </summary>
    public const int GWL_STYLE = -16;
 
    /// <summary>
    /// window Extended style of
    /// </summary>
    public const int GWL_EXSTYLE = -20;
 
    /// <summary>
    /// Sets the style of the form
    /// </summary>
    /// <param name="handle"> Handle to the action form </param>
    /// <param name="oldStyle"> Sets the style type of the form .</param>
    /// <param name="newStyle"> New style </param>
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    public static extern void SetWindowLong(IntPtr handle, int oldStyle, long newStyle);
 
    /// <summary>
    /// Gets the style specified by the form .
    /// </summary>
    /// <param name="handle"> Handle to the action form </param>
    /// <param name="style"> The style to return </param>
    /// <returns> The current window The style of the </returns>
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    public static extern long GetWindowLong(IntPtr handle, int style);
 
    /// <summary>
    /// Sets the work area of the form .
    /// </summary>
    /// <param name="handle"> Handle to the action form .</param>
    /// <param name="handleRegion"> Handle to manipulate the form region .</param>
    /// <param name="regraw">if set to <c>true</c> [regraw].</param>
    /// <returns> The return value </returns>
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    public static extern int SetWindowRgn(IntPtr handle, IntPtr handleRegion, bool regraw);
 
    /// <summary>
    /// Create an area with rounded corners .
    /// </summary>
    /// <param name="x1"> Top-left coordinate X value .</param>
    /// <param name="y1"> Top-left coordinate Y value .</param>
    /// <param name="x2"> Of the lower right hand corner X value .</param>
    /// <param name="y2"> Of the lower right hand corner Y value .</param>
    /// <param name="width"> Oval with rounded corners width.</param>
    /// <param name="height"> Oval with rounded corners height.</param>
    /// <returns>hRgn The handle of </returns>
    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    public static extern IntPtr CreateRoundRectRgn(int x1, int y1, int x2, int y2, int width, int height);
 
    /// <summary>
    /// Sets the layered window attributes.
    /// </summary>
    /// <param name="handle"> Handle to the window to operate on </param>
    /// <param name="colorKey">RGB The value of the </param>
    /// <param name="alpha">Alpha The value of transparency </param>
    /// <param name="flags"> With parameters </param>
    /// <returns>true or false</returns>
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    public static extern bool SetLayeredWindowAttributes(IntPtr handle, ulong colorKey, byte alpha, long flags);
}

The following question is how to do this. First, add an Load event to the WPF form in which the WinForm control is embedded. Add the following code to the event:
//  Gets the form handle  
 IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
 
 // Get form's style
 long oldstyle = NativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_STYLE);
 
 // Change the style of the form to a bezel-less form
 NativeMethods.SetWindowLong(hwnd, NativeMethods.GWL_STYLE, oldstyle & ~NativeMethods.WS_CAPTION);
 
 // SetWindowLong(hwnd, GWL_EXSTYLE, oldstyle & ~WS_EX_LAYERED);
 // 1 | 2 << 8 | 3 << 16  r=1,g=2,b=3 As shown in the winuse.h file
 // Set the form to be transparent
 NativeMethods.SetLayeredWindowAttributes(hwnd, 1 | 2 << 8 | 3 << 16, 0, NativeMethods.LWA_ALPHA);
 
 // Create a rounded form   12 This value can be set according to its own project
 NativeMethods.SetWindowRgn(hwnd, NativeMethods.CreateRoundRectRgn(0, 0, Convert.ToInt32(this.ActualWidth), Convert.ToInt32(this.ActualHeight), 12, 12), true);


In addition, it is necessary to redraw the rounded corner form after the size of the form changes, otherwise the display effect is not ideal. Add the following event code to solve the problem of redrawing the rounded corner area of the form when the size of the form changes:
/// <summary> 
/// Handles the SizeChanged event of the DesktopShell control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.SizeChangedEventArgs"/> instance containing the event data.</param>
private void DesktopShell_SizeChanged(object sender, SizeChangedEventArgs e)
{
    // Gets the form handle
    IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
 
    // Create a rounded form
    NativeMethods.SetWindowRgn(hwnd,NativeMethods.CreateRoundRectRgn(0, 0, Convert.ToInt32(this.ActualWidth), Convert.ToInt32(this.ActualHeight), 12, 12), true);
}

That's all there is to solve the problem, and hopefully this article will help you with your WPF programming.


Related articles: