Excel作为WPF中的嵌入框架已禁用ExcelWorksheet

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

我找到了一个使用Windows的SetParent()函数在WPF中设置Excel实例的解决方案。

问题是,鼠标和键盘不会对工作表做出反应,而是对工作簿做出反应。

完整样本Project Download here

我也试过WindowsFormsHost,但它有同样的效果。

XAML

<Window x:Class="ExcelEditor.SimpleWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ExcelEditor"
    mc:Ignorable="d" Loaded="Window_Loaded" Closing="Window_Closing"
    Title="SimpleWindow" Height="450" Width="800">
<Grid x:Name="LayoutRoot">

</Grid>

C#代码

    using System;
    using System.Windows;


namespace ExcelEditor
{
    /// <summary>
    /// Interaktionslogik für SimpleWindow.xaml
    /// </summary>
    public partial class SimpleWindow : Window
    {
        private Microsoft.Office.Interop.Excel.Application ExcelApplication;

        public SimpleWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(this); // <- testing only (no success)
            ExcelApplication = new Microsoft.Office.Interop.Excel.Application();
            ExcelApplication.DisplayAlerts = false;
            System.Windows.Interop.HwndSource hwnd = (System.Windows.Interop.HwndSource)System.Windows.Interop.HwndSource.FromVisual(this.LayoutRoot);
            var excelWnd = Microsoft.Win32.Interop.FindWindow("XLMAIN", null);
            GenerateTestData(ExcelApplication);
            var successOfParentSetup = Microsoft.Win32.Interop.SetParent(excelWnd, hwnd.Handle);
            var isMovedToLeftTop = Microsoft.Win32.Interop.MoveWindow(excelWnd, 10, 10, 800, 600, true);
            ExcelApplication.Visible = true;
        }

        private void GenerateTestData(Microsoft.Office.Interop.Excel.Application excelApplication)
        {
            var excelWorkbook = excelApplication.Workbooks.Add();
            var excelWorksheet = excelWorkbook.Worksheets[1] as Microsoft.Office.Interop.Excel.Worksheet;
            excelWorksheet.Cells[1, 1] = "Today";
            excelWorksheet.Cells[2, 1] = DateTime.Now.ToString();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (ExcelApplication != null)
            {
                ExcelApplication.ActiveWorkbook.Close();
                ExcelApplication.Visible = false;
                ExcelApplication.Quit();
                ExcelApplication = null;
            }
        }
    }
}

Api电话

    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    public static extern bool SetWindowPos(
        IntPtr hWnd,               // handle to window
        IntPtr hWndInsertAfter,    // placement-order handle
        int X,                  // horizontal position
        int Y,                  // vertical position
        int cx,                 // width
        int cy,                 // height
        uint uFlags             // window-positioning options
    );

    [DllImport("user32.dll", EntryPoint = "MoveWindow")]
    public static extern bool MoveWindow(
        IntPtr hWnd,
        int X,
        int Y,
        int nWidth,
        int nHeight,
        bool bRepaint
    );
    [DllImport("USER32.DLL", SetLastError = true)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    //Sets a window to be a child window of another window
    [DllImport("USER32.DLL", SetLastError = true)]
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

问题是,如何在Excel中启用鼠标和键盘处理以允许编辑工作表?

Excel not working propert as parent

*经测试:Windows 10 x64,单屏(可选双屏)Excel 2016 MSO 32位(16.0.10325.20082),不在Office 365中

此问题也在Microsoft Forum上报告,以检查是否有解决方案。

在下面的视频中,您将看到点击有时会选择单元格,有时它无法识别鼠标。

Excel

c# .net excel windows pinvoke
1个回答
1
投票

在调用SetParent之前,您需要确保Excel已显示一次。当然,它看起来很难看,所以你还需要以某种方式隐藏最终用户的Excel UI。例如:

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        ...
        // get excel window
        var excelWnd = Microsoft.Win32.Interop.FindWindow("XLMAIN", null);

        // move excel somewhere outside the screen (of course you should compute it, not hardcode it)
        Microsoft.Win32.Interop.MoveWindow(excelWnd, -10000, -10000, 800, 600, true);

        // show it so it's initialized properly
        ExcelApplication.Visible = true;
        GenerateTestData(ExcelApplication);

        // now call SetParent
        Microsoft.Win32.Interop.SetParent(excelWnd, hwnd.Handle);

        // move it to parent
        Microsoft.Win32.Interop.MoveWindow(excelWnd, 10, 10, 800, 600, true);
    }
© www.soinside.com 2019 - 2024. All rights reserved.