Reputation: 4036
For a WPF WebBrowser control, is there a way to duplicate Internet Explorer's zoom functionality?
In other words, Internet Explorer has the menu View > Zoom > 75%, which renders the web page at 75% scale. Is there a way to make a web browser control, which is embedded in a WPF app, do the same thing?
I've seen this post: WPF WebBrowser - How to Zoom Content?
But it only seems to scale the page and not the page content.
Upvotes: 8
Views: 12457
Reputation: 183
Here's how I did it:
// 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);
}
static readonly Guid SID_SWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
private void ZoomListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
object zoomPercent; // A VT_I4 percentage ranging from 10% to 1000%
switch(ZoomListBox.SelectedItem.ToString())
{
case "System.Windows.Controls.ListBoxItem: 200%":
zoomPercent = 200;
break;
case "System.Windows.Controls.ListBoxItem: 100%":
zoomPercent = 100;
break;
case "System.Windows.Controls.ListBoxItem: 50%":
zoomPercent = 50;
break;
default:
zoomPercent = 100;
break;
}
// grab a handle to the underlying ActiveX object
IServiceProvider serviceProvider = null;
if (m_webView.Document != null)
{
serviceProvider = (IServiceProvider)m_webView.Document;
}
Guid serviceGuid = SID_SWebBrowserApp;
Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;
SHDocVw.IWebBrowser2 browserInst = (SHDocVw.IWebBrowser2)serviceProvider.QueryService(ref serviceGuid, ref iid);
// send the zoom command to the ActiveX object
browserInst.ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref zoomPercent, IntPtr.Zero);
}
All the service provider stuff exposes the ActiveX since the WPF WebBrowser control doesn't expose it directly. Aside from that, it's pretty much the same as alexei's solution.
Upvotes: 4
Reputation: 71
public partial class TestWindow: UserControl
{
public TestWindow()
{
InitializeComponent();
browser.LoadCompleted += new LoadCompletedEventHandler(browser_LoadCompleted);
}
private void browser_LoadCompleted(object sender, NavigationEventArgs e)
{
try
{
FieldInfo webBrowserInfo = browser.GetType().GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic);
object comWebBrowser = null;
object zoomPercent = 120;
if (webBrowserInfo != null)
comWebBrowser = webBrowserInfo.GetValue(browser);
if (comWebBrowser != null)
{
InternetExplorer ie = (InternetExplorer)comWebBrowser;
ie.ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref zoomPercent, IntPtr.Zero);
}
}
catch (Exception ex)
{
}
}
public void SetBrowser(string url)
{
browser.Navigate(url,null,null,null);
}
internal void Destroy()
{
try
{
if (browser.Parent != null)
{
((Grid)browser.Parent).Children.Remove(browser);
browser.Navigate("about:blank");
browser.Dispose();
browser = null;
}
}
catch { }
}
}
Upvotes: 7
Reputation: 40736
When using the other solutions, I always get errors of kind
HRESULT: 0x80040100
DRAGDROP_E_NOTREGISTERED
I found a solution on this page that worked for me:
var wb = webBrowser.ActiveXInstance.GetType();
object o = zoomPercentage; // Between 10 and 1000.
wb.InvokeMember(
@"ExecWB",
BindingFlags.InvokeMethod,
null,
webBrowser.ActiveXInstance,
new[]
{
OLECMDID.OLECMDID_OPTICAL_ZOOM,
OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,
o,
o
});
With OLECMDID_OPTICAL_ZOOM
being 63 and OLECMDEXECOPT_DONTPROMPTUSER
being 2.
Upvotes: 0
Reputation: 2291
This is not an exact answer since it is for the WinForms control, but perhaps will be useful in case you decide to use it in a WindowsFormsHost instead of the WPF control, which exposes way too little to be useful.
You could use an OLE commands through ExecWB on the ActiveX instance: OLECMDID_ZOOM
for text size and OLECMDID_OPTICAL_ZOOM
for optical zoom. For example,
object pvaIn = 200; // A VT_I4 percentage ranging from 10% to 1000%
var browserInst = ((SHDocVw.IWebBrowser2)(browserContol.ActiveXInstance));
browserInst.ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM,
SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,
ref pvaIn, IntPtr.Zero);
Some notes:
OLECMDID_GETZOOMRANGE
Upvotes: 2