我正在开发一个Windows WPF应用程序,它使用默认的WebBrowser控件(System.Windows.Controls.WebBrowser)来嵌入网页。使用作为WPF控件基础的COM对象,我能够根据需要操作控件中加载的每个HTML文档。举个例子,这里是我用来获取COM对象句柄的代码片段:
std::vector
我在哪里使用来自Microsoft.mshtml.dll的依赖项。 在这里,我将处理程序附加到DOM元素的事件,以便能够在.NET代码中管理它们(onclick和onblur事件)。
使用该对象(HTMLDocument),我几乎可以克服WPF控件的所有限制。 当WebBrowser控件导航到PDF文档时(即响应MIME类型是application / pdf),我的问题出现了。在这种情况下,我必须假设默认的Adobe Reader插件用于显示PDF(这是我的目标机器必须表现的方式)。我仍然可以获得与以下内容一起使用的基础AcroRead ActiveX的句柄:
qsort
我在项目中添加了正确的依赖项(Interop.AcroPDFLib.dll)
但此时我不知道是否有办法注册文件上发生的鼠标事件。我所要做的就是处理PDF文档上的click事件。
当然,使用以下,不起作用。该事件不会冒泡到.NET代码级别。
public void HookInputElementForKeyboard()
{
HTMLDocument htmlDocument = (HTMLDocument)webBrowserControl.Document;
var inputElements = htmlDocument.getElementsByTagName("input");
HTMLDocumentEvents_Event documentEvents = (HTMLDocumentEvents_Event) htmlDocument;
documentEvents.onclick += documentEvents_onclick;
DeregisterAll();
foreach (var item in inputElements)
{
DispHTMLInputElement inputElement = item as DispHTMLInputElement;
if (inputElement.type == "text" || inputElement.type == "password" || inputElement.type == "search")
{
HTMLButtonElementEvents_Event htmlButtonEvent = inputElement as HTMLButtonElementEvents_Event;
this.hookedElements.Add(htmlButtonEvent);
htmlButtonEvent.onclick += InputOnClickHandler;
htmlButtonEvent.onblur += InputOnBlurHandler;
}
}
}
有人知道是否有办法挂钩IAcroAXDocShim以便处理鼠标点击事件? 任何可能的选择?我是否应该选择完全不同的道路? 直接使用AcroRead ActiveX是否比现有场景具有一些优势?
答案 0 :(得分:1)
我最后采用了不同的方法。每当识别出PDF内容时,我决定切换到不同的UserControl,而不是WPF WebBrowser。 我知道在开发Windows应用商店应用时,可以使用一些用于PDF呈现的类和API,因此我应用了一个解决方案,以便在我的WPF应用程序中使用这些类。
首先我编辑了csproj文件,将以下标记添加为<PropertyGroup>
的子标记:
<TargetPlatformVersion>8.1</TargetPlatformVersion>
然后在“添加引用”对话框窗口中出现名为“Windows 8.1”的部分。我将此部分的唯一程序集添加到引用中。为了使解决方案有效,可能还需要一些组件:
有了这些,我写了一个渲染方法,遍历PDF文件的页面并为每个页面创建一个png文件。然后我将页面添加到StackPanel。此时,您可以像往常一样在任何UIElement上管理StackPanel上的Click(或MouseDown)事件。 以下是渲染方法的简要示例:
async private void RenderPages(String pdfUrl)
{
try
{
HttpClient client = new HttpClient();
var responseStream = await client.GetInputStreamAsync(new Uri(pdfUrl));
InMemoryRandomAccessStream inMemoryStream = new InMemoryRandomAccessStream();
using (responseStream)
{
await responseStream.AsStreamForRead().CopyToAsync(inMemoryStream.AsStreamForWrite());
}
var pdf = await PdfDocument.LoadFromStreamAsync(inMemoryStream);
if (pdf != null && pdf.PageCount > 0)
{
AddPages(pdf);
}
}
catch (Exception e)
{
throw new CustomException("An exception has been thrown while rendering PDF document pages", e);
}
}
async public void AddPages(PdfDocument pdfDocument)
{
PagesStackPanel.Children.Clear();
if (pdfDocument == null || pdfDocument.PageCount == 0)
{
throw new ArgumentException("Invalid PdfDocument object");
}
var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
StorageFolder rootFolder = await StorageFolder.GetFolderFromPathAsync(path);
var storageItemToDelete = await rootFolder.TryGetItemAsync(Constants.LOCAL_TEMP_PNG_FOLDER);
if (storageItemToDelete != null)
{
await storageItemToDelete.DeleteAsync();
}
StorageFolder tempFolder = await rootFolder.CreateFolderAsync(Constants.LOCAL_TEMP_PNG_FOLDER, CreationCollisionOption.OpenIfExists);
for (uint i = 0; i < pdfDocument.PageCount; i++)
{
logger.Info("Adding PDF page nr. " + i);
try
{
await AppendPage(pdfDocument.GetPage(i), tempFolder);
}
catch (Exception e)
{
logger.Error("Error while trying to append a page: ", e);
throw new CustomException("Error while trying to append a page: ", e);
}
}
}