将Excel嵌入你的.Net程序-使用dsoFramer (转载)

简介:
 

   使用AxWebBrowser或者WebBrowser的方法将Office嵌入我们的.Net系统问题有几个,1是WebBrowser控件是一个比较重的控件,2是通过WebBrowser去控制Office如果出现问题没有办法进行调试与判断,也无法修改,3是Office对应的菜单没有办法控制。为此我们决定需求新的解决方案,使用微软提供的dsoFramer控件例子,这个例子使用VC++编写,本身是可以使用的,可以参见:

   http://support.microsoft.com/default.aspx?scid=kb;en-us;311765

在这里下载dsoFramer的源码

http://www.microsoft.com/downloads/details.aspx?familyid=CE2CA4FD-2169-4FAC-82AF-770AA9B60D77&displaylang=en

下面进行我们的改造过程

1.使用VisualStudio2005打开该VC工程,按系统提示进行转换

2.转换完成后,发现该控件缺少OLB文件,这个文件是控件的对象库,在引用该控件的时候要用到,编译该对象库需要mktyplib.exe但该工具在VS2005中已经不再提供,使用MIDL代替,但MIDL又不支持这种转换过来的工程,没想到第一步就遇到了挫折,为此想了很多办法,后来从VS2003中找到旧的mktyplib.exe,拷入VS2005\common\tools\bin下面,呵呵可以了,(这个应该算VS2005的一个Bug吧)

3.编译好ocx,通过Regsvr32 注册到系统中

4.创建一个C#工程,引入刚才的ocx

5.发现该控件,自带了菜单,工具栏,并且我们基本不能控制该控件,晕倒

6.决定自己将它的菜单栏放到我们的.Net  Form上,发现不能将 C++的菜单直接放过来,C++的有太多的控制了,如果要重写这些控制,就要吐血了,并且发现新的MenuStrip控件根本就不是一个菜单,传入C++后,不认识。费了好大的劲,将Form的MainMenu给传了进去,呵呵,这下行了,看看运行的效果:

怎么样,感觉还不错吧,现在这个Excel就可以好好的控制了,最主要的是, 如果你想增加什么新的东西,出现什么问题就可以自己调试解决了。

如果你要在OCX中增加接口,你必须同时修改三个地方,一个是ODL,OCX的接口定义文件,并且按照规范,一个是你的控件实现的对应的.H文件,一个实现的.CPP文件,这些都简单了。

6.菜单出来了,发现不能控制,又再次晕倒,不知所措了

解决办法,是通过OVerride窗体的WndProc方法,将菜单的事件,除了你自己的菜单以外的,都给传到OCX中。

在OCX中增加一个接口方法:ExecuteMenuMessage,它直接调用OnMenuMessage,呵呵,这样就行了,代码如下:

        protected override void WndProc(ref Message m)
        {
            IntPtr  lWParam=IntPtr.Zero  ;
            switch (m.Msg)
            {
                case WindowsMessages.WM_INITMENU :
                case WindowsMessages.WM_ENTERIDLE:
                case WindowsMessages.WM_MENUSELECT:
                case WindowsMessages.WM_INITMENUPOPUP:
                case WindowsMessages.WM_COMMAND :                 
                    ExecuteMenuMessage(m.Msg, m.WParam, m.LParam);
                    //Console.Write(m.Msg.ToString("X"));
                    //Console.Write("    ");
                    //Console.Write(lWParam.ToString("X"));
                    //Console.Write("    ");
                    //Console.WriteLine(m.LParam.ToString("X"));
                    break;               
            }
       
             base.WndProc(ref m);      
        }

   现在菜单信息也传入了,哦,创建菜单的程序如下,酷吧:

   private void Form1_Load(object sender, EventArgs e)
        {
            //if (this.Menu == null)
            {
                this.Menu = new MainMenu();
                CreateFileMenu();
                IntPtr hMainMenu = this.Menu.Handle;
                this.axFramerControl1.MainFormMenu = hMainMenu;
                this.axFramerControl1.MainForm = this.Handle;
            }
        } 
       
     

        private void CreateFileMenu()
        {
            IntPtr pFileMenu = MenuHelper.CreatePopupMenu();
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_NEW, "新建(&N)...\tCtrl+N");
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_OPEN, "打开(&O)...\tCtrl+O");
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_CLOSE, "关闭(&C)");
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_SEPARATOR, 0, string.Empty);
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_SAVE, "保存(&S)\tCtrl+S");
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_SAVEAS, "另存为(&A)...");
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_SEPARATOR, 0, string.Empty);
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_PGSETUP, "页面设置(&U)...");
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_PRINTPV, "打印预览(&V)");
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_PRINT, "打印(&P)...");
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_SEPARATOR, 0, string.Empty);
            MenuHelper.AppendMenu(pFileMenu, MenuFlags.MF_STRING, FrameMenuMessage.MNU_PROPS, "属性(&I)");

            MenuHelper.AppendMenu(this.Menu.Handle, MenuFlags.MF_BYPOSITION | MenuFlags.MF_POPUP, (uint)pFileMenu.ToInt32() , "文件(&F)");
            MenuHelper.DrawMenuBar(this.Handle);
        }

7.当关闭Excel后会怎么样,靠,菜单还在,并且每个都报错,肯定报错,OLE已经卸载了,只好跑去修改OCX控件中docObject的ClearMergeMenu,让它清除掉Excel的菜单,明白原理就简单了。

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::ClearMergedMenu (protected)
//
//  Frees the merged menu set by host.
//
STDMETHODIMP_(void) CDsoDocObject::ClearMergedMenu()

 if (m_hMenuMerged)
 {
        int cbMenuCnt = GetMenuItemCount(m_hMenuMerged);
  int iMainMenuCnt=0;
  if(this->m_hMenuMainForm)
   iMainMenuCnt=GetMenuItemCount(m_hMenuMainForm);

  for (int i = cbMenuCnt-1; i >0; --i)
  {
   if(this->m_hMenuMainForm)
   {
    RemoveMenu(m_hMenuMainForm,--iMainMenuCnt,MF_BYPOSITION);
   }
   RemoveMenu(m_hMenuMerged, i, MF_BYPOSITION);
  }
  if(m_hwndMainForm)
   DrawMenuBar(m_hwndMainForm);

  DestroyMenu(m_hMenuMerged);
  m_hMenuMerged = NULL;
 }
}

版权说明

  如果标题未标有<转载、转>等字则属于作者原创,欢迎转载,其版权归作者和博客园共有。
  作      者:温景良
  文章出处:http://wenjl520.cnblogs.com/  或  http://www.cnblogs.com/

分类: WinForm
0
0
« 上一篇: AE获得鼠标选择的图层信息
» 下一篇: 将Exce嵌入你的.Net程序1(转载)
posted @ 2008-12-25 17:09 温景良(Jason) Views( 1354) Comments( 3) Edit 收藏

  
#1楼 2009-02-09 23:16 | 张亚  
好东西,留下一个脚印,以后会用得着!

  
#2楼 2011-07-23 11:00 | 老WH虎  
好东西,正好需要

  
#3楼 2014-02-22 23:56 | NewSea  
mark

相关文章
|
3月前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
167 13
|
10月前
|
XML 开发框架 .NET
LabVIEW中加载.NET 2.0,3.0和3.5程序集
LabVIEW中加载.NET 2.0,3.0和3.5程序集
212 4
|
6月前
|
Ubuntu 持续交付 API
如何使用 dotnet pack 打包 .NET 跨平台程序集?
`dotnet pack` 是 .NET Core 的 NuGet 包打包工具,用于将代码打包成 NuGet 包。通过命令 `dotnet pack` 可生成 `.nupkg` 文件。使用 `--include-symbols` 和 `--include-source` 选项可分别创建包含调试符号和源文件的包。默认情况下,`dotnet pack` 会先构建项目,可通过 `--no-build` 跳过构建。此外,还可以使用 `--output` 指定输出目录、`-c` 设置配置等。示例展示了创建类库项目并打包的过程。更多详情及命令选项,请参考官方文档。
358 11
|
5月前
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
230 0
|
6月前
|
存储 运维
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
|
6月前
|
自然语言处理 C# 图形学
使用dnSpyEx对.NET Core程序集进行反编译、编辑和调试
使用dnSpyEx对.NET Core程序集进行反编译、编辑和调试
|
8月前
|
Linux C# iOS开发
如何用 WinDbg 调试Linux上的 .NET程序
【7月更文挑战第13天】 1. `dotnet-dump`: Collects process dumps with `dotnet-dump collect -p &lt;process_id&gt;`. 2. `lldb`: Debugs Mono runtime apps on macOS/Linux. 3. **Visual Studio Code**: Remotely debugs .NET via the C# extension. 4. **JetBrains Rider**: Supports remote debugging of .NET on Linux.
|
7月前
|
开发框架 .NET API
分享一个 ASP.NET Web Api 上传和读取 Excel的方案
分享一个 ASP.NET Web Api 上传和读取 Excel的方案
179 0
|
7月前
|
开发框架 NoSQL .NET
使用 Asp.net core webapi 集成配置系统,提高程序的灵活和可维护性
使用 Asp.net core webapi 集成配置系统,提高程序的灵活和可维护性
103 0
|
8月前
|
存储 对象存储 Python
`openpyxl`是一个用于读写Excel 2010 xlsx/xlsm/xltx/xltm文件的Python库。它不需要Microsoft Excel,也不需要.NET或COM组件。
`openpyxl`是一个用于读写Excel 2010 xlsx/xlsm/xltx/xltm文件的Python库。它不需要Microsoft Excel,也不需要.NET或COM组件。

热门文章

最新文章