前面我们已经编译了一个附带的例子,但是怎么编写自己的工程呢?
现在最主要的问题就是头文件缺少,并且需要设置好编译器选项。这是个麻烦的事情,不过幸好有互联网,网上有人已经处理过这个问题了!
大家可以到http://www.codeproject.com/KB/wtl/Wtl_OOo.aspx这是一个牛人自制的图片查看器,使用了OpenOffice SDK并且采用了C++和VisualStudio的开发环境。而且,他为了方便,简化了建立工程的步骤。下面我就逐一说明,怎么使用他提供的工程以及怎么建立自己的工程。(如果你有任何不清楚的地方,都可以到这个网页来查看,里面的介绍很详细)
使用他提供的工程
1.打开http://www.codeproject.com/KB/wtl/Wtl_OOo/OOo.zip 并下载,然后将之解压到你的OpenOffice SDK 路径下。
2.运行OOoCpp.js这个刚解压出来的脚本。这个脚本会在你的SDK路径下创建一个名为includecpp的文件夹,并且为自动调用sdk下的cppumaker工具生成所有的头文件。这个脚本可以说是做了大量的粗重杂活。如果你想了解脚本的具体内容,可以到前面我提到的那个网页链接自己看看,里面有详细介绍。
3.运行完这个脚本后,在你sdk目录下会有一个OOo.vsprops文件已经准备好了。这个.vsprops文件就是一个vs工程的属性文件,里面定义了一些工程的设置包括编译器啊,连接器啊,等等。可能平时大家都是自己在工程里点右键,然后选属性之后进行设置,现在有了这个文件,你就可以很方便地设置一个工程的属性了。
以后你每次想要编写OpenOffice的工程,就需要将这个OOo.vsprops文件拷到你的工程目录下,然后在你工程属性页面的General选项卡的Inherited Project Property Sheets这一栏填入 ./OOo.vsprops 这样的话该文件的设置都能自动继承到你的工程里了,你不用设置任何东西,是不是很方便呢?
其实你可以打开这个.vsprops文件看看究竟,这个文件其实只是定义了一些附加include路径,附加静态库路径,以及定义了延迟加载几个必须的动态链接库文件。
4.打开http://www.codeproject.com/KB/wtl/Wtl_OOo/WtlOOo.zip 并下载工程,然后解压到你自己喜欢的路径。
5.将刚才sdk路径下的那个OOo.vsprops文件拷到这个工程路径下覆盖原来的文件。
6.打开工程,编译链接,运行。应该就能够成功了。
下面我介绍如何自己建立工程。
1.新建一个w32 console工程,选择建立一个空的工程。
2.将OOo.vsprops文件拷到你的工程目录下,记住这个文件非常重要,必须得有。
3.在工程的属性面板的General那一栏(Debugging的上面)的Inherited Project Property Sheets栏填入./OOo.vsprops 这样就能从该文件继承所有的工程设置了,其他的设置都完全不用改。
4.新建一个main.cpp文件
5.打开http://www.codeproject.com/KB/wtl/Wtl_OOo/atlOOo.zip 下载atlOOo.h头文件,并将里面的第一个函数FindInstallAndSetPath()的定义拷到你的main.cpp里面。 这个函数非常重要,它到注册表里面去寻找你的OpenOffice的安装路径,并且设置好环境变量,使得使用OpenOffice SDK时所必须的一些动态链接库能够被找到。
6.在你的main函数定义里面首先调用这个FindInstallAndSetPath(),然后再做其他的事情。
7.请注意作者的版权声明,拷代码的时候不要忘了哦。
下面我发一段完整的代码,这个例子将一系列等差数以此输入到一个电子表格里,并且计算了他们的和,然后将其用红色字符表示出来,并将电子表格保存。
#include <windows.h> #include <cppuhelper/bootstrap.hxx> #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/lang/XMultiComponentFactory.hpp> #include <com/sun/star/frame/XComponentLoader.hpp> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/util/Color.hpp> #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> #include <com/sun/star/sheet/XSpreadsheet.hpp> #include <com/sun/star/container/XIndexAccess.hpp> #include <com/sun/star/container/XNameAccess.hpp> #include <com/sun/star/container/XNamed.hpp> #include <com/sun/star/frame/XStorable.hpp> 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 namespace com::sun::star::sheet; using namespace com::sun::star::container; using namespace com::sun::star::table; using namespace com::sun::star::util; using namespace rtl; using namespace cppu; inline LRESULT FindInstallAndSetPath() { // OpenOffice.org 3 installation key static LPCWSTR sSubKey = L"SOFTWARE//OpenOffice.org//Layers//URE//1"; HKEY hk = NULL; // check for machine install LRESULT lRes = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, sSubKey, 0, KEY_READ, &hk); // check for user install if (lRes != ERROR_SUCCESS) if (::RegOpenCurrentUser(KEY_READ, &hk) == ERROR_SUCCESS) lRes = ::RegOpenKeyEx(hk, sSubKey, 0, KEY_READ, &hk); if (lRes != ERROR_SUCCESS) return lRes; // Allocate new PATH environment variable PVOID pNewPath = calloc(MAX_PATH, sizeof(WCHAR)); if (!pNewPath) return GetLastError(); // Get the UREINSTALLLOCATION directory DWORD dwsize = MAX_PATH; PWCHAR sNewPath = (PWCHAR)pNewPath; if (lRes = RegQueryValueEx(hk, L"UREINSTALLLOCATION", NULL, NULL, (LPBYTE)sNewPath, &dwsize) == ERROR_SUCCESS) lRes = wcsncat_s(sNewPath + wcslen(sNewPath), MAX_PATH - wcslen(sNewPath), L"bin;", 4); RegCloseKey(hk); // Return if no UREINSTALLLOCATION directory if (lRes != ERROR_SUCCESS) { free(pNewPath); return lRes; } // Get the old PATH environment variable size_t sizeOldPath; lRes = _wgetenv_s(&sizeOldPath, NULL, 0, L"PATH"); LPWSTR sOldPath = (PWCHAR)malloc(sizeOldPath * sizeof(WCHAR)); if (sOldPath && SUCCEEDED(lRes)) lRes = _wgetenv_s(&sizeOldPath, sOldPath, sizeOldPath, L"PATH"); // Add directory to PATH if not already there if (SUCCEEDED(lRes) && !wcsstr(sOldPath, sNewPath)) { // Resize mem for new PATH environment variable if (sNewPath = (PWCHAR)(pNewPath = realloc(pNewPath, (wcslen(sNewPath) + sizeOldPath) * sizeof(WCHAR)))) // Append old PATH content to new if SUCCEEDED(lRes = wcsncat_s(sNewPath + wcslen(sNewPath), sizeOldPath, sOldPath, sizeOldPath)) // Change PATH environment variable lRes = _wputenv_s(L"PATH", sNewPath); } // Cleanup free(sOldPath); free(pNewPath); return lRes; } int main() { if(FindInstallAndSetPath() != ERROR_SUCCESS) { return -1; } ////////////////////////////////////////////////// Reference<XComponentContext> xContext; Reference<XMultiComponentFactory> xMSFactory; Reference<XComponent> xDocument; // get the remote office component context xContext = bootstrap(); // get the remote office service manager xMSFactory = xContext->getServiceManager(); // get an instance of the remote office desktop UNO service // and query the XComponentLoader interface Reference<XInterface> desktop = xMSFactory->createInstanceWithContext( OUString::createFromAscii("com.sun.star.frame.Desktop"), xContext ); Reference<XComponentLoader> rComponentLoader( desktop, UNO_QUERY_THROW ); // the boolean property Hidden tells the office to open a file in hidden mode Sequence<PropertyValue> loadProps(1); loadProps[0].Name = OUString::createFromAscii("Hidden"); loadProps[0].Value = Any(true);//new Boolean(true); //get an instance of the spreadsheet document xDocument = rComponentLoader->loadComponentFromURL( OUString::createFromAscii("private:factory/scalc"), OUString::createFromAscii("_blank"), 0, loadProps); //query for a XSpreadsheetDocument interface Reference< XSpreadsheetDocument > rSheetDoc (xDocument, UNO_QUERY); //use it to get the XSpreadsheets interface Reference< XSpreadsheets > rSheets = rSheetDoc->getSheets(); //query for the XIndexAccess interface Reference< XIndexAccess > xSheetsIA (rSheets, UNO_QUERY); Any sheet = xSheetsIA->getByIndex( 0 ); Reference< XSpreadsheet > rSpSheet (sheet, UNO_QUERY); double num = 1.0; for(int i=0; i<10; i++,num+=2.0) { Reference<XCell> cell = rSpSheet->getCellByPosition(i, 0); cell->setValue(num); } Reference<XCell> cell = rSpSheet->getCellByPosition(10, 0); cell->setFormula(OUString::createFromAscii("=SUM(A1:J1)")); ////////////////////////// Reference< XPropertySet > rCellProps (cell, UNO_QUERY); Any PropVal; //PropVal <<= OUString::createFromAscii("Result"); PropVal <<= (Color)(0xff0000); rCellProps->setPropertyValue(OUString::createFromAscii("CharColor"), PropVal); ////////////////////////// Reference<XStorable> rStore (xDocument, UNO_QUERY); Sequence<PropertyValue> storeProps(1); storeProps[0].Name = OUString::createFromAscii("FilterName"); storeProps[0].Value = Any( OUString::createFromAscii("MS Excel 97") ); rStore->storeAsURL( OUString::createFromAscii("file:///c:/MyTest.xls"), storeProps ); xDocument->dispose(); return 0; }
你只需新建一个空的main.cpp,然后要把这段代码拷到你的main.cpp里面就可以了。下一节我会详细说明代码的含义。