winform窗体嵌入excel


        [DllImport("user32.dll")]
        public static extern int FindWindow(string strclassName, string strWindowName);

        [DllImport("user32.dll")]
        public static extern int SetParent(IntPtr hWndChild, int hWndNewParent);

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        public static extern bool SetWindowPos(
            IntPtr hWnd,             
            int hWndInsertAfter,  
            int X,                 
            int Y,                
            int cx,                 
            int cy,                 
            uint uFlags            
        );

        [DllImport("user32.dll", EntryPoint = "MoveWindow")]
        static extern bool MoveWindow(
            IntPtr Wnd,
            int X,
            int Y,
            int Width,
            int Height,
            bool Repaint
        );
 private void Form4_Load(object sender, EventArgs e)
        {           
            // Create a new Excel application
            var excel = new Excel.Application();
            var name = @"C:\Users\op\报告表.xlsx";
            excel.Workbooks.Open(name);
            // Set the visible property of the Excel application to false
            excel.Visible = false;
          //嵌入窗体
            SetParent((IntPtr)excel.Hwnd, this.Handle.ToInt32());            
            excel.Visible = true;
        }

public static extern int SetParent(IntPtr hWndChild, int hWndNewParent); excel通过这种方法嵌入到窗体,有些excel的事件失效

在将Excel(或其他应用程序)嵌入到窗体中时,可能会遇到一些事件失效的问题。这是因为当使用SetParent函数将应用程序的主窗口嵌入到另一个应用程序的窗口时,新的父窗口将接管原始窗口的某些消息和事件。这可能会导致一些应用程序的事件失效,因为它们需要原始父窗口接收消息和事件。

为避免这种情况,您可以尝试使用其他方法将Excel(或其他应用程序)嵌入到窗体中,如使用Windows  Forms的WebBrowser控件,或使用第三方控件如Awesomium或CEFSharp等。这些控件提供了自己的方法来将外部应用程序嵌入到窗体中,并提供了更好的事件处理支持。

如果您决定继续使用SetParent函数来嵌入Excel,则可以尝试使用以下方法来解决事件失效的问题:

1.  在窗体中处理所有需要Excel响应的事件,而不是在Excel自己的窗口中处理它们。您可以将这些事件路由到Excel窗口,并手动处理Excel在回调中返回的结果。

2.  使用Windows  API函数Hook和Subclass以截取Excel窗口的消息和事件。这样您就可以自己处理它们,而不是交给新的父窗口处理。

请注意,这些方法可能需要更高水平的编程技能,并且可能会产生其他问题。使用控件等第三方解决方案可能是您更好的选择。 

如何使用Windows API函数Hook和Subclass以截取Excel窗口的消息和事件

使用Windows  API函数Hook和Subclass是截取Excel窗口的消息和事件的一种方法。以下是一些实现方法:

1.  使用SetWindowsHook函数。使用SetWindowsHook函数可以将一个函数钩子(hook)附加到Excel窗口进程中的消息队列中。这个钩子函数将可以截取并处理Excel窗口的消息和事件。

以下是一个示例代码,该代码在全局钩子中安装了一个Windows消息钩子,并使用WH_CALLWNDPROC来截取Excel窗口的消息和事件:

[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SetWindowsHookEx(int idHook,
    HookProc lpfn, IntPtr hInstance, uint threadId);
[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool UnhookWindowsHookEx(IntPtr hHook);
[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern int CallNextHookEx(IntPtr hHook, int nCode,
    IntPtr wParam, IntPtr lParam);
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
public const int WH_CALLWNDPROC = 4;
public const int WM_NULL = 0x0000;
public static IntPtr hHook = IntPtr.Zero;
private void InstallHook(IntPtr hWnd)
{
    if (hWnd != IntPtr.Zero)
    {
        hHook = SetWindowsHookEx(WH_CALLWNDPROC, hookProc,
            IntPtr.Zero, AppDomain.GetCurrentThreadId());
    }
}
private void UninstallHook()
{
    if (hHook != IntPtr.Zero)
    {
        UnhookWindowsHookEx(hHook);
    }
}
private int HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode == 0 && wParam.ToInt32() == WM_NULL)
    {
        CallWndProcEventArgs eventArgs =
            (CallWndProcEventArgs)Marshal.PtrToStructure(lParam,
            typeof(CallWndProcEventArgs));
        // Handle Excel window messages and events here
        // ...
        return 0;
    }
    else
    {
        return CallNextHookEx(hHook, nCode, wParam, lParam);
    }
}

 在上面的示例中,`SetWindowsHookEx`函数安装了一个全局钩子,并将一个`HookProc`委托函数`hookProc`附加到了Excel窗口进程的消息队列中。`CallNextHookEx`函数用于将截取的消息传递到下一个钩子,或者是默认的消息处理程序。

请注意,当使用钩子函数截取窗口消息时,您需要小心,不能阻止窗口处理其自己的消息和事件,否则可能会导致Excel在响应鼠标/键盘事件和其他用户输入时出现奇怪的行为。

2.  使用SetWindowLongPtr函数。使用SetWindowLongPtr函数可以替换Excel窗口对象的窗口处理程序(WndProc)函数,以便截取并处理Excel窗口的消息和事件。

以下是一个示例代码,该代码使用SetWindowLongPtr函数替换Excel窗口对象的WndProc函数,并向新的窗口处理程序转发Excel窗口的消息和事件:

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex,
    IntPtr dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc,
    IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public delegate IntPtr WindowProcDelegate(
    IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public const int GWLP_WNDPROC = -4;
private WindowProcDelegate oldWindowProc;
private void SubclassWindow(IntPtr hWnd)
{
    if (hWnd != IntPtr.Zero)
    {
        oldWindowProc = (WindowProcDelegate)
            SetWindowLongPtr(hWnd, GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(newWindowProc));
    }
}
private void RestoreWindow(IntPtr hWnd)
{
    if (hWnd != IntPtr.Zero && oldWindowProc != null)
    {
        SetWindowLongPtr(hWnd, GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(oldWindowProc));
        oldWindowProc = null;
    }
}
private IntPtr NewWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
    switch (msg)
    {
        // Handle Excel window messages and events here
        default:
            return CallWindowProc(oldWindowProc, hWnd, msg, wParam, lParam);
    }
}

在上面的示例中,`SetWindowLongPtr`函数替换Excel窗口的WndProc函数,并使用`Marshal.GetFunctionPointerForDelegate`为新的窗口处理程序创建函数指针。`CallWindowProc`函数用于将消息转发到Excel窗口原始的WndProc函数。

使用以上两种方法之一来截取Excel窗口的消息和事件。注意,这些方法都需要更高水平的编程技能,并且可能会有其他潜在问题。使用控件等第三方解决方案可能是更好的选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值