mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 18:26:39 +02:00
[FileExplorerPreview] Move everything from WebBrowser to WebView2 (#17588)
* Move MarkdownPreviewHandler from WebBrowser to WebView2 * Disable context menu Open links in default browser * Update expect.txt * Move SvgPreviewHandler from WebBrowser to WebView2 * Migrate SvgThumbnailProvider from WebBrowser to WebView2 * Migrate CustomControlTest to WebView2 Remove WebBrowser related stuff * Update tests * Revert GetThumbnail return value Disable javascript dialogs in WebView2 for Svg thumbnail and preview * expect.txt * Increase timeout for Markdown tests * Add sleeps * Add zero check
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}</ProjectGuid>
|
||||
<RootNamespace>Microsoft.PowerToys.PreviewHandler.Markdown</RootNamespace>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<TargetFramework>net6.0-windows10.0.18362.0</TargetFramework>
|
||||
<EnableComHosting>true</EnableComHosting>
|
||||
<IntermediateOutputPath>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(AssemblyName)\</IntermediateOutputPath>
|
||||
<AssemblyName>PowerToys.MarkdownPreviewHandler</AssemblyName>
|
||||
@@ -45,6 +45,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1150.38" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO.Abstractions;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using Common;
|
||||
@@ -12,7 +14,10 @@ using Markdig;
|
||||
using Microsoft.PowerToys.PreviewHandler.Markdown.Properties;
|
||||
using Microsoft.PowerToys.PreviewHandler.Markdown.Telemetry.Events;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Microsoft.Web.WebView2.WinForms;
|
||||
using PreviewHandlerCommon;
|
||||
using Windows.System;
|
||||
|
||||
namespace Microsoft.PowerToys.PreviewHandler.Markdown
|
||||
{
|
||||
@@ -53,13 +58,40 @@ namespace Microsoft.PowerToys.PreviewHandler.Markdown
|
||||
/// <summary>
|
||||
/// Extended Browser Control to display markdown html.
|
||||
/// </summary>
|
||||
private WebBrowserExt _browser;
|
||||
private WebView2 _browser;
|
||||
|
||||
/// <summary>
|
||||
/// WebView2 Environment
|
||||
/// </summary>
|
||||
private CoreWebView2Environment _webView2Environment;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the virtual host
|
||||
/// </summary>
|
||||
public const string VirtualHostName = "PowerToysLocalMarkdown";
|
||||
|
||||
/// <summary>
|
||||
/// True if external image is blocked, false otherwise.
|
||||
/// </summary>
|
||||
private bool _infoBarDisplayed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the current assembly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Source: https://stackoverflow.com/a/283917/14774889
|
||||
/// </remarks>
|
||||
public static string AssemblyDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().Location;
|
||||
UriBuilder uri = new UriBuilder(codeBase);
|
||||
string path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MarkdownPreviewHandlerControl"/> class.
|
||||
/// </summary>
|
||||
@@ -103,25 +135,52 @@ namespace Microsoft.PowerToys.PreviewHandler.Markdown
|
||||
string parsedMarkdown = Markdig.Markdown.ToHtml(fileText, pipeline);
|
||||
string markdownHTML = $"{htmlHeader}{parsedMarkdown}{htmlFooter}";
|
||||
|
||||
_browser = new WebView2()
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
};
|
||||
|
||||
_browser.NavigationStarting += async (object sender, CoreWebView2NavigationStartingEventArgs args) =>
|
||||
{
|
||||
if (args.Uri != null && args.IsUserInitiated)
|
||||
{
|
||||
args.Cancel = true;
|
||||
await Launcher.LaunchUriAsync(new Uri(args.Uri));
|
||||
}
|
||||
};
|
||||
|
||||
InvokeOnControlThread(() =>
|
||||
{
|
||||
_browser = new WebBrowserExt
|
||||
ConfiguredTaskAwaitable<CoreWebView2Environment>.ConfiguredTaskAwaiter
|
||||
webView2EnvironmentAwaiter = CoreWebView2Environment
|
||||
.CreateAsync(userDataFolder: System.Environment.GetEnvironmentVariable("USERPROFILE") +
|
||||
"\\AppData\\LocalLow\\Microsoft\\PowerToys\\MarkdownPreview-Temp")
|
||||
.ConfigureAwait(true).GetAwaiter();
|
||||
webView2EnvironmentAwaiter.OnCompleted(() =>
|
||||
{
|
||||
DocumentText = markdownHTML,
|
||||
Dock = DockStyle.Fill,
|
||||
IsWebBrowserContextMenuEnabled = false,
|
||||
ScriptErrorsSuppressed = true,
|
||||
ScrollBarsEnabled = true,
|
||||
AllowNavigation = false,
|
||||
};
|
||||
Controls.Add(_browser);
|
||||
InvokeOnControlThread(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_webView2Environment = webView2EnvironmentAwaiter.GetResult();
|
||||
await _browser.EnsureCoreWebView2Async(_webView2Environment).ConfigureAwait(true);
|
||||
await _browser.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.addEventListener('contextmenu', window => {window.preventDefault();});");
|
||||
_browser.CoreWebView2.SetVirtualHostNameToFolderMapping(VirtualHostName, AssemblyDirectory, CoreWebView2HostResourceAccessKind.Allow);
|
||||
_browser.NavigateToString(markdownHTML);
|
||||
Controls.Add(_browser);
|
||||
|
||||
if (_infoBarDisplayed)
|
||||
{
|
||||
_infoBar = GetTextBoxControl(Resources.BlockedImageInfoText);
|
||||
Resize += FormResized;
|
||||
Controls.Add(_infoBar);
|
||||
}
|
||||
if (_infoBarDisplayed)
|
||||
{
|
||||
_infoBar = GetTextBoxControl(Resources.BlockedImageInfoText);
|
||||
Resize += FormResized;
|
||||
Controls.Add(_infoBar);
|
||||
}
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new MarkdownFilePreviewed());
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1108.44" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1150.38" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Windows.Forms;
|
||||
using Common;
|
||||
@@ -12,6 +14,8 @@ using Common.Utilities;
|
||||
using Microsoft.PowerToys.PreviewHandler.Svg.Telemetry.Events;
|
||||
using Microsoft.PowerToys.PreviewHandler.Svg.Utilities;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Microsoft.Web.WebView2.WinForms;
|
||||
using PreviewHandlerCommon;
|
||||
|
||||
namespace Microsoft.PowerToys.PreviewHandler.Svg
|
||||
@@ -22,9 +26,36 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg
|
||||
public class SvgPreviewControl : FormHandlerControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Extended Browser Control to display Svg.
|
||||
/// WebView2 Control to display Svg.
|
||||
/// </summary>
|
||||
private WebBrowserExt _browser;
|
||||
private WebView2 _browser;
|
||||
|
||||
/// <summary>
|
||||
/// WebView2 Environment
|
||||
/// </summary>
|
||||
private CoreWebView2Environment _webView2Environment;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the virtual host
|
||||
/// </summary>
|
||||
public const string VirtualHostName = "PowerToysLocalSvg";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the current assembly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Source: https://stackoverflow.com/a/283917/14774889
|
||||
/// </remarks>
|
||||
public static string AssemblyDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().Location;
|
||||
UriBuilder uri = new UriBuilder(codeBase);
|
||||
string path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Text box to display the information about blocked elements from Svg.
|
||||
@@ -73,7 +104,6 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg
|
||||
catch (Exception ex)
|
||||
#pragma warning restore CA1031 // Do not catch general exception types
|
||||
{
|
||||
_browser.ScrollBarsEnabled = true;
|
||||
PowerToysTelemetry.Log.WriteEvent(new SvgFilePreviewError { Message = ex.Message });
|
||||
}
|
||||
|
||||
@@ -90,7 +120,7 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg
|
||||
AddTextBoxControl(Properties.Resource.BlockedElementInfoText);
|
||||
}
|
||||
|
||||
AddBrowserControl(svgData);
|
||||
AddWebViewControl(svgData);
|
||||
Resize += FormResized;
|
||||
base.DoPreview(dataSource);
|
||||
PowerToysTelemetry.Log.WriteEvent(new SvgFilePreviewed());
|
||||
@@ -129,19 +159,38 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Web Browser Control to Control Collection.
|
||||
/// Adds a WebView2 Control to Control Collection.
|
||||
/// </summary>
|
||||
/// <param name="svgData">Svg to display on Browser Control.</param>
|
||||
private void AddBrowserControl(string svgData)
|
||||
private void AddWebViewControl(string svgData)
|
||||
{
|
||||
_browser = new WebBrowserExt();
|
||||
_browser.DocumentText = svgData;
|
||||
_browser = new WebView2();
|
||||
_browser.Dock = DockStyle.Fill;
|
||||
_browser.IsWebBrowserContextMenuEnabled = false;
|
||||
_browser.ScriptErrorsSuppressed = true;
|
||||
_browser.ScrollBarsEnabled = false;
|
||||
_browser.AllowNavigation = false;
|
||||
Controls.Add(_browser);
|
||||
|
||||
ConfiguredTaskAwaitable<CoreWebView2Environment>.ConfiguredTaskAwaiter
|
||||
webView2EnvironmentAwaiter = CoreWebView2Environment
|
||||
.CreateAsync(userDataFolder: System.Environment.GetEnvironmentVariable("USERPROFILE") +
|
||||
"\\AppData\\LocalLow\\Microsoft\\PowerToys\\SvgPreview-Temp")
|
||||
.ConfigureAwait(true).GetAwaiter();
|
||||
webView2EnvironmentAwaiter.OnCompleted(() =>
|
||||
{
|
||||
InvokeOnControlThread(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_webView2Environment = webView2EnvironmentAwaiter.GetResult();
|
||||
await _browser.EnsureCoreWebView2Async(_webView2Environment).ConfigureAwait(true);
|
||||
await _browser.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.addEventListener('contextmenu', window => {window.preventDefault();});");
|
||||
_browser.CoreWebView2.SetVirtualHostNameToFolderMapping(VirtualHostName, AssemblyDirectory, CoreWebView2HostResourceAccessKind.Allow);
|
||||
_browser.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
|
||||
_browser.NavigateToString(svgData);
|
||||
Controls.Add(_browser);
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1150.38" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg.Utilities
|
||||
|
||||
string centering = "position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);";
|
||||
|
||||
// Because WebBrowser class is based on IE version that do not support max-width and max-height extra CSS is needed for it to work.
|
||||
// max-width and max-height not supported. Extra CSS is needed for it to work.
|
||||
string scaling = $"max-width: {width} ; max-height: {height} ;";
|
||||
scaling += $" _height:expression(this.scrollHeight > {heightR} ? \" {height}\" : \"auto\"); _width:expression(this.scrollWidth > {widthR} ? \"{width}\" : \"auto\");";
|
||||
|
||||
|
||||
@@ -6,13 +6,15 @@ using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Windows.Forms;
|
||||
using Common.ComInterlop;
|
||||
using Common.Utilities;
|
||||
using PreviewHandlerCommon;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Microsoft.Web.WebView2.WinForms;
|
||||
|
||||
namespace Microsoft.PowerToys.ThumbnailHandler.Svg
|
||||
{
|
||||
@@ -22,7 +24,7 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Svg
|
||||
[Guid("36B27788-A8BB-4698-A756-DF9F11F64F84")]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ComVisible(true)]
|
||||
public class SvgThumbnailProvider : IInitializeWithStream, IThumbnailProvider
|
||||
public class SvgThumbnailProvider : IInitializeWithStream, IThumbnailProvider, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the stream object to access file.
|
||||
@@ -35,135 +37,116 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Svg
|
||||
private const uint MaxThumbnailSize = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// Captures an image representation of browser contents.
|
||||
/// WebView2 Control to display Svg.
|
||||
/// </summary>
|
||||
/// <param name="browser">The WebBrowser instance rendering the SVG.</param>
|
||||
/// <param name="rectangle">The client rectangle to capture from.</param>
|
||||
/// <param name="backgroundColor">The default background color to apply.</param>
|
||||
/// <returns>A Bitmap representing the browser contents.</returns>
|
||||
public static Bitmap GetBrowserContentImage(WebBrowser browser, Rectangle rectangle, Color backgroundColor)
|
||||
private WebView2 _browser;
|
||||
|
||||
/// <summary>
|
||||
/// WebView2 Environment
|
||||
/// </summary>
|
||||
private CoreWebView2Environment _webView2Environment;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the virtual host
|
||||
/// </summary>
|
||||
public const string VirtualHostName = "PowerToysLocalSvgThumbnail";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the current assembly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Source: https://stackoverflow.com/a/283917/14774889
|
||||
/// </remarks>
|
||||
public static string AssemblyDirectory
|
||||
{
|
||||
Bitmap image = new Bitmap(rectangle.Width, rectangle.Height);
|
||||
using (Graphics graphics = Graphics.FromImage(image))
|
||||
get
|
||||
{
|
||||
IntPtr deviceContextHandle = IntPtr.Zero;
|
||||
RECT rect = new RECT
|
||||
{
|
||||
Left = rectangle.Left,
|
||||
Top = rectangle.Top,
|
||||
Right = rectangle.Right,
|
||||
Bottom = rectangle.Bottom,
|
||||
};
|
||||
|
||||
graphics.Clear(backgroundColor);
|
||||
|
||||
try
|
||||
{
|
||||
deviceContextHandle = graphics.GetHdc();
|
||||
|
||||
IViewObject viewObject = browser?.ActiveXInstance as IViewObject;
|
||||
viewObject.Draw(1, -1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, deviceContextHandle, ref rect, IntPtr.Zero, IntPtr.Zero, 0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (deviceContextHandle != IntPtr.Zero)
|
||||
{
|
||||
graphics.ReleaseHdc(deviceContextHandle);
|
||||
}
|
||||
}
|
||||
string codeBase = Assembly.GetExecutingAssembly().Location;
|
||||
UriBuilder uri = new UriBuilder(codeBase);
|
||||
string path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap the SVG markup in HTML with a meta tag to ensure the
|
||||
/// WebBrowser control is in Edge mode to enable SVG rendering.
|
||||
/// We also set the padding and margin for the body to zero as
|
||||
/// there is a default margin of 8.
|
||||
/// Render SVG using WebView2 control, capture the WebView2
|
||||
/// preview and create Bitmap out of it.
|
||||
/// </summary>
|
||||
/// <param name="content">The content to render.</param>
|
||||
/// <param name="cx">The maximum thumbnail size, in pixels.</param>
|
||||
/// <returns>A thumbnail of the rendered content.</returns>
|
||||
public static Bitmap GetThumbnail(string content, uint cx)
|
||||
public Bitmap GetThumbnail(string content, uint cx)
|
||||
{
|
||||
if (cx > MaxThumbnailSize)
|
||||
if (cx == 0 || cx > MaxThumbnailSize || string.IsNullOrEmpty(content) || !content.Contains("svg"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Bitmap thumbnail = null;
|
||||
|
||||
// Wrap the SVG content in HTML in IE Edge mode so we can ensure
|
||||
// we render properly.
|
||||
bool thumbnailDone = false;
|
||||
string wrappedContent = WrapSVGInHTML(content);
|
||||
using (WebBrowserExt browser = new WebBrowserExt())
|
||||
|
||||
_browser = new WebView2();
|
||||
_browser.Dock = DockStyle.Fill;
|
||||
_browser.Visible = true;
|
||||
_browser.Width = (int)cx;
|
||||
_browser.Height = (int)cx;
|
||||
_browser.NavigationCompleted += async (object sender, CoreWebView2NavigationCompletedEventArgs args) =>
|
||||
{
|
||||
browser.Dock = DockStyle.Fill;
|
||||
browser.IsWebBrowserContextMenuEnabled = false;
|
||||
browser.ScriptErrorsSuppressed = true;
|
||||
browser.ScrollBarsEnabled = false;
|
||||
browser.AllowNavigation = false;
|
||||
browser.Width = (int)cx;
|
||||
browser.Height = (int)cx;
|
||||
browser.DocumentText = wrappedContent;
|
||||
|
||||
// Wait for the browser to render the content.
|
||||
while (browser.IsBusy || browser.ReadyState != WebBrowserReadyState.Complete)
|
||||
var a = await _browser.ExecuteScriptAsync($"document.getElementsByTagName('svg')[0].viewBox;");
|
||||
if (a != null)
|
||||
{
|
||||
Application.DoEvents();
|
||||
await _browser.ExecuteScriptAsync($"document.getElementsByTagName('svg')[0].style = 'width:100%;height:100%';");
|
||||
}
|
||||
|
||||
// Check size of the rendered SVG.
|
||||
var svg = browser.Document.GetElementsByTagName("svg").Cast<HtmlElement>().FirstOrDefault();
|
||||
if (svg != null)
|
||||
MemoryStream ms = new MemoryStream();
|
||||
await _browser.CoreWebView2.CapturePreviewAsync(CoreWebView2CapturePreviewImageFormat.Png, ms);
|
||||
thumbnail = new Bitmap(ms);
|
||||
|
||||
if (thumbnail.Width != cx && thumbnail.Height != cx && thumbnail.Width != 0 && thumbnail.Height != 0)
|
||||
{
|
||||
var viewBox = svg.GetAttribute("viewbox");
|
||||
if (viewBox != null)
|
||||
{
|
||||
// Update the svg style to override any width or height explicit settings
|
||||
// Setting to 100% width and height will allow to scale to our intended size
|
||||
// Otherwise, we would end up with a scaled up blurry image.
|
||||
svg.Style = "width:100%;height:100%";
|
||||
|
||||
// Wait for the browser to render the content.
|
||||
while (browser.IsBusy || browser.ReadyState != WebBrowserReadyState.Complete)
|
||||
{
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
|
||||
// Update the size of the browser control to fit the SVG
|
||||
// in the visible viewport.
|
||||
browser.Width = svg.OffsetRectangle.Width;
|
||||
browser.Height = svg.OffsetRectangle.Height;
|
||||
|
||||
// Wait for the browser to render the content.
|
||||
while (browser.IsBusy || browser.ReadyState != WebBrowserReadyState.Complete)
|
||||
{
|
||||
Application.DoEvents();
|
||||
}
|
||||
|
||||
// Capture the image of the SVG from the browser.
|
||||
thumbnail = GetBrowserContentImage(browser, svg.OffsetRectangle, Color.White);
|
||||
if (thumbnail.Width != cx && thumbnail.Height != cx)
|
||||
{
|
||||
// We are not the appropriate size for caller. Resize now while
|
||||
// respecting the aspect ratio.
|
||||
float scale = Math.Min((float)cx / thumbnail.Width, (float)cx / thumbnail.Height);
|
||||
int scaleWidth = (int)(thumbnail.Width * scale);
|
||||
int scaleHeight = (int)(thumbnail.Height * scale);
|
||||
thumbnail = ResizeImage(thumbnail, scaleWidth, scaleHeight);
|
||||
}
|
||||
// We are not the appropriate size for caller. Resize now while
|
||||
// respecting the aspect ratio.
|
||||
float scale = Math.Min((float)cx / thumbnail.Width, (float)cx / thumbnail.Height);
|
||||
int scaleWidth = (int)(thumbnail.Width * scale);
|
||||
int scaleHeight = (int)(thumbnail.Height * scale);
|
||||
thumbnail = ResizeImage(thumbnail, scaleWidth, scaleHeight);
|
||||
}
|
||||
|
||||
thumbnailDone = true;
|
||||
};
|
||||
|
||||
ConfiguredTaskAwaitable<CoreWebView2Environment>.ConfiguredTaskAwaiter
|
||||
webView2EnvironmentAwaiter = CoreWebView2Environment
|
||||
.CreateAsync(userDataFolder: System.Environment.GetEnvironmentVariable("USERPROFILE") +
|
||||
"\\AppData\\LocalLow\\Microsoft\\PowerToys\\SvgThumbnailPreview-Temp")
|
||||
.ConfigureAwait(true).GetAwaiter();
|
||||
webView2EnvironmentAwaiter.OnCompleted(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_webView2Environment = webView2EnvironmentAwaiter.GetResult();
|
||||
await _browser.EnsureCoreWebView2Async(_webView2Environment).ConfigureAwait(true);
|
||||
await _browser.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.addEventListener('contextmenu', window => {window.preventDefault();});");
|
||||
_browser.CoreWebView2.SetVirtualHostNameToFolderMapping(VirtualHostName, AssemblyDirectory, CoreWebView2HostResourceAccessKind.Allow);
|
||||
_browser.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
|
||||
_browser.NavigateToString(wrappedContent);
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
while (thumbnailDone == false)
|
||||
{
|
||||
Application.DoEvents();
|
||||
}
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap the SVG markup in HTML with a meta tag to ensure the
|
||||
/// WebBrowser control is in Edge mode to enable SVG rendering.
|
||||
/// Wrap the SVG markup in HTML with a meta tag to render it
|
||||
/// using WebView2 control.
|
||||
/// We also set the padding and margin for the body to zero as
|
||||
/// there is a default margin of 8.
|
||||
/// </summary>
|
||||
@@ -261,5 +244,10 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Svg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1150.38" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -2,18 +2,23 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.PowerToys.PreviewHandler.Markdown;
|
||||
using Microsoft.PowerToys.STATestExtension;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using PreviewHandlerCommon;
|
||||
using Microsoft.Web.WebView2.WinForms;
|
||||
|
||||
namespace MarkdownPreviewHandlerUnitTests
|
||||
{
|
||||
[STATestClass]
|
||||
public class MarkdownPreviewHandlerTest
|
||||
{
|
||||
private static readonly int TenSecondsInMilliseconds = 10000;
|
||||
private static readonly int SleepTimeInMilliseconds = 200;
|
||||
|
||||
[TestMethod]
|
||||
public void MarkdownPreviewHandlerControlAddsBrowserToFormWhenDoPreviewIsCalled()
|
||||
{
|
||||
@@ -23,9 +28,17 @@ namespace MarkdownPreviewHandlerUnitTests
|
||||
// Act
|
||||
markdownPreviewHandlerControl.DoPreview<string>("HelperFiles/MarkdownWithExternalImage.txt");
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (markdownPreviewHandlerControl.Controls.Count == 0 && Environment.TickCount < beforeTick + TenSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, markdownPreviewHandlerControl.Controls.Count);
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[0], typeof(WebBrowserExt));
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[0], typeof(WebView2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +51,14 @@ namespace MarkdownPreviewHandlerUnitTests
|
||||
// Act
|
||||
markdownPreviewHandlerControl.DoPreview<string>("HelperFiles/MarkdownWithExternalImage.txt");
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (markdownPreviewHandlerControl.Controls.Count == 0 && Environment.TickCount < beforeTick + TenSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, markdownPreviewHandlerControl.Controls.Count);
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[1], typeof(RichTextBox));
|
||||
@@ -53,6 +74,14 @@ namespace MarkdownPreviewHandlerUnitTests
|
||||
// Act
|
||||
markdownPreviewHandlerControl.DoPreview<string>("HelperFiles/MarkdownWithHTMLImageTag.txt");
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (markdownPreviewHandlerControl.Controls.Count < 2 && Environment.TickCount < beforeTick + TenSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, markdownPreviewHandlerControl.Controls.Count);
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[1], typeof(RichTextBox));
|
||||
@@ -68,9 +97,17 @@ namespace MarkdownPreviewHandlerUnitTests
|
||||
// Act
|
||||
markdownPreviewHandlerControl.DoPreview<string>("HelperFiles/MarkdownWithScript.txt");
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (markdownPreviewHandlerControl.Controls.Count == 0 && Environment.TickCount < beforeTick + TenSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(1, markdownPreviewHandlerControl.Controls.Count);
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[0], typeof(WebBrowserExt));
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[0], typeof(WebView2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,14 +120,17 @@ namespace MarkdownPreviewHandlerUnitTests
|
||||
// Act
|
||||
markdownPreviewHandlerControl.DoPreview<string>("HelperFiles/MarkdownWithExternalImage.txt");
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (markdownPreviewHandlerControl.Controls.Count < 2 && Environment.TickCount < beforeTick + TenSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[0], typeof(WebBrowserExt));
|
||||
Assert.IsNotNull(((WebBrowser)markdownPreviewHandlerControl.Controls[0]).DocumentText);
|
||||
Assert.AreEqual(DockStyle.Fill, ((WebBrowser)markdownPreviewHandlerControl.Controls[0]).Dock);
|
||||
Assert.AreEqual(false, ((WebBrowser)markdownPreviewHandlerControl.Controls[0]).IsWebBrowserContextMenuEnabled);
|
||||
Assert.AreEqual(true, ((WebBrowser)markdownPreviewHandlerControl.Controls[0]).ScriptErrorsSuppressed);
|
||||
Assert.AreEqual(true, ((WebBrowser)markdownPreviewHandlerControl.Controls[0]).ScrollBarsEnabled);
|
||||
Assert.AreEqual(false, ((WebBrowser)markdownPreviewHandlerControl.Controls[0]).AllowNavigation);
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[0], typeof(WebView2));
|
||||
Assert.AreEqual(DockStyle.Fill, ((WebView2)markdownPreviewHandlerControl.Controls[0]).Dock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +143,14 @@ namespace MarkdownPreviewHandlerUnitTests
|
||||
// Act
|
||||
markdownPreviewHandlerControl.DoPreview<string>("HelperFiles/MarkdownWithExternalImage.txt");
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (markdownPreviewHandlerControl.Controls.Count == 0 && Environment.TickCount < beforeTick + TenSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[1], typeof(RichTextBox));
|
||||
Assert.IsNotNull(((RichTextBox)markdownPreviewHandlerControl.Controls[1]).Text);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<ProjectGuid>{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}</ProjectGuid>
|
||||
<RootNamespace>PreviewPaneUnitTests</RootNamespace>
|
||||
<AssemblyName>PreviewPaneUnitTests</AssemblyName>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<TargetFramework>net6.0-windows10.0.18362.0</TargetFramework>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
|
||||
@@ -25,9 +25,6 @@
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.3" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="WebBrowserExtUnitTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\codeAnalysis\GlobalSuppressions.cs" Link="GlobalSuppressions.cs" />
|
||||
<Compile Include="..\STATestClassAttribute.cs" Link="STATestClassAttribute.cs" />
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Reflection;
|
||||
using Common;
|
||||
using Microsoft.PowerToys.STATestExtension;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using PreviewHandlerCommon;
|
||||
|
||||
namespace PreviewHandlerCommonUnitTests
|
||||
{
|
||||
[STATestClass]
|
||||
public class WebBrowserExtUnitTests : WebBrowserExt
|
||||
{
|
||||
private const string DISPIDAMBIENTDLCONTROL = "[DISPID=-5512]";
|
||||
|
||||
[TestMethod]
|
||||
public void InvokeMemberShouldSetValidFlagsWhenCalledWithValidDispId()
|
||||
{
|
||||
// Arrange
|
||||
var extendedSite = CreateWebBrowserSiteBase() as WebBrowserSiteExt;
|
||||
|
||||
// Act
|
||||
var actualFlags = (int)extendedSite.InvokeMember(DISPIDAMBIENTDLCONTROL, BindingFlags.InvokeMethod, null, null, null, null, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.PRAGMA_NO_CACHE) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.FORCEOFFLINE) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NO_CLIENTPULL) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NO_SCRIPTS) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NO_JAVA) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NO_FRAMEDOWNLOAD) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NOFRAMES) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NO_DLACTIVEXCTLS) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NO_RUNACTIVEXCTLS) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NO_BEHAVIORS) >= 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.SILENT) >= 0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InvokeMemberShouldOnlySetValidFlagsWhenCalledWithValidDispId()
|
||||
{
|
||||
// Arrange
|
||||
var extendedSite = CreateWebBrowserSiteBase() as WebBrowserSiteExt;
|
||||
|
||||
// Act
|
||||
var actualFlags = (int)extendedSite.InvokeMember(DISPIDAMBIENTDLCONTROL, BindingFlags.InvokeMethod, null, null, null, null, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.VIDEOS) == 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.BGSOUNDS) == 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.DOWNLOADONLY) == 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.RESYNCHRONIZE) == 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.NO_METACHARSET) == 0);
|
||||
Assert.IsTrue((actualFlags & (int)WebBrowserDownloadControlFlags.URL_ENCODING_DISABLE_UTF8) == 0);
|
||||
Assert.IsTrue((actualFlags & (uint)WebBrowserDownloadControlFlags.URL_ENCODING_ENABLE_UTF8) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,13 @@ using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.PowerToys.PreviewHandler.Svg;
|
||||
using Microsoft.PowerToys.STATestExtension;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.Web.WebView2.WinForms;
|
||||
using Moq;
|
||||
using PreviewHandlerCommon;
|
||||
|
||||
namespace SvgPreviewHandlerUnitTests
|
||||
{
|
||||
@@ -20,6 +21,9 @@ namespace SvgPreviewHandlerUnitTests
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2201:Do not raise reserved exception types", Justification = "new Exception() is fine in test projects.")]
|
||||
public class SvgPreviewControlTests
|
||||
{
|
||||
private static readonly int ThreeSecondsInMilliseconds = 3000;
|
||||
private static readonly int SleepTimeInMilliseconds = 200;
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControlShouldAddExtendedBrowserControlWhenDoPreviewCalled()
|
||||
{
|
||||
@@ -29,14 +33,22 @@ namespace SvgPreviewHandlerUnitTests
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream("<svg></svg>"));
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (svgPreviewControl.Controls.Count == 0 && Environment.TickCount < beforeTick + ThreeSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(1, svgPreviewControl.Controls.Count);
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(WebBrowserExt));
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(WebView2));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControlShouldSetDocumentStreamWhenDoPreviewCalled()
|
||||
public void SvgPreviewControlShouldFillDockForWebView2WhenDoPreviewCalled()
|
||||
{
|
||||
// Arrange
|
||||
using (var svgPreviewControl = new SvgPreviewControl())
|
||||
@@ -44,80 +56,16 @@ namespace SvgPreviewHandlerUnitTests
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream("<svg></svg>"));
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(((WebBrowser)svgPreviewControl.Controls[0]).DocumentStream);
|
||||
}
|
||||
}
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControlShouldDisableWebBrowserContextMenuWhenDoPreviewCalled()
|
||||
{
|
||||
// Arrange
|
||||
using (var svgPreviewControl = new SvgPreviewControl())
|
||||
{
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream("<svg></svg>"));
|
||||
while (svgPreviewControl.Controls.Count == 0 && Environment.TickCount < beforeTick + ThreeSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(false, ((WebBrowser)svgPreviewControl.Controls[0]).IsWebBrowserContextMenuEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControlShouldFillDockForWebBrowserWhenDoPreviewCalled()
|
||||
{
|
||||
// Arrange
|
||||
using (var svgPreviewControl = new SvgPreviewControl())
|
||||
{
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream("<svg></svg>"));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(DockStyle.Fill, ((WebBrowser)svgPreviewControl.Controls[0]).Dock);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControlShouldSetScriptErrorsSuppressedPropertyWhenDoPreviewCalled()
|
||||
{
|
||||
// Arrange
|
||||
using (var svgPreviewControl = new SvgPreviewControl())
|
||||
{
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream("<svg></svg>"));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(true, ((WebBrowser)svgPreviewControl.Controls[0]).ScriptErrorsSuppressed);
|
||||
}
|
||||
}
|
||||
|
||||
// ToDo: fix unit test
|
||||
[Ignore]
|
||||
[TestMethod]
|
||||
public void SvgPreviewControlShouldSetScrollBarsEnabledPropertyWhenDoPreviewCalled()
|
||||
{
|
||||
// Arrange
|
||||
using (var svgPreviewControl = new SvgPreviewControl())
|
||||
{
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream("<svg></svg>"));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(true, ((WebBrowser)svgPreviewControl.Controls[0]).ScrollBarsEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControlShouldDisableAllowNavigationWhenDoPreviewCalled()
|
||||
{
|
||||
// Arrange
|
||||
using (var svgPreviewControl = new SvgPreviewControl())
|
||||
{
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream("<svg></svg>"));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(false, ((WebBrowser)svgPreviewControl.Controls[0]).AllowNavigation);
|
||||
Assert.AreEqual(DockStyle.Fill, ((WebView2)svgPreviewControl.Controls[0]).Dock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +82,15 @@ namespace SvgPreviewHandlerUnitTests
|
||||
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(mockStream.Object);
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (svgPreviewControl.Controls.Count == 0 && Environment.TickCount < beforeTick + ThreeSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
var textBox = svgPreviewControl.Controls[0] as RichTextBox;
|
||||
|
||||
// Assert
|
||||
@@ -159,6 +116,15 @@ namespace SvgPreviewHandlerUnitTests
|
||||
.Setup(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<IntPtr>()))
|
||||
.Throws(new Exception());
|
||||
svgPreviewControl.DoPreview(mockStream.Object);
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (svgPreviewControl.Controls.Count == 0 && Environment.TickCount < beforeTick + ThreeSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
var textBox = svgPreviewControl.Controls[0] as RichTextBox;
|
||||
var incrementParentControlWidth = 5;
|
||||
var initialParentWidth = svgPreviewControl.Width;
|
||||
@@ -188,9 +154,17 @@ namespace SvgPreviewHandlerUnitTests
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString()));
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (svgPreviewControl.Controls.Count < 2 && Environment.TickCount < beforeTick + ThreeSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(RichTextBox));
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[1], typeof(WebBrowserExt));
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[1], typeof(WebView2));
|
||||
Assert.AreEqual(2, svgPreviewControl.Controls.Count);
|
||||
}
|
||||
}
|
||||
@@ -210,8 +184,16 @@ namespace SvgPreviewHandlerUnitTests
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString()));
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (svgPreviewControl.Controls.Count == 0 && Environment.TickCount < beforeTick + ThreeSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(WebBrowserExt));
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(WebView2));
|
||||
Assert.AreEqual(1, svgPreviewControl.Controls.Count);
|
||||
}
|
||||
}
|
||||
@@ -227,6 +209,15 @@ namespace SvgPreviewHandlerUnitTests
|
||||
svgBuilder.AppendLine("\t<script>alert(\"hello\")</script>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString()));
|
||||
|
||||
int beforeTick = Environment.TickCount;
|
||||
|
||||
while (svgPreviewControl.Controls.Count == 0 && Environment.TickCount < beforeTick + ThreeSecondsInMilliseconds)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Thread.Sleep(SleepTimeInMilliseconds);
|
||||
}
|
||||
|
||||
var textBox = svgPreviewControl.Controls[0] as RichTextBox;
|
||||
var incrementParentControlWidth = 5;
|
||||
var initialParentWidth = svgPreviewControl.Width;
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Common.ComInterlop;
|
||||
using Microsoft.PowerToys.STATestExtension;
|
||||
using Microsoft.PowerToys.ThumbnailHandler.Svg;
|
||||
@@ -27,8 +28,12 @@ namespace SvgThumbnailProviderUnitTests
|
||||
svgBuilder.AppendLine("\t</circle>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
|
||||
Bitmap thumbnail = SvgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||
Assert.IsTrue(thumbnail != null);
|
||||
SvgThumbnailProvider svgThumbnailProvider = new SvgThumbnailProvider();
|
||||
Bitmap thumbnail = svgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||
|
||||
Assert.IsNotNull(thumbnail);
|
||||
Assert.IsTrue(thumbnail.Width > 0);
|
||||
Assert.IsTrue(thumbnail.Height > 0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -41,7 +46,8 @@ namespace SvgThumbnailProviderUnitTests
|
||||
svgBuilder.AppendLine("\t</circle>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
|
||||
Bitmap thumbnail = SvgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||
SvgThumbnailProvider svgThumbnailProvider = new SvgThumbnailProvider();
|
||||
Bitmap thumbnail = svgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||
Assert.IsTrue(thumbnail != null);
|
||||
}
|
||||
|
||||
@@ -51,21 +57,24 @@ namespace SvgThumbnailProviderUnitTests
|
||||
var svgBuilder = new StringBuilder();
|
||||
svgBuilder.AppendLine("<p>foo</p>");
|
||||
|
||||
Bitmap thumbnail = SvgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||
SvgThumbnailProvider svgThumbnailProvider = new SvgThumbnailProvider();
|
||||
Bitmap thumbnail = svgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||
Assert.IsTrue(thumbnail == null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CheckNoSvgEmptyStringShouldReturnNullBitmap()
|
||||
{
|
||||
Bitmap thumbnail = SvgThumbnailProvider.GetThumbnail(string.Empty, 256);
|
||||
SvgThumbnailProvider svgThumbnailProvider = new SvgThumbnailProvider();
|
||||
Bitmap thumbnail = svgThumbnailProvider.GetThumbnail(string.Empty, 256);
|
||||
Assert.IsTrue(thumbnail == null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CheckNoSvgNullStringShouldReturnNullBitmap()
|
||||
{
|
||||
Bitmap thumbnail = SvgThumbnailProvider.GetThumbnail(null, 256);
|
||||
SvgThumbnailProvider svgThumbnailProvider = new SvgThumbnailProvider();
|
||||
Bitmap thumbnail = svgThumbnailProvider.GetThumbnail(null, 256);
|
||||
Assert.IsTrue(thumbnail == null);
|
||||
}
|
||||
|
||||
@@ -73,7 +82,8 @@ namespace SvgThumbnailProviderUnitTests
|
||||
public void CheckZeroSizedThumbnailShouldReturnNullBitmap()
|
||||
{
|
||||
string content = "<svg></svg>";
|
||||
Bitmap thumbnail = SvgThumbnailProvider.GetThumbnail(content, 0);
|
||||
SvgThumbnailProvider svgThumbnailProvider = new SvgThumbnailProvider();
|
||||
Bitmap thumbnail = svgThumbnailProvider.GetThumbnail(content, 0);
|
||||
Assert.IsTrue(thumbnail == null);
|
||||
}
|
||||
|
||||
@@ -94,7 +104,8 @@ namespace SvgThumbnailProviderUnitTests
|
||||
svgBuilder.AppendLine("</body>");
|
||||
svgBuilder.AppendLine("</html>");
|
||||
|
||||
Bitmap thumbnail = SvgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||
SvgThumbnailProvider svgThumbnailProvider = new SvgThumbnailProvider();
|
||||
Bitmap thumbnail = svgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||
Assert.IsTrue(thumbnail != null);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\codeAnalysis\GlobalSuppressions.cs" Link="GlobalSuppressions.cs" />
|
||||
<Compile Update="controls\WebBrowserExt.cs" />
|
||||
<Compile Update="examplehandler\CustomControlTest.cs" />
|
||||
<Compile Update="controls\FormHandlerControl.cs" />
|
||||
</ItemGroup>
|
||||
@@ -39,6 +38,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1150.38" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace Common
|
||||
this.Controls.Clear();
|
||||
});
|
||||
|
||||
// Call garbage collection at the time of unloading of Preview. This is to mitigate issue with WebBrowser Control not able to dispose properly.
|
||||
// Call garbage collection at the time of unloading of Preview.
|
||||
// Which is preventing prevhost.exe to exit at the time of closing File explorer.
|
||||
// Preview Handlers run in a separate process from PowerToys. This will not affect the performance of other modules.
|
||||
// Mitigate the following Github issue: https://github.com/microsoft/PowerToys/issues/1468
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags to control download and execution in Web Browser Control.
|
||||
/// Values of flags are defined in mshtmdid.h in distributed Windows Sdk.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Interop, keeping stuff in sync")]
|
||||
public enum WebBrowserDownloadControlFlags : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Images will be downloaded from the server if this flag is set.
|
||||
/// </summary>
|
||||
DLIMAGES = 0x00000010,
|
||||
|
||||
/// <summary>
|
||||
/// Videos will be downloaded from the server if this flag is set.
|
||||
/// </summary>
|
||||
VIDEOS = 0x00000020,
|
||||
|
||||
/// <summary>
|
||||
/// Background sounds will be downloaded from the server if this flag is set.
|
||||
/// </summary>
|
||||
BGSOUNDS = 0x00000040,
|
||||
|
||||
/// <summary>
|
||||
/// Scripts will not be executed.
|
||||
/// </summary>
|
||||
NO_SCRIPTS = 0x00000080,
|
||||
|
||||
/// <summary>
|
||||
/// Java applets will not be executed.
|
||||
/// </summary>
|
||||
NO_JAVA = 0x00000100,
|
||||
|
||||
/// <summary>
|
||||
/// ActiveX controls will not be executed.
|
||||
/// </summary>
|
||||
NO_RUNACTIVEXCTLS = 0x00000200,
|
||||
|
||||
/// <summary>
|
||||
/// ActiveX controls will not be downloaded.
|
||||
/// </summary>
|
||||
NO_DLACTIVEXCTLS = 0x00000400,
|
||||
|
||||
/// <summary>
|
||||
/// The page will only be downloaded, not displayed.
|
||||
/// </summary>
|
||||
DOWNLOADONLY = 0x00000800,
|
||||
|
||||
/// <summary>
|
||||
/// WebBrowser Control will download and parse a frameSet, but not the individual frame objects within the frameSet.
|
||||
/// </summary>
|
||||
NO_FRAMEDOWNLOAD = 0x00001000,
|
||||
|
||||
/// <summary>
|
||||
/// The server will be asked for update status. Cached files will be used if the server indicates that the cached information is up-to-date.
|
||||
/// </summary>
|
||||
RESYNCHRONIZE = 0x00002000,
|
||||
|
||||
/// <summary>
|
||||
/// Files will be re-downloaded from the server regardless of the update status of the files.
|
||||
/// </summary>
|
||||
PRAGMA_NO_CACHE = 0x00004000,
|
||||
|
||||
/// <summary>
|
||||
/// Behaviors are not downloaded and are disabled in the document.
|
||||
/// </summary>
|
||||
NO_BEHAVIORS = 0x00008000,
|
||||
|
||||
/// <summary>
|
||||
/// Character sets specified in meta elements are suppressed.
|
||||
/// </summary>
|
||||
NO_METACHARSET = 0x00010000,
|
||||
|
||||
/// <summary>
|
||||
/// The browsing component will disable UTF-8 encoding.
|
||||
/// </summary>
|
||||
URL_ENCODING_DISABLE_UTF8 = 0x00020000,
|
||||
|
||||
/// <summary>
|
||||
/// The browsing component will enable UTF-8 encoding.
|
||||
/// </summary>
|
||||
URL_ENCODING_ENABLE_UTF8 = 0x00040000,
|
||||
|
||||
/// <summary>
|
||||
/// No Documentation Available.
|
||||
/// </summary>
|
||||
NOFRAMES = 0x00080000,
|
||||
|
||||
/// <summary>
|
||||
/// WebBrowser Control always operates in offline mode.
|
||||
/// </summary>
|
||||
FORCEOFFLINE = 0x10000000,
|
||||
|
||||
/// <summary>
|
||||
/// No client pull operations will be performed.
|
||||
/// </summary>
|
||||
NO_CLIENTPULL = 0x20000000,
|
||||
|
||||
/// <summary>
|
||||
/// No user interface will be displayed during downloads.
|
||||
/// </summary>
|
||||
SILENT = 0x40000000,
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using Common;
|
||||
|
||||
namespace PreviewHandlerCommon
|
||||
{
|
||||
/// <summary>
|
||||
/// Customized the WebBrowser to get control over what it downloads, displays and executes.
|
||||
/// </summary>
|
||||
public class WebBrowserExt : WebBrowser
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
|
||||
{
|
||||
// Returns instance of WebBrowserSiteExt.
|
||||
return new WebBrowserSiteExt(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extend the WebBrowserSite with IDispatch implementation to handle the DISPID_AMBIENT_DLCONTROL.
|
||||
/// More details: https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa770041(v=vs.85)?redirectedfrom=MSDN#controlling-download-and-execution.
|
||||
/// </summary>
|
||||
protected class WebBrowserSiteExt : WebBrowserSite, IReflect
|
||||
{
|
||||
// Dispid of DISPID_AMBIENT_DLCONTROL is defined in MsHtmdid.h header file in distributed Windows Sdk component.
|
||||
private const string DISPIDAMBIENTDLCONTROL = "[DISPID=-5512]";
|
||||
private WebBrowserExt browserExtControl;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebBrowserSiteExt"/> class.
|
||||
/// </summary>
|
||||
/// <param name="browserControl">Browser Control Instance pass to the site.</param>
|
||||
public WebBrowserSiteExt(WebBrowserExt browserControl)
|
||||
: base(browserControl)
|
||||
{
|
||||
this.browserExtControl = browserControl;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Type UnderlyingSystemType
|
||||
{
|
||||
get { return this.GetType(); }
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
|
||||
{
|
||||
object result;
|
||||
|
||||
if (name != null && name.Equals(DISPIDAMBIENTDLCONTROL, StringComparison.Ordinal))
|
||||
{
|
||||
// Using InvariantCulture since this is used for web browser configurations
|
||||
result = Convert.ToInt32(
|
||||
WebBrowserDownloadControlFlags.DLIMAGES |
|
||||
WebBrowserDownloadControlFlags.PRAGMA_NO_CACHE |
|
||||
WebBrowserDownloadControlFlags.FORCEOFFLINE |
|
||||
WebBrowserDownloadControlFlags.NO_CLIENTPULL |
|
||||
WebBrowserDownloadControlFlags.NO_SCRIPTS |
|
||||
WebBrowserDownloadControlFlags.NO_JAVA |
|
||||
WebBrowserDownloadControlFlags.NO_FRAMEDOWNLOAD |
|
||||
WebBrowserDownloadControlFlags.NOFRAMES |
|
||||
WebBrowserDownloadControlFlags.NO_DLACTIVEXCTLS |
|
||||
WebBrowserDownloadControlFlags.NO_RUNACTIVEXCTLS |
|
||||
WebBrowserDownloadControlFlags.NO_BEHAVIORS |
|
||||
WebBrowserDownloadControlFlags.SILENT, CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = GetType().InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FieldInfo[] GetFields(BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetFields(bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MethodInfo[] GetMethods(BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetMethods(bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public PropertyInfo[] GetProperties(BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetProperties(bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FieldInfo GetField(string name, BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetField(name, bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetMember(name, bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MemberInfo[] GetMembers(BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetMembers(bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetMethod(name, bindingAttr);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
|
||||
{
|
||||
return this.GetType().GetMethod(name, bindingAttr, binder, types, modifiers);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
|
||||
{
|
||||
return this.GetType().GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
|
||||
{
|
||||
return this.GetType().GetProperty(name, bindingAttr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,12 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Microsoft.Web.WebView2.WinForms;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
@@ -12,6 +17,38 @@ namespace Common
|
||||
/// </summary>
|
||||
public class CustomControlTest : FormHandlerControl
|
||||
{
|
||||
/// <summary>
|
||||
/// WebView2 Control to display Svg.
|
||||
/// </summary>
|
||||
private WebView2 _browser;
|
||||
|
||||
/// <summary>
|
||||
/// WebView2 Environment
|
||||
/// </summary>
|
||||
private CoreWebView2Environment _webView2Environment;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the virtual host
|
||||
/// </summary>
|
||||
public const string VirtualHostName = "PowerToysLocalCustomControlTest";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the current assembly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Source: https://stackoverflow.com/a/283917/14774889
|
||||
/// </remarks>
|
||||
public static string AssemblyDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().Location;
|
||||
UriBuilder uri = new UriBuilder(codeBase);
|
||||
string path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the preview on the Control.
|
||||
/// </summary>
|
||||
@@ -21,13 +58,41 @@ namespace Common
|
||||
this.InvokeOnControlThread(() =>
|
||||
{
|
||||
var filePath = dataSource as string;
|
||||
WebBrowser browser = new WebBrowser();
|
||||
|
||||
browser.DocumentText = "Test";
|
||||
browser.Navigate(new Uri(filePath));
|
||||
browser.Dock = DockStyle.Fill;
|
||||
browser.IsWebBrowserContextMenuEnabled = false;
|
||||
this.Controls.Add(browser);
|
||||
_browser = new WebView2();
|
||||
_browser.Dock = DockStyle.Fill;
|
||||
_browser.Visible = true;
|
||||
_browser.NavigationCompleted += (object sender, CoreWebView2NavigationCompletedEventArgs args) =>
|
||||
{
|
||||
// Put here logic needed after WebView2 control is done navigating to url/page
|
||||
};
|
||||
|
||||
ConfiguredTaskAwaitable<CoreWebView2Environment>.ConfiguredTaskAwaiter
|
||||
webView2EnvironmentAwaiter = CoreWebView2Environment
|
||||
.CreateAsync(userDataFolder: System.Environment.GetEnvironmentVariable("USERPROFILE") +
|
||||
"\\AppData\\LocalLow\\Microsoft\\PowerToys\\CustomControlTest-Temp")
|
||||
.ConfigureAwait(true).GetAwaiter();
|
||||
webView2EnvironmentAwaiter.OnCompleted(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_webView2Environment = webView2EnvironmentAwaiter.GetResult();
|
||||
await _browser.EnsureCoreWebView2Async(_webView2Environment).ConfigureAwait(true);
|
||||
await _browser.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.addEventListener('contextmenu', window => {window.preventDefault();});");
|
||||
_browser.CoreWebView2.SetVirtualHostNameToFolderMapping(VirtualHostName, AssemblyDirectory, CoreWebView2HostResourceAccessKind.Allow);
|
||||
|
||||
// Navigate to page represented as a string
|
||||
_browser.NavigateToString("Test");
|
||||
|
||||
// Or navigate to Uri
|
||||
_browser.Source = new Uri(filePath);
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
this.Controls.Add(_browser);
|
||||
base.DoPreview(dataSource);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user