我找到了一个使用Windows的SetParent()函数在WPF中设置Excel实例的解决方案。
问题是,鼠标和键盘不会对工作表做出反应,而是对工作簿做出反应。
我也试过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中启用鼠标和键盘处理以允许编辑工作表?
*经测试:Windows 10 x64,单屏(可选双屏)Excel 2016 MSO 32位(16.0.10325.20082),不在Office 365中
此问题也在Microsoft Forum上报告,以检查是否有解决方案。
在下面的视频中,您将看到点击有时会选择单元格,有时它无法识别鼠标。
在调用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);
}