-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebView2 control is not visible after changing the parent window #985
Comments
Thanks for submitting this issue! I've added it to our backlog and the team will investigate this. |
We specifically did work to enable reparenting of the Winforms control, so I think this may be a bug or regression. @DominikPalo Which HWND specifically are you changing the parent to be the slideshow window? Are you able to try changing the |
The main issue was that I was calling the Update: I've just discovered that if I didn't open a PowerPoint task pane with another WebView2 control instance before opening the window which should be hosted under the SlideShow window, everything works fine (I'm able to change the parent window). Unfortunately, we need to use WebView2 in both places - in the task pane and also as a separate window hosted under the SlideShow window. To summarize:Scenario A:
Scenario B:
|
@DominikPalo New APIs in Windows 10 1607 and above allow creating windows with different DPI awarenesses than the process creating it. I wonder if that's what's happening here. I'm not quite sure how you are getting the HWNDs to parent to so can you please check the DPI awareness of the HWND you are parenting to in both scenarios using the following API? https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdpiawarenesscontext |
Thank you, because it is not possible to use the /// <summary>
/// Class name of the window with slide show content in PowerPoint 2010 and newer.
/// </summary>
public const string PowerPoint_SlideShowScreenName = "screenClass";
private void OnSlideShowBeginEvent(SlideShowWindow window)
{
// We can't use window.HWND, it fails with:
// System.Runtime.InteropServices.COMException HResult=-2147352573 Message=Member not found. (Exception from HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND)) ErrorCode=-2147352573
// See: https://github.com/NetOfficeFw/NetOffice/issues/103 and https://github.com/NetOfficeFw/NetOffice/issues/140
// WORKAROUND (using https://www.pinvoke.net/default.aspx/user32.FindWindowEx)
var slideShowWindowHwnd = NativeMethods.FindWindowEx(IntPtr.Zero, IntPtr.Zero, PowerPoint_SlideShowScreenName, null);
var slideShowWindowDpiAwarenessContext = NativeMethods.GetWindowDpiAwarenessContext(slideShowWindowHwnd);
var slideShowWindowDpiAwareness = Utils.GetAwarenessFromDpiAwarenessContext(slideShowWindowDpiAwarenessContext);
var threadDpiAwarenessContext = this.NativeMethods.GetThreadDpiAwarenessContext();
var threadDpiAwareness = Utils.GetAwarenessFromDpiAwarenessContext(threadDpiAwarenessContext);
var slideShowChildWindowWithWebView2 = new SlideShowChildWindowWithWebView2(slideShowWindowHwnd);
} in both scenarios, the resulting awareness modes ( But, the window which I want to set as a child window of the slideshow window (and which is hosting the WebView2 control) has DPI mode set to SlideShowChildWindowWithWebView2: public partial class SlideShowChildWindowWithWebView2 : Form
{
private IntPtr SlideShowWindowHwnd { get; set; }
public SlideShowChildWindowWithWebView2(IntPtr slideShowWindowHwnd)
{
this.SlideShowWindowHwnd = slideShowWindowHwnd;
InitializeComponent();
this.InitializeAsync();
}
private async void InitializeAsync()
{
var webView2Environment = await WebView2Configuration.CreateEnvironmentAsync();
await this.webView2.EnsureCoreWebView2Async(webView2Environment);
}
private void webView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
NativeMethods.SetParent(this.Handle, this.SlideShowWindowHwnd); // this method fails in Scenario A
}
} I checked also the So, I'm not sure why the DPI awareness modes of my WebView2 subprocesses differs in scenario A vs. B. I also tried to enforce the DPI awareness mode by setting/overriding the public static async Task<CoreWebView2Environment> CreateEnvironmentAsync()
{
var options = new CoreWebView2EnvironmentOptions($"--embedded-browser-webview-dpi-awareness=1");
return await CoreWebView2Environment.CreateAsync(null, UserDataFolder, options);
} but it didn't help - Maybe there is a way how to make WebView2 subprocesses isolated? So the WebView2 control in the task pane would have its own WebView2 subprocess and also the WebView2 control in the SlideShow child window will have a different WebView2 subprocess - this would probably help to solve the issue. |
I've just found that issue is caused by calling the My snippet (part of SlideShowChildWindowWithWebView2.cs): private async void InitializeAsync()
{
var dpiContextBefore = NativeMethods().GetWindowDpiAwarenessContext(this.Handle);
var dpiModeBefore = Utils.GetAwarenessFromDpiAwarenessContext(dpiContextBefore);
var webView2Environment = await WebView2Configuration.CreateEnvironmentAsync();
await this.webView2.EnsureCoreWebView2Async(webView2Environment);
var dpiContextAfter = NativeMethods().GetWindowDpiAwarenessContext(this.Handle);
var dpiModeAfter = Utils.GetAwarenessFromDpiAwarenessContext(dpiContextAfter);
} Results:
|
In reference to your last code segment, I'm not sure how the dpi awareness is different for an HWND after EnsureCoreWebView2Async. Windows doesn't allow changing the DPI awareness of a window after it's been created. Can you check if this.Handle refers to the same window handle in both cases? In the case of a SetParent call, a forced reset of an entire process' DPI awareness can occur (refer to https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent) but an HWND cannot change DPI awareness after creation. As to creating isolated WebView2 processes, the only way to do that is to create a separate environment with a different user data folder. Of course, this also means things like cookies and history aren't shared between your two WebView2 controls. But this would allow you to create two WebViews with different DPI Awareness levels. |
@jamesoli thank you - to get more details, I updated the previous snippet to write results to the console (I got the previous results by using a breakpoint at line private async void InitializeAsync()
{
var dpiContextBefore = NativeMethods().GetWindowDpiAwarenessContext(this.Handle);
var dpiModeBefore = Utils.GetAwarenessFromDpiAwarenessContext(dpiContextBefore);
Debug.WriteLine($"Window handle before calling EnsureCoreWebView2Async: {this.Handle}");
Debug.WriteLine($"DPI awareness mode before calling EnsureCoreWebView2Async: {dpiBefore}");
var webView2Environment = await WebView2Configuration.CreateEnvironmentAsync();
await this.webView2.EnsureCoreWebView2Async(webView2Environment);
var dpiContextAfter = NativeMethods().GetWindowDpiAwarenessContext(this.Handle);
var dpiModeAfter = Utils.GetAwarenessFromDpiAwarenessContext(dpiContextAfter);
Debug.WriteLine($"Window handle after calling EnsureCoreWebView2Async: {this.Handle}");
Debug.WriteLine($"DPI awareness mode after calling EnsureCoreWebView2Async: {dpiAfter}");
} Now (without using breakpoints) the results are more interesting: Scenario A
BUT: calling the The weird thing is that when I don't try to access
Scenario B (OK)
|
What it looks like is happening is that in scenario A, since there are two WebViews created by threads with different DPI awarenesses, it will fail the same way SetParent does. That is because we do a cross process SetParent internally which is why when the second WebView is being spun up and we detect that the DPI awareness is different, we send back an error. The reason that you don't see the issue if you don't reference this.Handle before calling EnsureCoreWebView2Async could be because an HWND is not created until this.Handle is referenced for the first time. And because no window is created, the DPI awareness is not set. We are working on removing that cross process SetParent dependency which would allow you to create two WebViews with the same user data folder from threads with different DPI Awarenesses. But this will come some time in the future. |
We can use this issue to track the planned work we have for parenting and will update this thread. |
Thank you, but I would like to mention that even if I use the suggested workaround (use different UserData folders for my WebView2 controls) the issue still persists - I'm not able to change the parent window in scenario A and calling the "SetParent" method fails with Regarding the threads - I've checked both threads by calling the |
@DominikPalo I'm afraid the SetParent limitation is one from Windows itself. You can't call SetParent with windows of differing DPI awarenesses. |
Yes, that is true - and I'm aware of it. But the question/problem is why calling If I didn't initialize WebView2 in my task pane (commenting out EnsureCoreWebView2Async is enough) or use a different web view control (CefSharp), I'm able to create new WinForm windows with I'm calling |
Hi @jamesoli, what options do we have here to make sure the WebView2 runtime will use the same DPI level as the PowerPoint process? This works well in CefSharp Chromium library and we can set our form with Chromium browser control as child of the PowerPoint's slide show window. |
Description
We are migrating our PowerPoint integration from CefSharp (a different Chromium-based webview control) to WebView2 and we have bumped into an issue when trying to change the parent window of a window with WebView2 control inside.
The way how our integration works is that we create a new WinForms window containing a WebView2 control and then during a slideshow, we occasionally cover the slideshow window with our WebView2 window (to "replace" the content of the presented slide). But, before we display that window, we need to change the parent window of our WebView2 window to the PowerPoint slideshow window (by calling the function SetParent with HWND of the PowerPoint Slideshow window) - so apps like Zoom or MS Teams stream also our WebView2 content while streaming just the PowerPoint slideshow window.
Unfortunately, it looks that the WebView2 WinForms control (unlike the CefSharp WinForms control) is not compatible with that solution: after changing the parent window, we can see just the empty WinForms window - the WebView2 control is not visible (although the embedded web is loaded).
Version
SDK: 1.0.790-prerelease
Runtime: 88.0.705.74 (Evergreen Bootstrapper)
Framework: WinForms
OS: Win10
Repro Steps
SetParent
function fromWinuser.h
to another (already visible) windowAdditional context
The entire integration is built as a COM add-in (so it is running from the PowerPoint process).
AB#26124929
The text was updated successfully, but these errors were encountered: