C++ 自动化操作Word
本文事例工程源码面积分下载地址:http://download.csdn.net/detail/zy_dreamer/5321760
介绍:
这个事例演示了如何写C++代码来创建并操作一个MicrosoftWord实例,创建一个新文档,插入一个段落,保存文档,关闭Word程序并清理使用的COM资源。
利用VC++实现有三种基本方法:
1.使用#import指令和智能指针操作Word
Solution1.h/cpp中的代码演示了如何使用#import指令来实现操作Word。#import指令是一个Visual C++ 5.0后新支持的一个指令。从一个特定类型的库文件中创建VC++智能指针。它的功能非常强大,但是一般并不推荐,原因是在于微软办公应用程序一起使用时引用计数问题经常出现。与Solution2.h/cpp中直接利用API的方法不同,从类型信息中获益,智能指针可以让我们支持早或晚绑定到对象。#import指令帮我们处理了添加杂乱的guid到工程中。COM API同样包装在#import指令引入的类中。
2.利用MFC实现操作
使用MFC,使用Visual C++的类向导可以自动添加包装类。这些类使用了简单的COM服务。
3.利用C++和COM API来处理Word
在Solution2.h/cpp中演示了如何使用C/C++和COM API自动操作Word。这种操作方法非常困难,但是有时确实必要的,因为你避免了使用MFC所带来的额外开销以及使用#import指令所带来的问题。你将利用像CoCreateInstance()这样的API以及类似IDispatch 和 IUnknown的COM接口。
运行Sample
步骤1.当你成功在VS2008中编译事例工程后,你会得到一个名称为CppAutomateWord.exe.的应用程序。
步骤2.打开Windows资源管理器(Ctrl+Shift+Esc),确保没有winword.exe在运行。
步骤3.运行程序,如果没有任何错误抛出的话,它应该打印下列内容。然后你就会看见在程序目录下生成两个新文档:Sample1.docx和Sample2.docx。每个文档都有如下内容
利用代码:
A.使用#import指令和智能指针(Solution1.h/cpp)
1.使用#import指令引入需要使用的包含COM服务的库文件
C# code snippet - #import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" rename("RGB", "MSORGB") rename("DocumentProperties", "MSODocumentProperties") // [-or-] //#import "C:\Program Files\Common Files\Microsoft Shared\OFFICE12\MSO.DLL" // rename("RGB", "MSORGB") // rename("DocumentProperties", "MSODocumentProperties") using namespace Office; #import "libid:0002E157-0000-0000-C000-000000000046" // [-or-] //#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" using namespace VBIDE; #import "libid:00020905-0000-0000-C000-000000000046" rename("ExitWindows", "WordExitWindows") rename("FindText", "WordFindText") // [-or-] //#import "C:\Program Files\Microsoft Office\Office12\MSWORD.OLB" // rename("ExitWindows", "WordExitWindows") // rename("FindText", "WordFindText") - end -2.编译工程,如果成功,工程中会生成一个.tlh的文件,它包装了刚才引入的COM服务。它以一个包装类的形势供我们使用,我们可以通过它创建COM类并使用成员,方法等。
3.在当前线程上初始化COM库。
4.使用智能指针创建Word.Application COM对象。类的名字是原始接口名(例如Word::_Application)带一个Ptr前缀。我们可以利用智能指针的构造函数或是
CreateInstance方法来创建一个COM对象。
5.利用这个智能指针操作Word COM对象。例如你可以找到对Word的基本操作例如:
创建一个新的文档(例如Application.Documents.Add)
插入一个段落。
保存文档为docx文件并关闭它。
6.退出Word application(Application.Quit())
7.智能指针是自动释放的,所以我们不需要考虑收到释放COM对象。
8.我们有必要捕获可能的COM错误,例如
9.调用CoUninitialize销毁COM。
B.使用C++和COM API操作(Solution2.h/cpp)
1.添加自动化帮助类 AutoWrap.
2.初始化COM库,调用CoInitializeEx, 或 CoInitialize确保并发模型只有一个实例。
3.使用CLSIDFromProgID API获得Word COM的CLSID
4.使用CoCreateInstan获得IDispatch 接口
5.使用AutoWrap帮助类操作COM对象。
6.退出Word application(Application。Quit())
7.释放COM对象。
8.调用CoUninitialize卸载COM。
Solution1.h
/****************************** Module Header ****************************** * Module Name: Solution1.h * Project: CppAutomateWord * Copyright (c) Microsoft Corporation. * * The code in Solution1.h/cpp demonstrates the use of #import to automate * Word. #import (http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx), * a new directive that became available with Visual C++ 5.0, creates VC++ * "smart pointers" from a specified type library. It is very powerful, but * often not recommended because of reference-counting problems that typically * occur when used with the Microsoft Office applications. Unlike the direct * API approach in Solution2.h/cpp, smart pointers enable us to benefit from * the type info to early/late bind the object. #import takes care of adding * the messy guids to the project and the COM APIs are encapsulated in custom * classes that the #import directive generates. * * This source is subject to the Microsoft Public License. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. * All other rights reserved. * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. ***************************************************************************/ #pragma once // // FUNCTION: AutomateWordByImport(LPVOID) // // PURPOSE: Automate Microsoft Word using the #import directive and smart // pointers. // // PARAMETERS: // * lpParam - The thread data passed to the function using the // lpParameter parameter when creating a thread. // (http://msdn.microsoft.com/en-us/library/ms686736.aspx) // // RETURN VALUE: The return value indicates the success or failure of the // function. // DWORD WINAPI AutomateWordByImport(LPVOID lpParam);
Solution2.h
/****************************** Module Header ****************************** * Module Name: Solution2.h * Project: CppAutomateWord * Copyright (c) Microsoft Corporation. * * The code in Solution2.h/cpp demonstrates the use of C/C++ and the COM APIs * to automate Word. The raw automation is much more difficult, but it is * sometimes necessary to avoid the overhead with MFC, or problems with * #import. Basically, you work with such APIs as CoCreateInstance(), and COM * interfaces such as IDispatch and IUnknown. * * This source is subject to the Microsoft Public License. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. * All other rights reserved. * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. ***************************************************************************/ #pragma once // // FUNCTION: AutomateWordByCOMAPI(LPVOID) // // PURPOSE: Automate Microsoft Word using C++ and the COM APIs. // // PARAMETERS: // * lpParam - The thread data passed to the function using the // lpParameter parameter when creating a thread. // (http://msdn.microsoft.com/en-us/library/ms686736.aspx) // // RETURN VALUE: The return value indicates the success or failure of the // function. // DWORD WINAPI AutomateWordByCOMAPI(LPVOID lpParam);
Solution1.cpp
/****************************** Module Header ****************************** * Module Name: Solution1.cpp * Project: CppAutomateWord * Copyright (c) Microsoft Corporation. * * The code in Solution1.h/cpp demonstrates the use of #import to automate * Word. #import (http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx), * a new directive that became available with Visual C++ 5.0, creates VC++ * "smart pointers" from a specified type library. It is very powerful, but * often not recommended because of reference-counting problems that typically * occur when used with the Microsoft Office applications. Unlike the direct * API approach in Solution2.h/cpp, smart pointers enable us to benefit from * the type info to early/late bind the object. #import takes care of adding * the messy guids to the project and the COM APIs are encapsulated in custom * classes that the #import directive generates. * * This source is subject to the Microsoft Public License. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. * All other rights reserved. * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. ***************************************************************************/ #pragma region Includes #include <stdio.h> #include <windows.h> #include "Solution1.h" #pragma endregion #pragma region Import the type libraries #import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" rename("RGB", "MSORGB") rename("DocumentProperties", "MSODocumentProperties") // [-or-] //#import "C:\Program Files\Common Files\Microsoft Shared\OFFICE12\MSO.DLL" // rename("RGB", "MSORGB") // rename("DocumentProperties", "MSODocumentProperties") using namespace Office; #import "libid:0002E157-0000-0000-C000-000000000046" // [-or-] //#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" using namespace VBIDE; #import "libid:00020905-0000-0000-C000-000000000046" rename("ExitWindows", "WordExitWindows") rename("FindText", "WordFindText") // [-or-] //#import "C:\Program Files\Microsoft Office\Office12\MSWORD.OLB" // rename("ExitWindows", "WordExitWindows") // rename("FindText", "WordFindText") #pragma endregion // // FUNCTION: GetModuleDirectory(LPWSTR, DWORD); // // PURPOSE: This is a helper function in this sample. It retrieves the // fully-qualified path for the directory that contains the executable // file of the current process. For example, "D:Samples". // // PARAMETERS: // * pszDir - A pointer to a buffer that receives the fully-qualified // path for the directory taht contains the executable file of the // current process. If the length of the path is less than the size that // the nSize parameter specifies, the function succeeds and the path is // returned as a null-terminated string. // * nSize - The size of the lpFilename buffer, in characters. // // RETURN VALUE: If the function succeeds, the return value is the length // of the string that is copied to the buffer, in characters, not // including the terminating null character. If the buffer is too small // to hold the directory name, the function returns 0 and sets the last // error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return // value is 0 (zero). To get extended error information, call // GetLastError. // DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize); // // FUNCTION: AutomateWordByImport(LPVOID) // // PURPOSE: Automate Microsoft Word using the #import directive and smart // pointers. // DWORD WINAPI AutomateWordByImport(LPVOID lpParam) { // Initializes the COM library on the current thread and identifies the // concurrency model as single-thread apartment (STA). // [-or-] CoInitialize(NULL); // [-or-] CoCreateInstance(NULL); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); try { ///////////////////////////////////////////////////////////////////// // Create the Word.Application COM object using the #import directive // and smart pointers. // // Option 1) Create the object using the smart pointer"s constructor // _ApplicationPtr is the original interface name, _Application, with a // "Ptr" suffix. //Word::_ApplicationPtr spWordApp( // __uuidof(Word::Application) // CLSID of the component // ); // [-or-] // Option 2) Create the object using the smart pointer"s function, // CreateInstance Word::_ApplicationPtr spWordApp; HRESULT hr = spWordApp.CreateInstance(__uuidof(Word::Application)); if (FAILED(hr)) { wprintf(L"CreateInstance failed w/err 0x%08lx ", hr); return 1; } _putws(L"Word.Application is started"); ///////////////////////////////////////////////////////////////////// // Make Word invisible. (i.e. Application.Visible = 0) // spWordApp->Visible = VARIANT_FALSE; ///////////////////////////////////////////////////////////////////// // Create a new Document. (i.e. Application.Documents.Add) // Word::DocumentsPtr spDocs = spWordApp->Documents; Word::_DocumentPtr spDoc = spDocs->Add(); _putws(L"A new document is created"); ///////////////////////////////////////////////////////////////////// // Insert a paragraph. // _putws(L"Insert a paragraph"); Word::ParagraphsPtr spParas = spDoc->Paragraphs; Word::ParagraphPtr spPara = spParas->Add(); Word::RangePtr spParaRng = spPara->Range; spParaRng->Text = _bstr_t(L"Heading 1"); Word::_FontPtr spFont = spParaRng->Font; spFont->Bold = 1; spParaRng->InsertParagraphAfter(); ///////////////////////////////////////////////////////////////////// // Save the document as a docx file and close it. // _putws(L"Save and close the document"); // Make the file name // Get the directory of the current exe. wchar_t szFileName[MAX_PATH]; if (!GetModuleDirectory(szFileName, ARRAYSIZE(szFileName))) { _putws(L"GetModuleDirectory failed"); return 1; } // Concat "Sample1.docx" to the directory wcsncat_s(szFileName, ARRAYSIZE(szFileName), L"Sample1.docx", 12); // Convert the NULL-terminated string to BSTR variant_t vtFileName(szFileName); spDoc->SaveAs(&vtFileName); spDoc->Close(); ///////////////////////////////////////////////////////////////////// // Quit the Word application. // _putws(L"Quit the Word application"); spWordApp->Quit(); ///////////////////////////////////////////////////////////////////// // Release the COM objects. // // Releasing the references is not necessary for the smart pointers // ... // spWordApp.Release(); // ... } catch (_com_error &err) { wprintf(L"Word throws the error: %s ", err.ErrorMessage()); wprintf(L"Description: %s ", (LPCWSTR) err.Description()); } // Uninitialize COM for this thread CoUninitialize(); return 0; }
Solution2.cpp
/****************************** Module Header ****************************** * Module Name: Solution2.cpp * Project: CppAutomateWord * Copyright (c) Microsoft Corporation. * * The code in Solution2.h/cpp demonstrates the use of C/C++ and the COM APIs * to automate Word. The raw automation is much more difficult, but it is * sometimes necessary to avoid the overhead with MFC, or problems with * #import. Basically, you work with such APIs as CoCreateInstance(), and COM * interfaces such as IDispatch and IUnknown. * * This source is subject to the Microsoft Public License. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. * All other rights reserved. * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. ***************************************************************************/ #pragma region Includes #include <stdio.h> #include <windows.h> #include "Solution2.h" #pragma endregion // // FUNCTION: AutoWrap(int, VARIANT*, IDispatch*, LPOLESTR, int,...) // // PURPOSE: Automation helper function. It simplifies most of the low-level // details involved with using IDispatch directly. Feel free to use it // in your own implementations. One caveat is that if you pass multiple // parameters, they need to be passed in reverse-order. // // PARAMETERS: // * autoType - Could be one of these values: DISPATCH_PROPERTYGET, // DISPATCH_PROPERTYPUT, DISPATCH_PROPERTYPUTREF, DISPATCH_METHOD. // * pvResult - Holds the return value in a VARIANT. // * pDisp - The IDispatch interface. // * ptName - The property/method name exposed by the interface. // * cArgs - The count of the arguments. // // RETURN VALUE: An HRESULT value indicating whether the function succeeds // or not. // // EXAMPLE: // AutoWrap(DISPATCH_METHOD, NULL, pDisp, L"call", 2, parm[1], parm[0]); // HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...) { // Begin variable-argument list va_list marker; va_start(marker, cArgs); if (!pDisp) { _putws(L"NULL IDispatch passed to AutoWrap()"); _exit(0); return E_INVALIDARG; } // Variables used DISPPARAMS dp = { NULL, NULL, 0, 0 }; DISPID dispidNamed = DISPID_PROPERTYPUT; DISPID dispID; HRESULT hr; // Get DISPID for name passed hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID); if (FAILED(hr)) { wprintf(L"IDispatch::GetIDsOfNames("%s") failed w/err 0x%08lx ", ptName, hr); _exit(0); return hr; } // Allocate memory for arguments VARIANT *pArgs = new VARIANT[cArgs + 1]; // Extract arguments... for(int i=0; i < cArgs; i++) { pArgs[i] = va_arg(marker, VARIANT); } // Build DISPPARAMS dp.cArgs = cArgs; dp.rgvarg = pArgs; // Handle special-case for property-puts if (autoType & DISPATCH_PROPERTYPUT) { dp.cNamedArgs = 1; dp.rgdispidNamedArgs = &dispidNamed; } // Make the call hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL); if (FAILED(hr)) { wprintf(L"IDispatch::Invoke("%s"=%08lx) failed w/err 0x%08lx ", ptName, dispID, hr); _exit(0); return hr; } // End variable-argument section va_end(marker); delete[] pArgs; return hr; } // // FUNCTION: GetModuleDirectory(LPWSTR, DWORD); // // PURPOSE: This is a helper function in this sample. It retrieves the // fully-qualified path for the directory that contains the executable // file of the current process. For example, "D:Samples". // // PARAMETERS: // * pszDir - A pointer to a buffer that receives the fully-qualified // path for the directory taht contains the executable file of the // current process. If the length of the path is less than the size that // the nSize parameter specifies, the function succeeds and the path is // returned as a null-terminated string. // * nSize - The size of the lpFilename buffer, in characters. // // RETURN VALUE: If the function succeeds, the return value is the length // of the string that is copied to the buffer, in characters, not // including the terminating null character. If the buffer is too small // to hold the directory name, the function returns 0 and sets the last // error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return // value is 0 (zero). To get extended error information, call // GetLastError. // DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize); // // FUNCTION: AutomateWordByCOMAPI(LPVOID) // // PURPOSE: Automate Microsoft Word using C++ and the COM APIs. // DWORD WINAPI AutomateWordByCOMAPI(LPVOID lpParam) { // Initializes the COM library on the current thread and identifies the // concurrency model as single-thread apartment (STA). // [-or-] CoInitialize(NULL); // [-or-] CoCreateInstance(NULL); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); ///////////////////////////////////////////////////////////////////////// // Create the Word.Application COM object using C++ and the COM APIs. // // Get CLSID of the server CLSID clsid; HRESULT hr; // Option 1. Get CLSID from ProgID using CLSIDFromProgID. LPCOLESTR progID = L"Word.Application"; hr = CLSIDFromProgID(progID, &clsid); if (FAILED(hr)) { wprintf(L"CLSIDFromProgID("%s") failed w/err 0x%08lx ", progID, hr); return 1; } // Option 2. Build the CLSID directly. /*const IID CLSID_Application = {0x000209FF,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; clsid = CLSID_Application;*/ // Start the server and get the IDispatch interface IDispatch *pWordApp = NULL; hr = CoCreateInstance( // [-or-] CoCreateInstanceEx, CoGetObject clsid, // CLSID of the server NULL, CLSCTX_LOCAL_SERVER, // Word.Application is a local server IID_IDispatch, // Query the IDispatch interface (void **)&pWordApp); // Output if (FAILED(hr)) { wprintf(L"Word is not registered properly w/err 0x%08lx ", hr); return 1; } _putws(L"Word.Application is started"); ///////////////////////////////////////////////////////////////////////// // Make Word invisible. (i.e. Application.Visible = 0) // { VARIANT x; x.vt = VT_I4; x.lVal = 0; AutoWrap(DISPATCH_PROPERTYPUT, NULL, pWordApp, L"Visible", 1, x); } ///////////////////////////////////////////////////////////////////////// // Create a new Document. (i.e. Application.Documents.Add) // // Get the Documents collection IDispatch *pDocs = NULL; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pWordApp, L"Documents", 0); pDocs = result.pdispVal; } // Call Documents.Add() to get a new document IDispatch *pDoc = NULL; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_METHOD, &result, pDocs, L"Add", 0); pDoc = result.pdispVal; } _putws(L"A new document is created"); ///////////////////////////////////////////////////////////////////////// // Insert a paragraph. // _putws(L"Insert a paragraph"); // pParas = pDoc->Paragraphs IDispatch *pParas = NULL; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, L"Paragraphs", 0); pParas = result.pdispVal; } // pPara = pParas->Add IDispatch *pPara = NULL; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_METHOD, &result, pParas, L"Add", 0); pPara = result.pdispVal; } // pParaRng = pPara->Range IDispatch *pParaRng = NULL; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pPara, L"Range", 0); pParaRng = result.pdispVal; } // pParaRng->Text = "Heading 1" { VARIANT x; x.vt = VT_BSTR; x.bstrVal = ::SysAllocString(L"Heading 1"); AutoWrap(DISPATCH_PROPERTYPUT, NULL, pParaRng, L"Text", 1, x); VariantClear(&x); } // pFont = pParaRng->Font IDispatch *pFont = NULL; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pParaRng, L"Font", 0); pFont = result.pdispVal; } // pFont->Bold = 1 { VARIANT x; x.vt = VT_I4; x.lVal = 1; AutoWrap(DISPATCH_PROPERTYPUT, NULL, pFont, L"Bold", 1, x); } // pParaRng->InsertParagraphAfter(); AutoWrap(DISPATCH_METHOD, NULL, pParaRng, L"InsertParagraphAfter", 0); ///////////////////////////////////////////////////////////////////////// // Save the document as a docx file and close it. // _putws(L"Save and close the document"); // pDoc->SaveAs { // Make the file name // Get the directory of the current exe. wchar_t szFileName[MAX_PATH]; if (!GetModuleDirectory(szFileName, ARRAYSIZE(szFileName))) { _putws(L"GetModuleDirectory failed"); return 1; } // Concat "Sample2.docx" to the directory. wcsncat_s(szFileName, ARRAYSIZE(szFileName), L"Sample2.docx", 12); // Convert the NULL-terminated string to BSTR. VARIANT vtFileName; vtFileName.vt = VT_BSTR; vtFileName.bstrVal = SysAllocString(szFileName); AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"SaveAs", 1, vtFileName); VariantClear(&vtFileName); } // pDoc->Close() AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"Close", 0); ///////////////////////////////////////////////////////////////////////// // Quit the Word application. (i.e. Application.Quit()) // _putws(L"Quit the Word application"); AutoWrap(DISPATCH_METHOD, NULL, pWordApp, L"Quit", 0); ///////////////////////////////////////////////////////////////////////// // Release the COM objects. // if (pFont != NULL) { pFont->Release(); } if (pParaRng != NULL) { pParaRng->Release(); } if (pPara != NULL) { pPara->Release(); } if (pParas != NULL) { pParas->Release(); } if (pDoc != NULL) { pDoc->Release(); } if (pDocs != NULL) { pDocs->Release(); } if (pWordApp != NULL) { pWordApp->Release(); } // Uninitialize COM for this thread. CoUninitialize(); return 0; }CppAutomateWord.cpp
/****************************** Module Header ****************************** * Module Name: CppAutomateWord.cpp * Project: CppAutomateWord * Copyright (c) Microsoft Corporation. * * The CppAutomateWord example demonstrates how to write VC++ code to create a * Microsoft Word instance, create a new document, insert a paragraph, save * the document, close the Microsoft Word application and then clean up * unmanaged COM resources. * * There are three basic ways you can write VC++ automation codes: * * 1. Automating Word using the #import directive and smart pointers * (Solution1.h/cpp) * 2. Automating Word using C++ and the COM APIs (Solution2.h/cpp) * 3. Automating Word using MFC (This is not covered in this sample) * * This source is subject to the Microsoft Public License. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. * All other rights reserved. * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. ***************************************************************************/ #pragma region Includes #include <stdio.h> #include <windows.h> #include "Solution1.h" // The example of using the #import directive // and smart pointers to automate Word #include "Solution2.h" // The example of using the raw COM API to // automate Word #pragma endregion int wmain(int argc, wchar_t* argv[]) { HANDLE hThread; // Demonstrate automating Word using the #import directive and smart // pointers in a separate thread. hThread = CreateThread(NULL, 0, AutomateWordByImport, NULL, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); _putws(L""); // Demonstrate automating Word using C++ and the COM APIs in a separate // thread. hThread = CreateThread(NULL, 0, AutomateWordByCOMAPI, NULL, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); return 0; } // // FUNCTION: GetModuleDirectory(LPWSTR, DWORD); // // PURPOSE: This is a helper function in this sample. It retrieves the // fully-qualified path for the directory that contains the executable // file of the current process. For example, "D:Samples". // // PARAMETERS: // * pszDir - A pointer to a buffer that receives the fully-qualified // path for the directory taht contains the executable file of the // current process. If the length of the path is less than the size that // the nSize parameter specifies, the function succeeds and the path is // returned as a null-terminated string. // * nSize - The size of the lpFilename buffer, in characters. // // RETURN VALUE: If the function succeeds, the return value is the length // of the string that is copied to the buffer, in characters, not // including the terminating null character. If the buffer is too small // to hold the directory name, the function returns 0 and sets the last // error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return // value is 0 (zero). To get extended error information, call // GetLastError. // DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize) { // Retrieve the path of the executable file of the current process. nSize = GetModuleFileName(NULL, pszDir, nSize); if (!nSize || GetLastError() == ERROR_INSUFFICIENT_BUFFER) { *pszDir = L" "; // Ensure it"s NULL terminated return 0; } // Run through looking for the last slash in the file path. // When we find it, NULL it to truncate the following filename part. for (int i = nSize - 1; i >= 0; i--) { if (pszDir[i] == L"\" || pszDir[i] == L"/") { pszDir[i + 1] = L" "; nSize = i + 1; break; } } return nSize; }
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
- 上一篇: 利用环境变量向子进程传递一个参数
- 下一篇:没有了