[转]LibreOffice-SDK 开发实战:嵌入MFC-View 和 C# Winform

简介: 转自:http://www.aqcoder.com/blog/detail/id/1579bb39-9bcd-4c0f-9b02-67a851148196/ 前面片文章中我简要介绍了下 LibreOffice SDK 的环境配置,以及 cpp 中一个例子的编译。

转自:http://www.aqcoder.com/blog/detail/id/1579bb39-9bcd-4c0f-9b02-67a851148196/

前面片文章中我简要介绍了下 LibreOffice SDK 的环境配置,以及 cpp 中一个例子的编译。 接下来我们来看一下如何将 LibreOffice 嵌入到 MFC 的 View 中和 C# 的 Winform 中。先上两张效果图: MFC View:这里写图片描述

C# Winform:这里写图片描述

MFC View

这里我主要讲解 LibreOffice 的相关部分,MFC 相关的部分就要带过,特别注意环境设置(ps: 玩MFC 的童鞋都不用多说,不要闲我啰嗦 ^_^) 1.建立一个当文档程序

2.设置头文件包含目录

C:\LibreOffice4\sdk\include
C:\LibreOffice4\sdk\includecpp

注意第二个目录是编译 cpp 例子得到的,详见http://blog.csdn.net/my___dream/article/details/45176921

3.设置库目录 C:\LibreOffice4\sdk\lib

4.添加环境变量 PATH: C:\LibreOffice4\URE\bin

5.show you the code: 包含头文件以及命名空间

#include "sal/config.h"
#include <sal/main.h> #include <rtl/ustring.hxx> #include <osl/diagnose.h> #include <cppuhelper/bootstrap.hxx> #include <com/sun/star/bridge/XUnoUrlResolver.hpp> #include <com/sun/star/registry/XSimpleRegistry.hpp> #include <com/sun/star/lang/XMultiComponentFactory.hpp> #include <com/sun/star/frame/XDesktop.hpp> #include <com/sun/star/uno/Reference.h> #include <com/sun/star/lang/XComponent.hpp> #include <com/sun/star/awt/XSystemChildFactory.hpp> #include <com/sun/star/util/URL.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/container/XNameAccess.hpp> #include <com/sun/star/container/XEnumerationAccess.hpp> #include <com/sun/star/frame/XComponentLoader.hpp> #include <com/sun/star/frame/XTitle.hpp> #include <com/sun/star/util/URL.hpp> #include <com/sun/star/util/XCloseable.hpp> #include <com/sun/star/util/XCloseListener.hpp> #include <com/sun/star/util/CloseVetoException.hpp> #include <com/sun/star/uno/RuntimeException.hpp> #include <osl/file.hxx> #include <osl/process.h> #include <rtl/ustrbuf.hxx> #include <com/sun/star/awt/XSystemChildFactory.hpp> #include <com/sun/star/awt/XDialog2.hpp> #include <com/sun/star/awt/XControlModel.hpp> #include <com/sun/star/lang/SystemDependent.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/awt/XSystemDependentWindowPeer.hpp> #include <com/sun/star/util/XURLTransformer.hpp> #include <list> using namespace cppu; using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::beans; using namespace com::sun::star::frame; using ::rtl::OUString; using ::rtl::OUStringToOString; using namespace com::sun::star; using namespace container; using namespace osl; using namespace rtl; using namespace util; using namespace awt;

在 View 中重写 OnInitialUpdate 函数,键入如下代码:

void CSDITestView::OnInitialUpdate() { CView::OnInitialUpdate(); CString strFileName = GetDocument()->GetPathName(); if (strFileName.IsEmpty()) return; using com::sun::star::lang::SystemDependent::SYSTEM_WIN32; // init XComponentContext & XMultiComponentFactory & XMultiServiceFactory Reference< XComponentContext > xContext(::cppu::bootstrap()); Reference< XMultiComponentFactory > xMultiComponetFactory = xContext->getServiceManager(); Reference<XMultiServiceFactory> xMultiServiceFactory(xMultiComponetFactory, UNO_QUERY); // create XComponentLoader Reference< XComponentLoader > xComponentLoader = Reference<XComponentLoader>( xMultiComponetFactory->createInstanceWithContext(OUString("com.sun.star.frame.Desktop"), xContext), UNO_QUERY); // create a XWindow & XFrame Adn the XWindow contain the XFrame Reference<XSystemChildFactory> xSystemChildFactory = Reference<XSystemChildFactory>( xMultiComponetFactory->createInstanceWithContext(OUString("com.sun.star.awt.Toolkit"), xContext), UNO_QUERY); Reference<XWindowPeer> xPeer = Reference<XWindowPeer>(xSystemChildFactory->createSystemChild( Any(reinterpret_cast<long>(m_hWnd)), Sequence<sal_Int8>(4), SYSTEM_WIN32), UNO_QUERY); if (xPeer.is()) { Reference<XWindow> xFrameContainerWindow = Reference<XWindow>(xPeer, UNO_QUERY); Reference<XFrame> xFrame = Reference<XFrame>(xMultiComponetFactory ->createInstanceWithContext(OUString("com.sun.star.frame.Frame"), xContext), UNO_QUERY); if (xFrameContainerWindow.is() && xFrame.is()) { xFrame->initialize(xFrameContainerWindow); Reference<XFrames> xChildContainer = Reference<XFramesSupplier>(xComponentLoader,UNO_QUERY)->getFrames(); xChildContainer->append(xFrame); xFrame->setName(OUString("myframe")); // to identify frame } Reference<XSystemDependentWindowPeer> xPeer(xFrameContainerWindow, UNO_QUERY); if(xPeer.is()) { xFrameContainerWindow->setVisible(true); long lh = 0; xPeer->getWindowHandle(Sequence<sal_Int8>(4), SYSTEM_WIN32) >>= lh; m_hPlatformContainerWindow = reinterpret_cast<HWND>(lh); } } // load component Sequence<PropertyValue> properties; properties.realloc(2); properties[0] = PropertyValue(OUString("ReadOnly"), 0, Any(false), PropertyState_DIRECT_VALUE); properties[1].Name = OUString(OUString("passwd")); properties[1].Value = Any(OUString("abc")); URL url; OUString ousUrl, ousWorkingDir, ousPathUrl; osl_getProcessWorkingDir(&ousWorkingDir.pData); osl::FileBase::getFileURLFromSystemPath(strFileName.GetBuffer(), ousPathUrl); osl::FileBase::getAbsoluteFileURL(ousWorkingDir, ousPathUrl, ousUrl); url.Complete = OUString(ousUrl); Reference<XURLTransformer> urltf = Reference<XURLTransformer>(xMultiComponetFactory ->createInstanceWithContext(OUString("com.sun.star.util.URLTransformer"), xContext), UNO_QUERY); urltf->parseStrict(url); Reference<XComponent> xComponent = xComponentLoader->loadComponentFromURL(url.Complete, OUString("myframe"),4, properties);// move windowCWnd* pWnd =CWnd::FromHandle(m_hPlatformContainerWindow);if(pWnd){CRect rect;CWnd::FromHandle(m_hWnd)->GetClientRect(&rect); pWnd->MoveWindow(rect, TRUE);}// save to close m_xComponet = xComponent; m_xDesktop =Reference<XDesktop>(xComponentLoader, UNO_QUERY);}

代码解释(按注释行解释): 1. 首先是判断有没打开文档,没有就返回,这个不需要解释了,一定要判断哦。。。

  1. // init XComponentContext & XMultiComponentFactory & XMultiServiceFactory 初始化组件上下文、组件工厂(顺带提一下,LibreOffice 需要 UNO 编程的知识, 没接触过 UNO 的童鞋看看这个 中文:https://wiki.openoffice.org/wiki/Zh/Documentation/DevGuide/OpenOffice.org_Developers_Guide) 英文:https://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide

  2. // create XComponentLoader 创建 com.sun.star.frame.Desktop 对象得到 XComponentLoader 接口

  3. // create a XWindow & XFrame Adn the XWindow contain the XFrame 这里英文注释写的不是很准确,鄙人英文不是很好就这么写了 T_T。这部分是为了得到 XWindows 接口用于承载 XFrame 后面加载的组件都在 XFrame 容器当中。 首先,创建一个 com.sun.star.awt.Toolkit 对象得到 XSystemChildFactory,调用 XSystemChildFactory.createSystemChild() 方法得到 XWindowPeer 接口,注意这个方法传入了父窗口句柄,也就是 View 的句柄。 接着,创建一个 com.sun.star.frame.Frame 对象得到 XFrame 接口,并进行初始化工作,然后得到 XFrames 接口并调用 XFrames.getFrames() 方法加入到 Frame 集合当中。 最后,设置 com.sun.star.frame.Frame 对象的名称,这个很关键,以为后面要根据名称加载组件。 最最后,得到 XSystemDependentWindowPeer 接口,调用 XSystemDependentWindowPeer.getWindowHandle() 方法得到容器的窗口句柄。

  4. // load component 加载组件,这里特别要注意 URL 对象,因为从 GetPathName() 方法得到文件路径是 Window 的路径格式(也就是反斜杠),我们要把他转化为 Unix 系统下的路径格式(也就是正斜杠,到底谁反人类了 T_T) 然后调用 XComponentLoader 接口的 XComponentLoader.loadComponentFromURL() 方法加载组件。注意第二个参数一定要和步骤 4 中设置的 com.sun.star.frame.Frame 对象的名字相同,你得告诉人家加载到那个容器里嘛~~

  5. // move window 这段代码也没什么好解释的了,就是窗口的定位。

  6. 最后几个是成员变量是为了关闭文档,注意:如果不关闭文档后面再打开程序,打开同一个文档是会挂掉,因为 UNO 对象是跨进访问的,你的程序关了 soffice.exe 和 soffice.bin 两个进程都还在,而你打开的文档信息在进程中,所以挂掉。。。 这里只是做个示例和试验,所以代码没有考虑结构和严谨性,容易出 BUG ,请不要吐槽 ->_->

所以,在析构函数中加入如下代码:

CSDITestView::~CSDITestView() { Reference< XCloseable > xClaseable = Reference< XCloseable >(m_xComponet, UNO_QUERY); xClaseable->close(false); m_xDesktop.clear(); }

以及成员变量

HWND m_hPlatformContainerWindow;
com::sun::star::uno::Reference< com::sun::star::frame::XDesktop > m_xDesktop; com::sun::star::uno::Reference< com::sun::star::lang::XComponent > m_xCompone

OK, MFC 的示例就酱完了,刚开始看 UNO 的代码可能有点累,都是模板和接口,建议先收悉一下 UNO 编程的相关知识,上面给的中文连接还有没翻译完,建议看英文的。。。英文不好的程序员不是好程序员 ->_->

C# Winform

Winform 的代码步骤是一样的: 初始化 --> 创建容器 --> 加载组件 --> 移动窗口。 1. 创建工程 2. 添加引用: \LibreOffice4\sdk\cli\ 目录下有 cli_basetypes.dll、cli_cppuhelper.dll、cli_oootypes.dll、cli_ure.dll、cli_uretypes.dll 5 个程序集,都引用上 3. 上代码:

[DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)] public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRePaint); public Form1() { InitializeComponent(); m_xContext = uno.util.Bootstrap.bootstrap(); mxMSFactory = (XMultiServiceFactory)m_xContext.getServiceManager(); XComponentLoader aLoader = (XComponentLoader) mxMSFactory.createInstance("com.sun.star.frame.Desktop"); XSystemChildFactory xSystemChildFactory = (XSystemChildFactory)mxMSFactory.createInstance("com.sun.star.awt.Toolkit"); XWindowPeer xWindowPeer = xSystemChildFactory.createSystemChild(new Any(this.Handle.ToInt32()), new byte[4], 1); XWindow xWindow = (XWindow)xWindowPeer; XFrame xFrame = (XFrame)mxMSFactory.createInstance("com.sun.star.frame.Frame"); xFrame.initialize(xWindow); XFramesSupplier xFrameSupplier = (XFramesSupplier)aLoader; xFrameSupplier.getFrames().append(xFrame); xFrame.setName("myframe"); XSystemDependentWindowPeer xSDWindowPeer = (XSystemDependentWindowPeer)xWindow; xWindow.setVisible(true); object hHandle = xSDWindowPeer.getWindowHandle(new byte[4], 1).Value; XComponent xComponent = aLoader.loadComponentFromURL("file:///C:/test.odt", "myframe", 4, new unoidl.com.sun.star.beans.PropertyValue[0]); MoveWindow(new IntPtr((int)hHandle), 0, 0, this.Width, this.Height, true); }

这个实例在主窗口初始化的时候就加载了,所以加载的文档是写死的,注意是正斜杠哦。。。 代码基本和 C++ 的一样就不解释了,提一下就是 MoveWindows() 用到了 Win32API 不知道 C# 如何调用 Win32API 的童鞋自己 Google 吧 ^_^ 好了,我也刚开始学 LO,这种方法还没在实际项目中验证,如有错漏之处还请大神请教,共勉。。。

相关文章
|
2月前
|
数据采集 JavaScript C#
C#图像爬虫实战:从Walmart网站下载图片
C#图像爬虫实战:从Walmart网站下载图片
|
15天前
|
前端开发 JavaScript 安全
C#一分钟浅谈:Blazor WebAssembly 开发
Blazor WebAssembly 是一个客户端框架,允许开发者使用C#和Razor语法构建Web应用。本文介绍了Blazor WebAssembly的基本概念、常见问题及解决方案,包括路由配置、数据绑定、异步操作、状态管理和性能优化等方面的内容,并分享了一些易错点及如何避免的方法。希望这些内容能帮助你在Blazor WebAssembly开发中少走弯路,提高开发效率。
88 51
|
12天前
|
开发框架 缓存 .NET
C# 一分钟浅谈:Blazor Server 端开发
Blazor Server 是基于 ASP.NET Core 的框架,允许使用 C# 和 Razor 语法构建交互式 Web 应用。本文介绍 Blazor Server 的基本概念、快速入门、常见问题及解决方案,帮助开发者快速上手。涵盖创建应用、基本组件、数据绑定、状态管理、跨组件通信、错误处理和性能优化等内容。
26 1
|
13天前
|
缓存 C# 开发者
C# 一分钟浅谈:Blazor Server 端开发
本文介绍了 Blazor Server,一种基于 .NET 的 Web 开发模型,允许使用 C# 和 Razor 语法构建交互式 Web 应用。文章从基础概念、创建应用、常见问题及解决方案、易错点及避免方法等方面详细讲解,帮助开发者快速上手并提高开发效率。
36 2
|
23天前
|
测试技术 Go C#
C#一分钟浅谈:ReSharper 插件增强开发效率
【10月更文挑战第25天】ReSharper 是 JetBrains 开发的一款 Visual Studio 插件,旨在提高 .NET 开发者的生产力。它通过代码分析、重构、导航等功能,帮助开发者避免常见错误,提升代码质量和开发效率。本文将通过具体代码案例,详细介绍 ReSharper 的常见功能及其应用。
37 1
|
28天前
|
C# Python
使用wxpython开发跨平台桌面应用,对wxpython控件实现类似C#扩展函数处理的探究
【10月更文挑战第30天】使用 `wxPython` 开发跨平台桌面应用时,可以通过创建辅助类来模拟 C# 扩展函数的功能。具体步骤包括:1. 创建辅助类 `WxWidgetHelpers`;2. 在该类中定义静态方法,如 `set_button_color`;3. 在应用中调用这些方法。这种方法提高了代码的可读性和可维护性,无需修改 `wxPython` 库即可为控件添加自定义功能。但需要注意显式调用方法和避免命名冲突。
|
1月前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
36 1
|
2月前
|
SQL API 定位技术
基于C#使用winform技术的游戏平台的实现【C#课程设计】
本文介绍了基于C#使用WinForms技术开发的游戏平台项目,包括项目结构、运行截图、实现功能、部分代码说明、数据库设计和完整代码资源。项目涵盖了登录注册、个人信息修改、游戏商城列表查看、游戏管理、用户信息管理、数据分析等功能。代码示例包括ListView和ImageList的使用、图片上传、图表插件使用和SQL工具类封装,以及高德地图天气API的调用。
基于C#使用winform技术的游戏平台的实现【C#课程设计】
|
1月前
|
开发框架 NoSQL MongoDB
C#/.NET/.NET Core开发实战教程集合
C#/.NET/.NET Core开发实战教程集合
|
1月前
|
设计模式 程序员 C#
C# 使用 WinForm MDI 模式管理多个子窗体程序的详细步骤
WinForm MDI 模式就像是有超能力一般,让多个子窗体井然有序地排列在一个主窗体之下,既美观又实用。不过,也要小心管理好子窗体们的生命周期哦,否则一不小心就会出现一些意想不到的小bug
109 0
下一篇
无影云桌面