I found a solution to setup Excel instance in WPF by using the SetParent() function of Windows.
Problem is, that mouse and keyboard is not reacting to the sheet but to the Workbook it does.
Full sample Project Download here
I also tried with WindowsFormsHost but it has the same effect.
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# code
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 calls
[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);
Question is, how to enable the mouse and keyboard handling in Excel to allow editing the worksheet?
*Tested at: Windows 10 x64, Single screen (optional dual screen) Excel 2016 MSO 32-Bit (16.0.10325.20082) out of Office 365
1 Answers
Answers 1
You need to make sure Excel has been shown once before you can call SetParent
. Of course, it looks ugly, so you also need to hide Excel UI somehow from the end-user. For example:
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); }
0 comments:
Post a Comment