WPF WebBrowser control flickers in ToolWindow while resizing

Docking/MDI for WPF Forum

Posted 10 years ago by Mariano Spiegelberg
Version: 13.2.0592
Avatar

Hello...again :-)

 

I have this very problem as I mentioned in title.... Actually we have an own user control that hosts this System.Windows.Controls.WebBrowser . And the ToolWindow contains this user control. While resizing we can see the background windows partly temporary. What can we do to avoid this render bug ?

 

Cheers,

Mariano

Comments (9)

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Mariano,

Hmmm... I'm not seeing that.  Can you email our support address with a new simple sample project that shows this issue and include instructions on exactly how to repro it?  Please reference this post and rename the .zip file extension so it doesn't get spam blocked.  Thanks!


Actipro Software Support

Posted 10 years ago by Mariano Spiegelberg
Avatar

Hi...and thanks for your answer.....

Do you use the same WebBrowser Control I do ? One thing is interessting: if I set my window design of my Win7 Ultimate to NonAero respective Windows Classic, the resize flickering disappears...

 

I'll create an example for sending....

[Modified 10 years ago]

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Mariano,

I have a sample here that has both a WinForms WebBrowser and a WPF WebBrowser in separate docking window tabs.  When I resize with ether visible, I don't see any flickering whatsoever and it looks correct.  I originally tried this on Windows 8.1 but just now tried it on Windows 7 with Aero enabled and don't see any problems there either.  I would recommend you try on another machine and also try upgrading your display drivers.  Sometimes flicker kinds of issues in WPF are resolved simply by updating display drivers.

If it still happens after trying all of those things, please send us the simple sample I requested and we can try that scenario.


Actipro Software Support

Posted 10 years ago by Mariano Spiegelberg
Avatar

Thanks for testing.... 

 

Unfortunately the example works in any case.... 

It is very complicated to rebuild the entire app with all Docksites and ToolWindows. The driver update didn't help...

[Modified 10 years ago]

Posted 10 years ago by Markus Henschel - Yager Development
Avatar

Hi,

I found a simple repro case for the flickering:

<Window x:Class="WebbrowserFlicker.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:docking="http://schemas.actiprosoftware.com/winfx/xaml/docking" 
        Title="MainWindow" Height="350" Width="525">

        <docking:DockSite x:Name="dockSite" AutomationProperties.Name="MainDockSite">
            <docking:ToolWindowContainer x:Name="MainContainer" docking:DockSite.ControlSize="200,600">
                <docking:ToolWindow Title="WebBrowser" x:Name="BrowserWindow">
                    <WebBrowser x:Name="Webbrowser" Source="http://www.actiprosoftware.com/community/forums" />
                </docking:ToolWindow>
            </docking:ToolWindowContainer>
        </docking:DockSite>
</Window>

As soon as you bring the WebBrowser ToolWindow to floating state and resize it it flickers like crazy. If it stays docked into the main window no flickering occurs. Any ideas?

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Markus,

I'm trying to repro it with your sample but still don't see any problems... there was no flickering when I resized the floating tool window.  Are you using our latest version?  Which one do you have?  Also, which Windows system are you on?


Actipro Software Support

Posted 10 years ago by Markus Henschel - Yager Development
Avatar

Hi again,

I'm using 2013.2 build 0592 with Windows7 x64 with .NET 4.0 (also tried 4.5) with all service packs and patches installed. We have an off site coworker using windows 8 that doesn't report any flickering. The WebBrowser control uses the IE ActiveX control so may be the Version of Internet Explorer is also important. We tested Versions IE9, IE10 and IE11 all causing the Toolwindow to flicker on resize if floating. I also tested enabling and disabling GPU acceleration in IE with no effect.It also doesn't seem to be hardware specific as it occurs on both ATI/AMD and nVidia hardware.

What's actually quite strange is that the flickering is caused by seeing what's behind the window for a brief moment. I'm used to flickering that is caused by having the window's background color visible but in this case it's anything that is behind the RaftingWindow. If I disable Aero or WPF hardware acceleration the flickering is gone.

I downloaded the sources and looked at the way the RaftingWindow is created. If I remove the line forcing ResizeMode=NoResize from the static ctor the floating windows gets the standard windows borders for resizing and the flickering is gone too. So I would guess it's somehow connected to the way RaftingWindows handle the resizing?! 

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Markus,

Thanks for the reply.  I tested on Windows 7 with Aero and saw the flicker in that scenario.  After debugging further, I found the same thing as you... that it's the NoResize setting causing it.  The problem is that if that is not set, then you get the Aero border around the window, which we don't want when chroming the window.

I did another test where I created a quick Window with similar functionality as what we effectively do with the rafting windows:

var window = new Window();
window.Title = "Regular Window";
window.Owner = this;
window.WindowStyle = System.Windows.WindowStyle.None;
window.ResizeMode = System.Windows.ResizeMode.NoResize;

var grid = new Grid();
			
var wb = new WebBrowser();
wb.Margin = new Thickness(40);
wb.Navigate("http://www.actiprosoftware.com/community/forums");
grid.Children.Add(wb);

var grip = new ResizeGrip();
grid.Children.Add(grip);
grip.MouseDown += (sender2, e2) => { startPoint = this.PointToScreen(e2.GetPosition(this)); grip.CaptureMouse(); };
grip.MouseMove += (sender2, e2) => {
	if (e2.LeftButton == MouseButtonState.Pressed) {
		var newPoint = this.PointToScreen(e2.GetPosition(this));
		var delta = newPoint - startPoint;
		window.Width += delta.X;
		window.Height += delta.Y;
		startPoint = newPoint;
	}
};
grip.MouseUp += (sender2, e2) => { grip.ReleaseMouseCapture(); };

window.Content = grid;
window.Show();

In that test I could see the same issue.  Unfortunately I don't think we can do anything about this particular problem since we don't want the extra resize border to show.

That being said, if you don't care about the extra border, you could override DockSite.CreateRaftingWindow and in the window that is created by the base method call, change the ResizeMode property and return the window back to the caller.  That would likely work around it for your app.


Actipro Software Support

Posted 10 years ago by Markus Henschel - Yager Development
Avatar

Hello,

thanks for information. I don't think that we can live with the extra border. But I found another workaround that seems to be much better than forcing software rendering. I found it here:

http://archive.msdn.microsoft.com/WPFShell

I downloaded the source and added a WebBrowser control to the example project. When using the "Gradient Chrome" style that is similar to the Actipro tool Windows the webbrowser starts to flicker as expected. But when "Glassy Chrome" had been selected at least once the flickering is gone. Because of this I searched the sources for a reason and found this in WindowChromeWorker.cs:333:

// There was a regression in DWM in Windows 7 with regard to handling WM_NCCALCSIZE to effect custom chrome.
// When windows with glass are maximized on a multimonitor setup the glass frame tends to turn black.
// Also when windows are resized they tend to flicker black, sometimes staying that way until resized again.
//
// This appears to be a bug in DWM related to device bitmap optimizations.  At least on RTM Win7 we can
// evoke a legacy code path that bypasses the bug by calling an esoteric DWM function.  This doesn't affect
// the system, just the application.
// WPF also tends to call this function anyways during animations, so we're just forcing the issue
// consistently and a bit earlier.

 What the code basically does is call DwmGetCompositionTimingInfo:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa969514(v=vs.85).aspx

 

So I added a handler for the Loaded event of the ToolWindow that hosts the WebBrowser control that looks like this:

[StructLayout(LayoutKind.Sequential)]
internal struct UNSIGNED_RATIO
{
    public uint uiNumerator;
    public uint uiDenominator;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct DWM_TIMING_INFO
{
    public int cbSize;
    public UNSIGNED_RATIO rateRefresh;
    public ulong qpcRefreshPeriod;
    public UNSIGNED_RATIO rateCompose;
    public ulong qpcVBlank;
    public ulong cRefresh;
    public uint cDXRefresh;
    public ulong qpcCompose;
    public ulong cFrame;
    public uint cDXPresent;
    public ulong cRefreshFrame;
    public ulong cFrameSubmitted;
    public uint cDXPresentSubmitted;
    public ulong cFrameConfirmed;
    public uint cDXPresentConfirmed;
    public ulong cRefreshConfirmed;
    public uint cDXRefreshConfirmed;
    public ulong cFramesLate;
    public uint cFramesOutstanding;
    public ulong cFrameDisplayed;
    public ulong qpcFrameDisplayed;
    public ulong cRefreshFrameDisplayed;
    public ulong cFrameComplete;
    public ulong qpcFrameComplete;
    public ulong cFramePending;
    public ulong qpcFramePending;
    public ulong cFramesDisplayed;
    public ulong cFramesComplete;
    public ulong cFramesPending;
    public ulong cFramesAvailable;
    public ulong cFramesDropped;
    public ulong cFramesMissed;
    public ulong cRefreshNextDisplayed;
    public ulong cRefreshNextPresented;
    public ulong cRefreshesDisplayed;
    public ulong cRefreshesPresented;
    public ulong cRefreshStarted;
    public ulong cPixelsReceived;
    public ulong cPixelsDrawn;
    public ulong cBuffersEmpty;
}

[DllImport("dwmapi.dll", EntryPoint = "DwmGetCompositionTimingInfo")]
private static extern uint DwmGetCompositionTimingInfo(IntPtr hwnd, ref DWM_TIMING_INFO pTimingInfo);

private void BrowserWindow_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
    var obj = sender as DependencyObject;
    if (null!=obj && Environment.OSVersion.Version.Major==6 && Environment.OSVersion.Version.MajorRevision==1)
    {
        Window wnd = Window.GetWindow(obj);
        if (wnd is ActiproSoftware.Windows.Controls.Docking.Primitives.RaftingWindow)
        {
            WindowInteropHelper helper = new WindowInteropHelper(wnd);
            var dti = new DWM_TIMING_INFO { cbSize = Marshal.SizeOf(typeof(DWM_TIMING_INFO)) };
            uint hresult = DwmGetCompositionTimingInfo(helper.Handle, ref dti);
        }
    }
}

 

 This removed the flickering completely for me. May be RaftingWindow could do this internally in some way? Otherwise it might just be helpful to people with the same problem.

 

Regards,

 

Markus

The latest build of this product (v24.1.1) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.