如何防止Excel在使用SetParent嵌入时失去焦点?

问题描述 投票:0回答:1

我正在尝试将 Excel 嵌入到 WPF 应用程序中。我已经拥有了工作所需的所有内容,除了现在我试图允许 .xlsm 文件。单击 ActiveX 控件时,Excel 似乎失去焦点,并且我无法再单击工作簿中的任何内容。我仍然可以单击 Excel 应用程序 UI,例如选项卡等。有人知道如何防止这种焦点变化,或者我如何才能将其恢复?这是我当前打开 Excel 时正在执行的操作的一个小示例,如果需要,我可以提供更多信息。

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);


            if (excelApp == null) return;
            
            if (!(windowsFormsHost1.Child is Panel panel))
            {
                panel = new Panel();
                windowsFormsHost1.Child = panel;
            }

            excelHandle = new IntPtr(excelApp.Hwnd);
            SetParent(excelHandle, panel.Handle);
            SetForegroundWindow(excelHandle);
            SetFocus(excelHandle);

我没有尝试过改变太多,因为我不确定从那里该去哪里。我尝试添加代码以将 Excel 重新聚焦在计时器上,但它无法解决任何问题。我最初打开新工作簿时也遇到了这个问题,我无法单击任何单元格或任何内容,并且每次打开工作簿时都必须创建一个新的 Excel 应用程序实例。当工作簿打开时我真的无法做到这一点。

c# excel wpf interop
1个回答
0
投票

在 WPF 应用程序中嵌入 Excel 时,您似乎遇到了焦点管理问题,特别是在处理 .xlsm 文件和 ActiveX 控件时。您可以采取以下几个步骤来解决此问题:

  • 确保 Excel 应用程序可见性: 使用 SetParent 设置父窗口后,通过将其 Visible 属性设置为 true 来确保 Excel 应用程序窗口可见。

    excelApp.Visible = true;

  • 处理焦点事件:在 WPF 应用程序中实现事件处理程序,以处理与嵌入的 Excel 实例相关的焦点事件。您可以捕获焦点事件(例如 LostFocus 或 GotFocus),并采取适当的操作以确保 Excel 实例在与其交互时保留焦点。

  • 在 Excel 应用程序上设置焦点: 将 Excel 应用程序嵌入 WPF 应用程序后,尝试使用 SetForegroundWindow 函数在 Excel 应用程序窗口上显式设置焦点。您可以在使用 SetParent 设置父窗口后调用此函数,以确保 Excel 窗口保持焦点。

    [DllImport("user32.dll")] 私有静态 extern bool SetForegroundWindow(IntPtr hWnd);

    // 将焦点置于 Excel 应用程序窗口 设置前景窗口(excelHandle);

  • 验证 ActiveX 控件兼容性: 确保 Excel 工作簿中使用的 ActiveX 控件与 WPF 应用程序中的嵌入完全兼容。某些 ActiveX 控件在嵌入其他应用程序时可能存在限制或兼容性问题,因此请确保它们在您的 WPF 环境中得到完全支持。

  • 检查 Excel 应用程序设置: 检查 Excel 应用程序的设置和配置,以确保它们与 WPF 应用程序中的嵌入兼容。确保与焦点行为或交互性相关的任何设置都针对嵌入场景进行了适当配置。

通过执行这些步骤并尝试不同的方法,您也许能够解决焦点管理问题并确保与 WPF 应用程序中嵌入的 Excel 工作簿进行顺利交互。我想。

您的代码上传:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class ExcelEmbedder
{
    [DllImport("user32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll")]
    private static extern IntPtr SetFocus(IntPtr hWnd);

    private IntPtr excelHandle;

    public void EmbedExcel(Application excelApp, WindowsFormsHost windowsFormsHost)
    {
        if (excelApp == null) return;
        
        if (!(windowsFormsHost.Child is Panel panel))
        {
            panel = new Panel();
            windowsFormsHost.Child = panel;
        }

        excelHandle = new IntPtr(excelApp.Hwnd);
        SetParent(excelHandle, panel.Handle);
        SetForegroundWindow(excelHandle);
        SetFocus(excelHandle);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.