mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-10-21 19:25:14 +00:00
Fix #539: replace IE WebView with Edge WebView2
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// Copyright © 2017 Paddy Xu
|
// Copyright © 2021 Paddy Xu and mooflu
|
||||||
//
|
//
|
||||||
// This file is part of QuickLook program.
|
// This file is part of QuickLook program.
|
||||||
//
|
//
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
@@ -23,13 +24,26 @@ namespace QuickLook.Plugin.HtmlViewer
|
|||||||
{
|
{
|
||||||
internal static class Helper
|
internal static class Helper
|
||||||
{
|
{
|
||||||
public static string FilePathToFileUrl(string filePath)
|
public static bool IsWebView2Available()
|
||||||
|
{
|
||||||
|
var path = App.Is64Bit
|
||||||
|
? @"SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}\"
|
||||||
|
: @"SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}\";
|
||||||
|
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey(path, RegistryKeyPermissionCheck.ReadSubTree))
|
||||||
|
{
|
||||||
|
var pv = key?.GetValue("pv");
|
||||||
|
return !string.IsNullOrEmpty(pv as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Uri FilePathToFileUrl(string filePath)
|
||||||
{
|
{
|
||||||
var uri = new StringBuilder();
|
var uri = new StringBuilder();
|
||||||
foreach (var v in filePath)
|
foreach (var v in filePath)
|
||||||
if (v >= 'a' && v <= 'z' || v >= 'A' && v <= 'Z' || v >= '0' && v <= '9' ||
|
if (v >= 'a' && v <= 'z' || v >= 'A' && v <= 'Z' || v >= '0' && v <= '9' ||
|
||||||
v == '+' || v == '/' || v == ':' || v == '.' || v == '-' || v == '_' || v == '~' ||
|
v == '+' || v == '/' || v == ':' || v == '.' || v == '-' || v == '_' || v == '~' ||
|
||||||
v > '\xFF')
|
v > '\x80')
|
||||||
uri.Append(v);
|
uri.Append(v);
|
||||||
else if (v == Path.DirectorySeparatorChar || v == Path.AltDirectorySeparatorChar)
|
else if (v == Path.DirectorySeparatorChar || v == Path.AltDirectorySeparatorChar)
|
||||||
uri.Append('/');
|
uri.Append('/');
|
||||||
@@ -39,48 +53,34 @@ namespace QuickLook.Plugin.HtmlViewer
|
|||||||
uri.Insert(0, "file:");
|
uri.Insert(0, "file:");
|
||||||
else
|
else
|
||||||
uri.Insert(0, "file:///");
|
uri.Insert(0, "file:///");
|
||||||
return uri.ToString();
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new Uri(uri.ToString());
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
public static void SetBrowserFeatureControl()
|
|
||||||
{
|
{
|
||||||
var exeName = Path.GetFileName(App.AppFullPath);
|
return null;
|
||||||
|
|
||||||
// use latest engine
|
|
||||||
SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", exeName, 0);
|
|
||||||
//
|
|
||||||
SetBrowserFeatureControlKey("FEATURE_GPU_RENDERING", exeName, 0);
|
|
||||||
// turn on hi-dpi mode
|
|
||||||
SetBrowserFeatureControlKey("FEATURE_96DPI_PIXEL", exeName, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetBrowserFeatureControlKey(string feature, string appName, uint value)
|
|
||||||
{
|
|
||||||
using (var key = Registry.CurrentUser.CreateSubKey(
|
|
||||||
string.Concat(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\", feature),
|
|
||||||
RegistryKeyPermissionCheck.ReadWriteSubTree))
|
|
||||||
{
|
|
||||||
key?.SetValue(appName, value, RegistryValueKind.DWord);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetUrlPath(string url)
|
internal static string GetUrlPath(string url)
|
||||||
{
|
{
|
||||||
int index = -1;
|
var index = -1;
|
||||||
string[] lines = File.ReadAllLines(url);
|
var lines = File.ReadAllLines(url);
|
||||||
foreach (string line in lines)
|
foreach (var line in lines)
|
||||||
{
|
|
||||||
if (line.ToLower().Contains("url="))
|
if (line.ToLower().Contains("url="))
|
||||||
{
|
{
|
||||||
index = System.Array.IndexOf(lines, line);
|
index = Array.IndexOf(lines, line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
var fullLine = lines.GetValue(index);
|
var fullLine = lines.GetValue(index);
|
||||||
return fullLine.ToString().Substring(fullLine.ToString().LastIndexOf('=') + 1);
|
return fullLine.ToString().Substring(fullLine.ToString().LastIndexOf('=') + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright © 2017 Paddy Xu
|
// Copyright © 2021 Paddy Xu and mooflu
|
||||||
//
|
//
|
||||||
// This file is part of QuickLook program.
|
// This file is part of QuickLook program.
|
||||||
//
|
//
|
||||||
@@ -15,11 +15,11 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
using Microsoft.Web.WebView2.Wpf;
|
||||||
using QuickLook.Common.Plugin;
|
using QuickLook.Common.Plugin;
|
||||||
|
|
||||||
namespace QuickLook.Plugin.HtmlViewer
|
namespace QuickLook.Plugin.HtmlViewer
|
||||||
@@ -35,12 +35,16 @@ namespace QuickLook.Plugin.HtmlViewer
|
|||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
Helper.SetBrowserFeatureControl();
|
if (Helper.IsWebView2Available())
|
||||||
|
new WebView2().EnsureCoreWebView2Async();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
public bool CanHandle(string path)
|
||||||
{
|
{
|
||||||
return !Directory.Exists(path) && (Extensions.Any(path.ToLower().EndsWith) || (path.ToLower().EndsWith(".url") && SupportedProtocols.Contains(Helper.GetUrlPath(path).Split(':')[0].ToLower())));
|
return !Directory.Exists(path) && (Extensions.Any(path.ToLower().EndsWith) ||
|
||||||
|
path.ToLower().EndsWith(".url") &&
|
||||||
|
SupportedProtocols.Contains(Helper.GetUrlPath(path).Split(':')[0]
|
||||||
|
.ToLower()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Prepare(string path, ContextObject context)
|
public void Prepare(string path, ContextObject context)
|
||||||
@@ -55,10 +59,8 @@ namespace QuickLook.Plugin.HtmlViewer
|
|||||||
context.Title = Path.IsPathRooted(path) ? Path.GetFileName(path) : path;
|
context.Title = Path.IsPathRooted(path) ? Path.GetFileName(path) : path;
|
||||||
|
|
||||||
if (path.ToLower().EndsWith(".url"))
|
if (path.ToLower().EndsWith(".url"))
|
||||||
{
|
|
||||||
path = Helper.GetUrlPath(path);
|
path = Helper.GetUrlPath(path);
|
||||||
}
|
_panel.NavigateToFile(path);
|
||||||
_panel.LoadFile(path);
|
|
||||||
_panel.Dispatcher.Invoke(() => { context.IsBusy = false; }, DispatcherPriority.Loaded);
|
_panel.Dispatcher.Invoke(() => { context.IsBusy = false; }, DispatcherPriority.Loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -61,6 +61,15 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="Microsoft.Web.WebView2.Core, Version=1.0.664.37, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\..\packages\Microsoft.Web.WebView2.1.0.664.37\lib\net462\Microsoft.Web.WebView2.Core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.Web.WebView2.WinForms, Version=1.0.664.37, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\..\packages\Microsoft.Web.WebView2.1.0.664.37\lib\net462\Microsoft.Web.WebView2.WinForms.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.Web.WebView2.Wpf, Version=1.0.664.37, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\..\packages\Microsoft.Web.WebView2.1.0.664.37\lib\net462\Microsoft.Web.WebView2.Wpf.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
@@ -73,7 +82,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="WebpagePanel.cs" />
|
<Compile Include="WebpagePanel.cs" />
|
||||||
<Compile Include="WpfBrowserWrapper.cs" />
|
|
||||||
<Compile Include="..\..\GitVersion.cs">
|
<Compile Include="..\..\GitVersion.cs">
|
||||||
<Link>Properties\GitVersion.cs</Link>
|
<Link>Properties\GitVersion.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -108,5 +116,19 @@
|
|||||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||||
</COMReference>
|
</COMReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="Translations.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Import Project="..\..\packages\Microsoft.Web.WebView2.1.0.664.37\build\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\packages\Microsoft.Web.WebView2.1.0.664.37\build\Microsoft.Web.WebView2.targets')" />
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\..\packages\Microsoft.Web.WebView2.1.0.664.37\build\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Web.WebView2.1.0.664.37\build\Microsoft.Web.WebView2.targets'))" />
|
||||||
|
</Target>
|
||||||
</Project>
|
</Project>
|
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<Translations>
|
||||||
|
<en>
|
||||||
|
<WEBVIEW2_NOT_AVAILABLE>Viewing this file requires Microsoft Edge WebView2 to be present on the system. Click here to download it.</WEBVIEW2_NOT_AVAILABLE>
|
||||||
|
</en>
|
||||||
|
<ja>
|
||||||
|
<WEBVIEW2_NOT_AVAILABLE>このファイルを閲覧するには、Microsoft Edge WebView2 がインストールされている必要があります。 ここをクリックしてダウンロードを開始する。</WEBVIEW2_NOT_AVAILABLE>
|
||||||
|
</ja>
|
||||||
|
<zh-CN>
|
||||||
|
<WEBVIEW2_NOT_AVAILABLE>查看此文件需要安装 Microsoft Edge WebView2。 点击这里开始下载。</WEBVIEW2_NOT_AVAILABLE>
|
||||||
|
</zh-CN>
|
||||||
|
<zh-TW>
|
||||||
|
<WEBVIEW2_NOT_AVAILABLE>查看此文件需要安裝 Microsoft Edge WebView2。 點擊這裡開始下載。</WEBVIEW2_NOT_AVAILABLE>
|
||||||
|
</zh-TW>
|
||||||
|
</Translations>
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright © 2017 Paddy Xu
|
// Copyright © 2021 Paddy Xu and mooflu
|
||||||
//
|
//
|
||||||
// This file is part of QuickLook program.
|
// This file is part of QuickLook program.
|
||||||
//
|
//
|
||||||
@@ -15,42 +15,85 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Controls;
|
||||||
|
using Microsoft.Web.WebView2.Core;
|
||||||
|
using Microsoft.Web.WebView2.Wpf;
|
||||||
using QuickLook.Common.Helpers;
|
using QuickLook.Common.Helpers;
|
||||||
|
|
||||||
namespace QuickLook.Plugin.HtmlViewer
|
namespace QuickLook.Plugin.HtmlViewer
|
||||||
{
|
{
|
||||||
public class WebpagePanel : WpfWebBrowserWrapper
|
public class WebpagePanel : UserControl
|
||||||
{
|
{
|
||||||
|
private Uri _currentUri;
|
||||||
|
private WebView2 _webView;
|
||||||
|
|
||||||
public WebpagePanel()
|
public WebpagePanel()
|
||||||
{
|
{
|
||||||
Zoom = (int)(100 * DpiHelper.GetCurrentScaleFactor().Vertical);
|
if (!Helper.IsWebView2Available())
|
||||||
}
|
|
||||||
|
|
||||||
// adjust zoom when DPI changes.
|
|
||||||
protected override void OnDpiChanged(DpiScale oldDpi, DpiScale newDpi)
|
|
||||||
{
|
{
|
||||||
var ratio = newDpi.DpiScaleX / oldDpi.DpiScaleX;
|
Content = CreateDownloadButton();
|
||||||
Zoom = (int)(Zoom * ratio);
|
|
||||||
base.OnDpiChanged(oldDpi, newDpi);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
public void LoadFile(string path)
|
|
||||||
{
|
{
|
||||||
if (Path.IsPathRooted(path))
|
_webView = new WebView2();
|
||||||
path = Helper.FilePathToFileUrl(path);
|
_webView.NavigationStarting += NavigationStarting_CancelNavigation;
|
||||||
|
Content = _webView;
|
||||||
Dispatcher.Invoke(() => { base.Navigate(path); }, DispatcherPriority.Loaded);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadHtml(string html)
|
public void NavigateToFile(string path)
|
||||||
{
|
{
|
||||||
var s = new MemoryStream(Encoding.UTF8.GetBytes(html ?? ""));
|
var uri = Path.IsPathRooted(path) ? Helper.FilePathToFileUrl(path) : new Uri(path);
|
||||||
|
|
||||||
Dispatcher.Invoke(() => { base.Navigate(s); }, DispatcherPriority.Loaded);
|
NavigateToUri(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NavigateToUri(Uri uri)
|
||||||
|
{
|
||||||
|
if (_webView == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_webView.Source = uri;
|
||||||
|
_currentUri = _webView?.Source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NavigateToHtml(string html)
|
||||||
|
{
|
||||||
|
_webView.EnsureCoreWebView2Async()
|
||||||
|
.ContinueWith(_ => Dispatcher.Invoke(() => _webView?.NavigateToString(html)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NavigationStarting_CancelNavigation(object sender, CoreWebView2NavigationStartingEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Uri.StartsWith("data:")) // when using NavigateToString
|
||||||
|
return;
|
||||||
|
|
||||||
|
var newUri = new Uri(e.Uri);
|
||||||
|
if (newUri != _currentUri) e.Cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_webView?.Dispose();
|
||||||
|
_webView = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private object CreateDownloadButton()
|
||||||
|
{
|
||||||
|
var button = new Button
|
||||||
|
{
|
||||||
|
Content = TranslationHelper.Get("WEBVIEW2_NOT_AVAILABLE"),
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
Padding = new Thickness(20, 6, 20, 6)
|
||||||
|
};
|
||||||
|
button.Click += (sender, e) => Process.Start("https://go.microsoft.com/fwlink/p/?LinkId=2124703");
|
||||||
|
|
||||||
|
return button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,253 +0,0 @@
|
|||||||
// Copyright © 2017 Paddy Xu
|
|
||||||
//
|
|
||||||
// This file is part of QuickLook program.
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Windows.Navigation;
|
|
||||||
using SHDocVw;
|
|
||||||
using HorizontalAlignment = System.Windows.HorizontalAlignment;
|
|
||||||
using WebBrowser = System.Windows.Controls.WebBrowser;
|
|
||||||
|
|
||||||
namespace QuickLook.Plugin.HtmlViewer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class wraps a Browser (which itself is a bad designed WPF control) and presents itself as
|
|
||||||
/// a better designed WPF control. For example provides a bindable source property or commands.
|
|
||||||
/// </summary>
|
|
||||||
public class WpfWebBrowserWrapper : ContentControl, IDisposable
|
|
||||||
{
|
|
||||||
private static readonly Guid SidSWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
|
|
||||||
|
|
||||||
private WebBrowser _innerBrowser;
|
|
||||||
private bool _loaded;
|
|
||||||
private int _zoom;
|
|
||||||
|
|
||||||
public WpfWebBrowserWrapper()
|
|
||||||
{
|
|
||||||
_innerBrowser = new WebBrowser
|
|
||||||
{
|
|
||||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
|
||||||
VerticalAlignment = VerticalAlignment.Stretch
|
|
||||||
};
|
|
||||||
|
|
||||||
Content = _innerBrowser;
|
|
||||||
_innerBrowser.Navigated += InnerBrowserNavigated;
|
|
||||||
_innerBrowser.Navigating += InnerBrowserNavigating;
|
|
||||||
_innerBrowser.LoadCompleted += InnerBrowserLoadCompleted;
|
|
||||||
_innerBrowser.Loaded += InnerBrowserLoaded;
|
|
||||||
_innerBrowser.SizeChanged += InnerBrowserSizeChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Url { get; private set; }
|
|
||||||
|
|
||||||
public int Zoom
|
|
||||||
{
|
|
||||||
get => _zoom;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_zoom = value;
|
|
||||||
ApplyZoom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// gets the browser control's underlying activeXcontrol. Ready only from within Loaded-event but before loaded Document!
|
|
||||||
// do not use prior loaded event.
|
|
||||||
public InternetExplorer ActiveXControl
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// this is a brilliant way to access the WebBrowserObject prior to displaying the actual document (eg. Document property)
|
|
||||||
var fiComWebBrowser =
|
|
||||||
typeof(WebBrowser).GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
||||||
if (fiComWebBrowser == null) return null;
|
|
||||||
var objComWebBrowser = fiComWebBrowser.GetValue(_innerBrowser);
|
|
||||||
return objComWebBrowser as InternetExplorer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_innerBrowser.Source = null;
|
|
||||||
_innerBrowser.Dispose();
|
|
||||||
_innerBrowser = null;
|
|
||||||
Content = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InnerBrowserSizeChanged(object sender, SizeChangedEventArgs e)
|
|
||||||
{
|
|
||||||
ApplyZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InnerBrowserLoaded(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var ie = ActiveXControl;
|
|
||||||
ie.Silent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called when the loading of a web page is done
|
|
||||||
private void InnerBrowserLoadCompleted(object sender, NavigationEventArgs e)
|
|
||||||
{
|
|
||||||
ApplyZoom(); // apply later and not only at changed event, since only works if browser is rendered.
|
|
||||||
}
|
|
||||||
|
|
||||||
// called when the browser started to load and retrieve data.
|
|
||||||
private void InnerBrowserNavigating(object sender, NavigatingCancelEventArgs e)
|
|
||||||
{
|
|
||||||
if (_loaded)
|
|
||||||
if (_innerBrowser.Source != null)
|
|
||||||
if (_innerBrowser.Source.Scheme != e.Uri.Scheme ||
|
|
||||||
_innerBrowser.Source.AbsolutePath != e.Uri.AbsolutePath) // allow in-page navigation
|
|
||||||
e.Cancel = true;
|
|
||||||
_loaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// re query the commands once done navigating.
|
|
||||||
private void InnerBrowserNavigated(object sender, NavigationEventArgs e)
|
|
||||||
{
|
|
||||||
RegisterWindowErrorHanlder_();
|
|
||||||
|
|
||||||
var alertBlocker =
|
|
||||||
"window.print = window.alert = window.open = null;document.oncontextmenu=function(){return false;}";
|
|
||||||
_innerBrowser.InvokeScript("execScript", alertBlocker, "JavaScript");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Navigate(string uri)
|
|
||||||
{
|
|
||||||
Url = uri;
|
|
||||||
|
|
||||||
if (_innerBrowser == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(uri) && Uri.IsWellFormedUriString(uri, UriKind.Absolute))
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_innerBrowser.Source = new Uri(uri);
|
|
||||||
}
|
|
||||||
catch (UriFormatException)
|
|
||||||
{
|
|
||||||
// just don't crash because of a malformed url
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_innerBrowser.Source = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Navigate(Stream stream)
|
|
||||||
{
|
|
||||||
if (_innerBrowser == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_innerBrowser.NavigateToStream(stream);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// register script errors handler on DOM - document.window
|
|
||||||
private void RegisterWindowErrorHanlder_()
|
|
||||||
{
|
|
||||||
object parwin = ((dynamic)_innerBrowser.Document).parentWindow;
|
|
||||||
var cookie = new AxHost.ConnectionPointCookie(parwin, new HtmlWindowEvents2Impl(this),
|
|
||||||
typeof(IIntHTMLWindowEvents2));
|
|
||||||
// MemoryLEAK? No: cookie has a Finalize() to Disconnect istelf. We'll rely on that. If disconnected too early,
|
|
||||||
// though (eg. in LoadCompleted-event) scripts continue to run and can cause error messages to appear again.
|
|
||||||
// --> forget cookie and be happy.
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyZoom()
|
|
||||||
{
|
|
||||||
if (_innerBrowser == null || !_innerBrowser.IsLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// grab a handle to the underlying ActiveX object
|
|
||||||
IServiceProvider serviceProvider = null;
|
|
||||||
if (_innerBrowser.Document != null)
|
|
||||||
serviceProvider = (IServiceProvider)_innerBrowser.Document;
|
|
||||||
if (serviceProvider == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var serviceGuid = SidSWebBrowserApp;
|
|
||||||
var iid = typeof(IWebBrowser2).GUID;
|
|
||||||
var browserInst =
|
|
||||||
(IWebBrowser2)serviceProvider.QueryService(ref serviceGuid, ref iid);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
object zoomPercObj = _zoom;
|
|
||||||
// send the zoom command to the ActiveX object
|
|
||||||
browserInst.ExecWB(OLECMDID.OLECMDID_OPTICAL_ZOOM,
|
|
||||||
OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,
|
|
||||||
ref zoomPercObj,
|
|
||||||
IntPtr.Zero);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// ignore this dynamic call if it fails.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// needed to implement the Event for script errors
|
|
||||||
[Guid("3050f625-98b5-11cf-bb82-00aa00bdce0b")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
|
||||||
[TypeLibType(TypeLibTypeFlags.FHidden)]
|
|
||||||
[ComImport]
|
|
||||||
private interface IIntHTMLWindowEvents2
|
|
||||||
{
|
|
||||||
[DispId(1002)]
|
|
||||||
bool onerror(string description, string url, int line);
|
|
||||||
}
|
|
||||||
|
|
||||||
// needed to implement the Event for script errors
|
|
||||||
private class HtmlWindowEvents2Impl : IIntHTMLWindowEvents2
|
|
||||||
{
|
|
||||||
private readonly WpfWebBrowserWrapper _control;
|
|
||||||
|
|
||||||
public HtmlWindowEvents2Impl(WpfWebBrowserWrapper control)
|
|
||||||
{
|
|
||||||
_control = control;
|
|
||||||
}
|
|
||||||
|
|
||||||
// implementation of the onerror Javascript error. Return true to indicate a "Handled" state.
|
|
||||||
public bool onerror(string description, string urlString, int line)
|
|
||||||
{
|
|
||||||
Debug.WriteLine(description + "@" + urlString + ": " + line);
|
|
||||||
// Handled:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Needed to expose the WebBrowser's underlying ActiveX control for zoom functionality
|
|
||||||
[ComImport]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
|
|
||||||
internal interface IServiceProvider
|
|
||||||
{
|
|
||||||
[return: MarshalAs(UnmanagedType.IUnknown)]
|
|
||||||
object QueryService(ref Guid guidService, ref Guid riid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Web.WebView2" version="1.0.664.37" targetFramework="net462" />
|
||||||
|
</packages>
|
@@ -53,7 +53,7 @@ namespace QuickLook.Plugin.MailViewer
|
|||||||
context.ViewerContent = _panel;
|
context.ViewerContent = _panel;
|
||||||
context.Title = Path.GetFileName(path);
|
context.Title = Path.GetFileName(path);
|
||||||
|
|
||||||
_panel.Navigate(ExtractMailBody(path));
|
_panel.NavigateToFile(ExtractMailBody(path));
|
||||||
_panel.Dispatcher.Invoke(() => { context.IsBusy = false; }, DispatcherPriority.Loaded);
|
_panel.Dispatcher.Invoke(() => { context.IsBusy = false; }, DispatcherPriority.Loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -54,7 +54,7 @@ namespace QuickLook.Plugin.MarkdownViewer
|
|||||||
context.ViewerContent = _panel;
|
context.ViewerContent = _panel;
|
||||||
context.Title = Path.GetFileName(path);
|
context.Title = Path.GetFileName(path);
|
||||||
|
|
||||||
_panel.LoadHtml(GenerateMarkdownHtml(path));
|
_panel.NavigateToHtml(GenerateMarkdownHtml(path));
|
||||||
_panel.Dispatcher.Invoke(() => { context.IsBusy = false; }, DispatcherPriority.Loaded);
|
_panel.Dispatcher.Invoke(() => { context.IsBusy = false; }, DispatcherPriority.Loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user