原始 KB 编号: 4490421
症状
在某些情况下,当控件托管在 CustomTaskPane 控件或 Outlook FormRegion 中时,WebBrowser 或 WPF 控件内容可能无法在 Microsoft Office 应用程序中显示或正常运行。
原因
这些问题可能是由主机应用程序未将焦点返回到控件内呈现的 HTML 元素,或者由 Microsoft Office 解决方案中的高 DPI 和 DPI 缩放导致,如处理 Microsoft Office 解决方案中的高 DPI 和 DPI 缩放一文中所述。
解决方法 1:高 DPI 和 DPI 缩放问题
将名为 的 NativeImports
类添加到代码中,如下所示,并将以下行添加到 ThisAddIn_Startup
方法:
NativeImports.SetThreadDpiHostingBehavior(NativeImports.DPI_HOSTING_BEHAVIOR.DPI_HOSTING_BEHAVIOR_MIXED);
// ThisAddIn.cs
namespace TaskPaneWorkaround
{
public partial class ThisAddIn
{
private MyUserControl myUserControl1;
private Microsoft.Office.Tools.CustomTaskPane myCustomTaskPane;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
// Workaround for the rendering issues to do with DPI
NativeImports.SetThreadDpiHostingBehavior(NativeImports.DPI_HOSTING_BEHAVIOR.DPI_HOSTING_BEHAVIOR_MIXED);
myUserControl1 = new MyUserControl();
myCustomTaskPane = this.CustomTaskPanes.Add(myUserControl1, "My Task Pane");
myCustomTaskPane.Visible = true;
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
// NativeImports.cs
namespace TaskPaneWorkaround
{
class NativeImports
{
internal enum DPI_HOSTING_BEHAVIOR
{
DPI_HOSTING_BEHAVIOR_INVALID = -1,
DPI_HOSTING_BEHAVIOR_DEFAULT = 0,
DPI_HOSTING_BEHAVIOR_MIXED = 1
};
[DllImport("user32.dll")]
internal static extern DPI_HOSTING_BEHAVIOR SetThreadDpiHostingBehavior(DPI_HOSTING_BEHAVIOR value);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
}
}
解决方法 2:主机应用程序未返回焦点的问题
在 CustomTaskPane 与实际 WebBrowser 或 WPF 控件之间添加中间窗体。
有关向应用程序添加自定义任务窗格的详细信息,请参阅 向应用程序添加自定义任务窗格。
对于 WPF 呈现问题,解决方法包括在 WindowsForm 中托管 WPF UserControl,如演练:在 Windows 窗体 中托管 3D WPF 复合控件中所述。
下面是实现此解决方法的名为 MyUserControl 的用户控件的示例:
将名为 MyUserControl的 UserControl 添加到外接程序。
修改 UserControl 的源代码,并声明 Load、Paint 和 Resize 事件处理程序,如以下示例所示。
将 Windows 窗体 添加到项目。 将其命名 为 WorkaroundForm 并声明 Load 事件处理程序。
将 WebBrowser 控件添加到 WorkaroundForm ,如以下示例所示。
创建 CustomTaskPane 并向其添加 MyUserControl 的实例。
// ThisAddIn.cs namespace TaskPaneWorkaround { public partial class ThisAddIn { private MyUserControl myUserControl1; private Microsoft.Office.Tools.CustomTaskPane myCustomTaskPane; private void ThisAddIn_Startup(object sender, System.EventArgs e) { myUserControl1 = new MyUserControl(); myCustomTaskPane = this.CustomTaskPanes.Add(myUserControl1, "My Task Pane"); myCustomTaskPane.Visible = true; } private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { } #region VSTO generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InternalStartup() { this.Startup += new System.EventHandler(ThisAddIn_Startup); this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown); } #endregion } } // MyUserControl.cs using System; using System.Windows.Forms; using System.Runtime.InteropServices; namespace TaskPaneWorkaround { public partial class MyUserControl : UserControl { bool isformdisplayed = false; WorkaroundForm workaroundForm; [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); public MyUserControl() { this.SuspendLayout(); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Name = "MyUserControl"; this.Paint += new System.Windows.Forms.PaintEventHandler(this.MyUserControl_Paint); this.Resize += new System.EventHandler(this.MyUserControl_Resize); this.ResumeLayout(false); this.Paint += MyUserControl_Paint; this.Resize += MyUserControl_Resize; } private void MyUserControl_Load(object sender, System.EventArgs e) { this.Paint += MyUserControl_Paint; } private void MyUserControl_Paint(object sender, PaintEventArgs e) { if (!isformdisplayed) { this.SuspendLayout(); workaroundForm = new WorkaroundForm(); SetParent(workaroundForm.Handle, this.Handle); workaroundForm.Dock = DockStyle.Fill; workaroundForm.Width = Width; workaroundForm.Height = Height; workaroundForm.Show(); isformdisplayed = true; this.ResumeLayout(); } } private void MyUserControl_Resize(object sender, EventArgs e) { if (isformdisplayed) { workaroundForm.Width = this.Width; workaroundForm.Height = this.Height; } } } } //WorkaroundForm.cs using System; using System.Drawing; using System.Windows.Forms; namespace TaskPaneWorkaround { public partial class WorkaroundForm : Form { public WorkaroundForm() { this.SuspendLayout(); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(509, 602); this.Name = "Form1"; this.Text = "Form1"; this.Load += new System.EventHandler(this.WorkaroundForm_Load); this.ResumeLayout(false); } private void WorkaroundForm_Load(object sender, EventArgs e) { this.SuspendLayout(); this.Location = new Point(0, 0); this.Dock = DockStyle.Fill; this.FormBorderStyle = FormBorderStyle.None; WebBrowser webBrowser = new WebBrowser(); this.Controls.Add(webBrowser); webBrowser.Location = new Point(0, 0); webBrowser.Dock = DockStyle.Fill; this.ResumeLayout(); webBrowser.Focus(); webBrowser.Navigate(new System.Uri("https://bing.com")); } } }
更多信息
修补程序解决了大多数 WebBrowser 和 WPF 控件呈现问题。 但是,如果遇到无法正确呈现内容、焦点未返回到控件中呈现的 HTML 元素或某些组合键无法按预期工作的问题,请考虑上述解决方法。
GitHub 上提供了说明解决方法的代码示例。