Compartir a través de


El control WebBrowser o WPF no muestra el contenido correctamente en una aplicación de Office cuando se hospeda dentro de un control CustomTaskPane.

Número de KB original: 4490421

Síntomas

En algunas situaciones, es posible que el contenido del control WebBrowser o WPF no se muestre o funcione correctamente en una aplicación de Microsoft Office cuando el control se hospeda dentro de un control CustomTaskPane o Outlook FormRegion.

Causa

Estos problemas pueden deberse a que la aplicación host no devuelve el foco a los elementos HTML representados dentro de los controles o por el escalado elevado de PPP y PPP en las soluciones de Microsoft Office, como se indica en el artículo Controlar el escalado alto de PPP y PPP dentro de la solución de Microsoft Office.

Solución alternativa 1: Problema con el alto escalado de PPP y PPP

Agregue una clase denominada NativeImports al código, como se muestra a continuación, y agregue la siguiente línea al ThisAddIn_Startup método :

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);
    }

}

Solución alternativa 2: Problema con la aplicación host que no devuelve el foco

Agregue un formulario intermedio entre CustomTaskPane y el control WebBrowser o WPF real.

Para obtener más información sobre cómo agregar un panel de tareas personalizado a una aplicación, vea Agregar un panel de tareas personalizado a una aplicación.

En el caso de los problemas de representación de WPF, la solución consiste en hospedar un control UserControl de WPF dentro de un WindowsForm, tal como se describe en Tutorial: Hospedar un control compuesto de WPF 3D en Windows Forms.

Este es un ejemplo de un control de usuario denominado MyUserControl que implementa esta solución alternativa:

  1. Agregue un UserControl al complemento, denominado MyUserControl.

  2. Modifique el código fuente de UserControl y declare los controladores de eventos Load, Paint y Resize, como se indica en el ejemplo siguiente.

  3. Agregue un formulario de WindowsForm al proyecto. Asígnele el nombre WorkaroundForm y declare el controlador de eventos Load.

  4. Agregue el control WebBrowser a WorkaroundForm como se indica en el ejemplo siguiente.

  5. Cree un objeto CustomTaskPane y agréguele una instancia de 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"));
            }
    
        }
    }
    

Más información

La mayoría de los problemas de representación de controles WebBrowser y WPF se han solucionado mediante revisiones. Sin embargo, si se produce algún problema en el que el contenido no se representa correctamente, el foco no se devuelve a los elementos HTML representados dentro del control o ciertas combinaciones de teclas no funcionan según lo esperado, tenga en cuenta las soluciones alternativas mencionadas anteriormente.

Hay disponible un ejemplo de código que ilustra las soluciones alternativas en GitHub.