转自: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,这种方法还没在实际项目中验证,如有错漏之处还请大神请教,共勉。。。

[转]LibreOffice-SDK 开发实战:嵌入MFC-View 和 C# Winform的更多相关文章

  1. 【转】测试LibreOffice SDK 开发环境配置(Windows)

    原文:http://www.aqcoder.com/blog/detail/id/7441186b-93fd-482c-b4d7-0facd1ee498d 下载与安装 LibreOffice 主页:h ...

  2. 第15.25节 PyQt(Python+Qt)入门学习:Model/View开发实战--使用QTableView展示Excel文件内容

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 在前面的订阅专栏<第十九章.Model/View开发:QTableView的功能及属 ...

  3. Hybrid App开发实战

    Hybrid App开发实战 作者 李秉骏 发布于 九月 04, 2013 | [引言]近年来随着移动设备类型的变多,操作系统的变多,用户需求的增加,对于每个项目启动前,大家都会考虑到的成本,团队成员 ...

  4. Visual Studio跨平台开发实战(1) - Hello Xamarin!

    原文 Visual Studio跨平台开发实战(1) - Hello Xamarin! 前言 应用程式发展的脚步, 从来没有停过. 从早期的Windows 应用程式, 到网路时代的web 应用程式, ...

  5. 《Android Studio开发实战 从零基础到App上线》资源下载和内容勘误

    转载于:https://blog.csdn.net/aqi00/article/details/73065392 资源下载 下面是<Android Studio开发实战 从零基础到App上线&g ...

  6. 《iOS 7 应用开发实战详解》

    <iOS 7 应用开发实战详解> 基本信息 作者: 朱元波    管蕾 出版社:人民邮电出版社 ISBN:9787115343697 上架时间:2014-4-25 出版日期:2014 年5 ...

  7. 我的 Android 开发实战经验总结

    我的 Android 开发实战经验总结 字数4440 阅读5137 评论43 喜欢250 曾经一直想写一篇总结 Android 开发经验的文章,预计当时的我还达不到某种水平,所以思路跟不上,下笔又捉襟 ...

  8. 聚合数据 iOS 项目开发实战:条码查询器

    记录下,聚合数据 iOS 项目开发实战:条码查询器:视频地址:http://www.jikexueyuan.com/course/324.html 条码查询API:https://www.juhe.c ...

  9. iPhone与iPad开发实战读书笔记

    iPhone开发一些读书笔记 手机应用分类1.教育工具2.生活工具3.社交应用4.定位工具5.游戏6.报纸和杂志的阅读器7.移动办公应用8.财经工具9.手机购物应用10.风景区相关应用11.旅游相关的 ...

随机推荐

  1. VC++ 解决在鼠标移动时,光标闪烁的问题。其实本质是 ON_SETCURSOR的用法

    在调用Windows API函数SetCursor设置光标时,可能会碰到闪烁的问题:移动鼠标,光标在Class Cursor(即注册窗口类时指定的Cursor)与预设Cursor之间闪烁. 在MSDN ...

  2. Arcgis Server发布服务

    提到Arcgis Server 服务的发布,做起来貌似很简单,就算电脑再卡,只要鼠标还能点,一个小时肯定能搞定,但是当你遇到问题的时候,就头大了,也许搞上个一两天都摸不着头脑,最后你采取的措施可能是一 ...

  3. UGUI代码分析

    1.canvas,screen模式和world模式区别:screen的绑定摄像机与canvas相对位置不会改变不可改变canvas,world模式下有个event camera相对位置可改变,canv ...

  4. C++函数CString类常用函数

    C++ STL库里有很多与字符串操作相关的函数,熟练应用STL,字符串的处理将变得轻松.自在. 字符串截取函数: 1.CString Left( int nCount ) const;    //从左 ...

  5. Web开发必知的八种隔离级别

    ACID性质是数据库理论中的奠基石,它定义了一个理论上可靠数据库所必须具备的四个性质:原子性,一致性,隔离性和持久性.虽然这四个性质都很重要,但是隔离性最为灵活.大部分数据库都提供了一些可供选择的隔离 ...

  6. MFC对话框中显示BMP,JPG图片

    //************************************ // 方法说明:    显示JPG和GIF.BMP图片 // 参数说明:    CDC * pDC           设 ...

  7. Redis 缓存 + Spring 的集成示例

    参考网址:http://blog.csdn.net/defonds/article/details/48716161

  8. AJAX同步改异步

    var temp; $.ajax({ async: false, type : "POST", url : defaultPostData.url, dataType : 'jso ...

  9. 纯JS实现中国行政区域上下联动选择地址

    一.实现目的: 如标题所述,通过JS来实现地址的选取,上一篇博客介绍的方式是通过java读取txt资源文件来实现地址的选择,通过ajax方式访问服务器实现省市区联动.此篇中将介绍如何使用JS实现相同功 ...

  10. django单元测试

        django 单元测试小结 django 测试 从前很少写单元测试了,特别是web应用.最近不知不觉喜欢起来这个事情了,发现单元测试对于软件的模块,正交性有很大促进作用,因为函数,模块写的不合 ...