SoFunction
Updated on 2025-03-07

Solution to the compatibility problem of irregular forms and WindowsFormsHost control in WPF

This article describes the solution to the compatibility problem of irregular forms and WindowsFormsHost controls in WPF. Share it for your reference. The specific methods are as follows:

Let me first explain here that regarding the incompatibility of irregular forms in WPF and WindowsFormsHost controls, many solutions given on the Internet cannot meet all situations and have specific conditions. For example, there is an article "Solutions for compatibility problems between irregular forms in WPF and WebBrowser controls" (interested friends can take this article on Baidu). The netizen's solution is also unique. Why do you say that? His webBrowser control is placed separately in a Form, so that the Form is associated with a Bord control in WPF and moves synchronously, but it will flash when moving, and there will also be white spots in motion, which will definitely be bad for the user experience.

OK, after a long circle, let's get back to the point. Why does this problem occur? What causes the controls embedded in WinForm to not be displayed after setting a transparent form in WPF. At first I thought it was not loading normally, and I also wanted to have UISPY. Through this software, I captured the currently running program and found that the WinForm control I embedded in WPF has been loaded, but I just didn't see it. Very depressed.

The sad program, a headache, what causes it? I searched the information online and found /zh-cn/library/, which gave me a lot of knowledge. Since the project uses transparent forms and also creates a rounded form, it is said that it was originally intended to not change the settings for windows in WPF, that is, not to change the settings such as WindowStyle="None" and AllowTransparent="True". I wanted to make some settings on WindowsFormsHost, but I found that this path was not working. A lot of time wasted.

This road is not open, so you can change your thinking. Then, turn AllowTransparent = "false" and then display it. Haha... Of course, you need to modify it. The WPF form is so ugly, and there is a border on the outside. How to do it and how to do it, this is also a problem. I want to use the features of WPF, but it’s a tragedy. It seems that there is no relevant method.

OK, there are still ways, programmers are here to solve the problem. What should I do? I can only call the Windows API and remove the outermost border. So what do you need? I have the idea, right? Then let’s take action. I went to Google and Baidu and found that there are really many examples. The examples of C++ are the most comprehensive. You can refer to them. Then I sorted out these functions needed:

SetWindowLong   Set the style of the value window
GetWindowLong   Get window style
SetWindowRgn     Set the window's workspace
CreateRoundRectRgn Create an area with rounded corners
SetLayeredWindowAttributes Set hierarchical form and set transparency

Directly Baidu, the encyclopedia has a detailed explanation of them, but it is given a C++ explanation. Then you need to convert C++ things into C# things. Regarding how C# calls C++ DLL files, there are the answers you want in Baidu and Google, so I will make up for them, but pay attention to the conversion of types and characters.
set conversion.
Below I will post the functions I converted to for your benefit.

Copy the codeThe code is as follows:
public class NativeMethods
{
    /// <summary>
/// Style for windows with outer border and title
    /// </summary>
    public const long WS_CAPTION = 0X00C0000L;
 
    // public const long WS_BORDER = 0X0080000L;
 
    /// <summary>
/// window extension style layered display
    /// </summary>
    public const long WS_EX_LAYERED = 0x00080000L;
 
    /// <summary>
/// Style with alpha
    /// </summary>
    public const long LWA_ALPHA = 0x00000002L;
 
    /// <summary>
/// Color settings
    /// </summary>
    public const long LWA_COLORKEY = 0x00000001L;
 
    /// <summary>
/// Basic style of window
    /// </summary>
    public const int GWL_STYLE = -16;
 
    /// <summary>
/// window's extended style
    /// </summary>
    public const int GWL_EXSTYLE = -20;
 
    /// <summary>
/// Set the style of the form
    /// </summary>
/// <param name="handle">Operate the handle of the form</param>
/// <param name="oldStyle">Set the style type of the form.</param>
/// <param name="newStyle">New Style</param>
    [("")]
    public static extern void SetWindowLong(IntPtr handle, int oldStyle, long newStyle);
 
    /// <summary>
/// Get the style specified by the form.
    /// </summary>
/// <param name="handle">Operate the handle of the form</param>
/// <param name="style">Style to return</param>
/// <returns>The current window style</returns>
    [("")]
    public static extern long GetWindowLong(IntPtr handle, int style);
 
    /// <summary>
/// Set the work area of ​​the form.
    /// </summary>
/// <param name="handle">Operate the handle of the form.</param>
/// <param name="handleRegion">Address to the operation form area.</param>
    /// <param name="regraw">if set to <c>true</c> [regraw].</param>
/// <returns>Return value</returns>
    [("")]
    public static extern int SetWindowRgn(IntPtr handle, IntPtr handleRegion, bool regraw);
 
    /// <summary>
/// Create an area with rounded corners.
    /// </summary>
/// <param name="x1">X value of the upper left corner coordinate.</param>
/// <param name="y1">Y value of the upper left corner coordinate.</param>
/// <param name="x2">X value of the lower right corner coordinate.</param>
/// <param name="y2">Y value of the lower right corner coordinate.</param>
/// <param name="width">width of rounded ellipse.</param>
/// <param name="height">height of rounded ellipse.</param>
/// <returns>hRgn's handle</returns>
    [("")]
    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">Window handle to perform the operation</param>
/// <param name="colorKey">RGB value</param>
/// <param name="alpha">Alpha value, transparency</param>
/// <param name="flags">Accompany parameters</param>
    /// <returns>true or false</returns>
    [("")]
    public static extern bool SetLayeredWindowAttributes(IntPtr handle, ulong colorKey, byte alpha, long flags);
}

The following question is how to operate. First, add a Load event to the WPF form that embeds the WinForm control, and add the following code to the event:
Copy the codeThe code is as follows:
// Get the form handle
 IntPtr hwnd = new (this).Handle;
 
// Get the form's style
 long oldstyle = (hwnd, NativeMethods.GWL_STYLE);
 
// Change the style of the form to a borderless form
 (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 See the file for details
// Set the form to a transparent form
 (hwnd, 1 | 2 << 8 | 3 << 16, 0, NativeMethods.LWA_ALPHA);
 
// Create a rounded corner form 12 This value can be set according to your own project
 (hwnd, (0, 0, Convert.ToInt32(), Convert.ToInt32(), 12, 12), true);

 
Also, after the form size changes, you must re-draw the rounded corners of the form, otherwise there will be a very unsatisfactory display effect. Add the following event code to solve the problem that when the form size changes, re-draw the rounded corners of the form:
Copy the codeThe code is as follows:
/// <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=""/> instance containing the event data.</param>
private void DesktopShell_SizeChanged(object sender, SizeChangedEventArgs e)
{
// Get the form handle
    IntPtr hwnd = new (this).Handle;
 
// Create a rounded form
    (hwnd,(0, 0, Convert.ToInt32(), Convert.ToInt32(), 12, 12), true);
}

All the problems have been solved so far. I hope that the description in this article will be helpful to everyone's WPF programming.