C++ 自动化操作Word

C++ 自动化操作Word

备注:转载收藏

分类: windows Win32 351人阅读 评论(0) 收藏 举报

本文事例工程源码面积分下载地址:http://download.csdn.net/detail/zy_dreamer/5321760

介绍:

这个事例演示了如何写C++代码来创建并操作一个Microsoft
Word实例,创建一个新文档,插入一个段落,保存文档,关闭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。每个文档都有如下内容


 步骤4.打开任务管理器确保没有winword.exe进程,并且Word实例正常退出清理。
 利用代码:
 A.使用#import指令和智能指针(Solution1.h/cpp)

 1.使用#import指令引入需要使用的包含COM服务的库文件

  1. C# code snippet -  
  2.   
  3. #import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" \   
  4.         rename("RGB""MSORGB") \  
  5.         rename("DocumentProperties""MSODocumentProperties")  
  6.     // [-or-]   
  7.     //#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \   
  8.     //    rename("RGB", "MSORGB") \   
  9.     //    rename("DocumentProperties", "MSODocumentProperties")   
  10.    
  11.     using namespace Office;  
  12.   
  13.     #import "libid:0002E157-0000-0000-C000-000000000046"   
  14.     // [-or-]   
  15.     //#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"   
  16.    
  17.     using namespace VBIDE;  
  18.   
  19.     #import "libid:00020905-0000-0000-C000-000000000046" \   
  20.         rename("ExitWindows""WordExitWindows") \  
  21.         rename("FindText""WordFindText")  
  22.         // [-or-]   
  23.     //#import "C:\\Program Files\\Microsoft Office\\Office12\\MSWORD.OLB" \   
  24.     //    rename("ExitWindows", "WordExitWindows")   
  25.     //    rename("FindText", "WordFindText")   
  26.    
  27. - end -  
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

  1. /****************************** Module Header ******************************\ 
  2. * Module Name:  Solution1.h 
  3. * Project:      CppAutomateWord 
  4. * Copyright (c) Microsoft Corporation. 
  5.  
  6. * The code in Solution1.h/cpp demonstrates the use of #import to automate  
  7. * Word. #import (http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx), 
  8. * a new directive that became available with Visual C++ 5.0, creates VC++  
  9. * "smart pointers" from a specified type library. It is very powerful, but  
  10. * often not recommended because of reference-counting problems that typically  
  11. * occur when used with the Microsoft Office applications. Unlike the direct  
  12. * API approach in Solution2.h/cpp, smart pointers enable us to benefit from  
  13. * the type info to early/late bind the object. #import takes care of adding  
  14. * the messy guids to the project and the COM APIs are encapsulated in custom  
  15. * classes that the #import directive generates. 
  16.  
  17. * This source is subject to the Microsoft Public License. 
  18. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. 
  19. * All other rights reserved. 
  20.  
  21. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,  
  22. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED  
  23. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
  24. \***************************************************************************/  
  25.   
  26. #pragma once   
  27.   
  28.   
  29. //   
  30. //   FUNCTION: AutomateWordByImport(LPVOID)   
  31. //   
  32. //   PURPOSE: Automate Microsoft Word using the #import directive and smart    
  33. //      pointers.   
  34. //   
  35. //   PARAMETERS:   
  36. //      * lpParam - The thread data passed to the function using the    
  37. //      lpParameter parameter when creating a thread.    
  38. //      (http://msdn.microsoft.com/en-us/library/ms686736.aspx)   
  39. //   
  40. //   RETURN VALUE: The return value indicates the success or failure of the    
  41. //      function.    
  42. //   
  43. DWORD WINAPI AutomateWordByImport(LPVOID lpParam);  
/****************************** 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

  1. /****************************** Module Header ******************************\ 
  2. * Module Name:  Solution2.h 
  3. * Project:      CppAutomateWord 
  4. * Copyright (c) Microsoft Corporation. 
  5.  
  6. * The code in Solution2.h/cpp demonstrates the use of C/C++ and the COM APIs  
  7. * to automate Word. The raw automation is much more difficult, but it is  
  8. * sometimes necessary to avoid the overhead with MFC, or problems with  
  9. * #import. Basically, you work with such APIs as CoCreateInstance(), and COM  
  10. * interfaces such as IDispatch and IUnknown. 
  11.  
  12. * This source is subject to the Microsoft Public License. 
  13. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. 
  14. * All other rights reserved. 
  15.  
  16. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,  
  17. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED  
  18. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
  19. \***************************************************************************/  
  20.   
  21. #pragma once   
  22.   
  23.   
  24. //   
  25. //   FUNCTION: AutomateWordByCOMAPI(LPVOID)   
  26. //   
  27. //   PURPOSE: Automate Microsoft Word using C++ and the COM APIs.   
  28. //   
  29. //   PARAMETERS:   
  30. //      * lpParam - The thread data passed to the function using the    
  31. //      lpParameter parameter when creating a thread.    
  32. //      (http://msdn.microsoft.com/en-us/library/ms686736.aspx)   
  33. //   
  34. //   RETURN VALUE: The return value indicates the success or failure of the    
  35. //      function.    
  36. //   
  37. DWORD WINAPI AutomateWordByCOMAPI(LPVOID lpParam);  
/****************************** 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

  1. /****************************** Module Header ******************************\ 
  2. * Module Name:  Solution1.cpp 
  3. * Project:      CppAutomateWord 
  4. * Copyright (c) Microsoft Corporation. 
  5.  
  6. * The code in Solution1.h/cpp demonstrates the use of #import to automate  
  7. * Word. #import (http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx), 
  8. * a new directive that became available with Visual C++ 5.0, creates VC++  
  9. * "smart pointers" from a specified type library. It is very powerful, but  
  10. * often not recommended because of reference-counting problems that typically  
  11. * occur when used with the Microsoft Office applications. Unlike the direct  
  12. * API approach in Solution2.h/cpp, smart pointers enable us to benefit from  
  13. * the type info to early/late bind the object. #import takes care of adding  
  14. * the messy guids to the project and the COM APIs are encapsulated in custom  
  15. * classes that the #import directive generates. 
  16.  
  17. * This source is subject to the Microsoft Public License. 
  18. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. 
  19. * All other rights reserved. 
  20.  
  21. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,  
  22. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED  
  23. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
  24. \***************************************************************************/  
  25.   
  26. #pragma region Includes   
  27. #include <stdio.h>   
  28. #include <windows.h>   
  29. #include "Solution1.h"   
  30. #pragma endregion   
  31.   
  32.   
  33. #pragma region Import the type libraries   
  34.   
  35. #import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" \   
  36.     rename("RGB""MSORGB") \  
  37.     rename("DocumentProperties""MSODocumentProperties")  
  38. // [-or-]   
  39. //#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \   
  40. //  rename("RGB", "MSORGB") \   
  41. //  rename("DocumentProperties", "MSODocumentProperties")   
  42.   
  43. using namespace Office;  
  44.   
  45. #import "libid:0002E157-0000-0000-C000-000000000046"   
  46. // [-or-]   
  47. //#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"   
  48.   
  49. using namespace VBIDE;  
  50.   
  51. #import "libid:00020905-0000-0000-C000-000000000046" \   
  52.     rename("ExitWindows""WordExitWindows") \  
  53.     rename("FindText""WordFindText")  
  54. // [-or-]   
  55. //#import "C:\\Program Files\\Microsoft Office\\Office12\\MSWORD.OLB" \   
  56. //  rename("ExitWindows", "WordExitWindows") \   
  57. //  rename("FindText", "WordFindText")   
  58.   
  59. #pragma endregion   
  60.   
  61.   
  62. //   
  63. //   FUNCTION: GetModuleDirectory(LPWSTR, DWORD);   
  64. //   
  65. //   PURPOSE: This is a helper function in this sample. It retrieves the    
  66. //      fully-qualified path for the directory that contains the executable    
  67. //      file of the current process. For example, "D:\Samples\".   
  68. //   
  69. //   PARAMETERS:   
  70. //      * pszDir - A pointer to a buffer that receives the fully-qualified    
  71. //      path for the directory taht contains the executable file of the    
  72. //      current process. If the length of the path is less than the size that    
  73. //      the nSize parameter specifies, the function succeeds and the path is    
  74. //      returned as a null-terminated string.   
  75. //      * nSize - The size of the lpFilename buffer, in characters.   
  76. //   
  77. //   RETURN VALUE: If the function succeeds, the return value is the length    
  78. //      of the string that is copied to the buffer, in characters, not    
  79. //      including the terminating null character. If the buffer is too small    
  80. //      to hold the directory name, the function returns 0 and sets the last    
  81. //      error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return    
  82. //      value is 0 (zero). To get extended error information, call    
  83. //      GetLastError.   
  84. //   
  85. DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize);  
  86.   
  87.   
  88. //   
  89. //   FUNCTION: AutomateWordByImport(LPVOID)   
  90. //   
  91. //   PURPOSE: Automate Microsoft Word using the #import directive and smart    
  92. //      pointers.   
  93. //    
  94. DWORD WINAPI AutomateWordByImport(LPVOID lpParam)  
  95. {  
  96.     // Initializes the COM library on the current thread and identifies the   
  97.     // concurrency model as single-thread apartment (STA).    
  98.     // [-or-] CoInitialize(NULL);   
  99.     // [-or-] CoCreateInstance(NULL);   
  100.     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);  
  101.   
  102.     try  
  103.     {  
  104.   
  105.         /   
  106.         // Create the Word.Application COM object using the #import directive   
  107.         // and smart pointers.   
  108.         //    
  109.   
  110.         // Option 1) Create the object using the smart pointer's constructor   
  111.         // _ApplicationPtr is the original interface name, _Application, with a    
  112.         // "Ptr" suffix.   
  113.         //Word::_ApplicationPtr spWordApp(   
  114.         //  __uuidof(Word::Application) // CLSID of the component   
  115.         //  );   
  116.           
  117.         // [-or-]   
  118.   
  119.         // Option 2) Create the object using the smart pointer's function,   
  120.         // CreateInstance   
  121.         Word::_ApplicationPtr spWordApp;  
  122.         HRESULT hr = spWordApp.CreateInstance(__uuidof(Word::Application));  
  123.         if (FAILED(hr))  
  124.         {  
  125.             wprintf(L"CreateInstance failed w/err 0x%08lx\n", hr);  
  126.             return 1;  
  127.         }  
  128.   
  129.         _putws(L"Word.Application is started");  
  130.   
  131.   
  132.         /   
  133.         // Make Word invisible. (i.e. Application.Visible = 0)   
  134.         //    
  135.   
  136.         spWordApp->Visible = VARIANT_FALSE;  
  137.   
  138.   
  139.         /   
  140.         // Create a new Document. (i.e. Application.Documents.Add)   
  141.         //    
  142.   
  143.         Word::DocumentsPtr spDocs = spWordApp->Documents;  
  144.         Word::_DocumentPtr spDoc = spDocs->Add();  
  145.   
  146.         _putws(L"A new document is created");  
  147.   
  148.   
  149.         /   
  150.         // Insert a paragraph.   
  151.         //    
  152.   
  153.         _putws(L"Insert a paragraph");  
  154.   
  155.         Word::ParagraphsPtr spParas = spDoc->Paragraphs;  
  156.         Word::ParagraphPtr spPara = spParas->Add();  
  157.         Word::RangePtr spParaRng = spPara->Range;  
  158.         spParaRng->Text = _bstr_t(L"Heading 1");  
  159.         Word::_FontPtr spFont = spParaRng->Font;  
  160.         spFont->Bold = 1;  
  161.         spParaRng->InsertParagraphAfter();  
  162.   
  163.   
  164.         /   
  165.         // Save the document as a docx file and close it.   
  166.         //    
  167.   
  168.         _putws(L"Save and close the document");  
  169.   
  170.         // Make the file name   
  171.   
  172.         // Get the directory of the current exe.   
  173.         wchar_t szFileName[MAX_PATH];  
  174.         if (!GetModuleDirectory(szFileName, ARRAYSIZE(szFileName)))  
  175.         {  
  176.             _putws(L"GetModuleDirectory failed");  
  177.             return 1;  
  178.         }  
  179.   
  180.         // Concat "Sample1.docx" to the directory   
  181.         wcsncat_s(szFileName, ARRAYSIZE(szFileName), L"Sample1.docx", 12);  
  182.   
  183.         // Convert the NULL-terminated string to BSTR   
  184.         variant_t vtFileName(szFileName);  
  185.   
  186.         spDoc->SaveAs(&vtFileName);  
  187.   
  188.         spDoc->Close();  
  189.   
  190.   
  191.         /   
  192.         // Quit the Word application.   
  193.         //    
  194.   
  195.         _putws(L"Quit the Word application");  
  196.         spWordApp->Quit();  
  197.   
  198.   
  199.         /   
  200.         // Release the COM objects.   
  201.         //    
  202.   
  203.         // Releasing the references is not necessary for the smart pointers   
  204.         // ...   
  205.         // spWordApp.Release();   
  206.         // ...   
  207.   
  208.     }  
  209.     catch (_com_error &err)  
  210.     {  
  211.         wprintf(L"Word throws the error: %s\n", err.ErrorMessage());  
  212.         wprintf(L"Description: %s\n", (LPCWSTR) err.Description());  
  213.     }  
  214.   
  215.     // Uninitialize COM for this thread   
  216.     CoUninitialize();  
  217.   
  218.     return 0;  
  219. }  
/****************************** 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\n", 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\n", err.ErrorMessage());
		wprintf(L"Description: %s\n", (LPCWSTR) err.Description());
	}

	// Uninitialize COM for this thread
	CoUninitialize();

	return 0;
}

Solution2.cpp
  1. /****************************** Module Header ******************************\ 
  2. * Module Name:  Solution2.cpp 
  3. * Project:      CppAutomateWord 
  4. * Copyright (c) Microsoft Corporation. 
  5.  
  6. * The code in Solution2.h/cpp demonstrates the use of C/C++ and the COM APIs  
  7. * to automate Word. The raw automation is much more difficult, but it is  
  8. * sometimes necessary to avoid the overhead with MFC, or problems with  
  9. * #import. Basically, you work with such APIs as CoCreateInstance(), and COM  
  10. * interfaces such as IDispatch and IUnknown. 
  11.  
  12. * This source is subject to the Microsoft Public License. 
  13. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. 
  14. * All other rights reserved. 
  15.  
  16. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,  
  17. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED  
  18. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
  19. \***************************************************************************/  
  20.   
  21. #pragma region Includes   
  22. #include <stdio.h>   
  23. #include <windows.h>   
  24. #include "Solution2.h"   
  25. #pragma endregion   
  26.   
  27.   
  28. //   
  29. //   FUNCTION: AutoWrap(int, VARIANT*, IDispatch*, LPOLESTR, int,...)   
  30. //   
  31. //   PURPOSE: Automation helper function. It simplifies most of the low-level    
  32. //      details involved with using IDispatch directly. Feel free to use it    
  33. //      in your own implementations. One caveat is that if you pass multiple    
  34. //      parameters, they need to be passed in reverse-order.   
  35. //   
  36. //   PARAMETERS:   
  37. //      * autoType - Could be one of these values: DISPATCH_PROPERTYGET,    
  38. //      DISPATCH_PROPERTYPUT, DISPATCH_PROPERTYPUTREF, DISPATCH_METHOD.   
  39. //      * pvResult - Holds the return value in a VARIANT.   
  40. //      * pDisp - The IDispatch interface.   
  41. //      * ptName - The property/method name exposed by the interface.   
  42. //      * cArgs - The count of the arguments.   
  43. //   
  44. //   RETURN VALUE: An HRESULT value indicating whether the function succeeds    
  45. //      or not.    
  46. //   
  47. //   EXAMPLE:    
  48. //      AutoWrap(DISPATCH_METHOD, NULL, pDisp, L"call", 2, parm[1], parm[0]);   
  49. //   
  50. HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,   
  51.                  LPOLESTR ptName, int cArgs...)   
  52. {  
  53.     // Begin variable-argument list   
  54.     va_list marker;  
  55.     va_start(marker, cArgs);  
  56.   
  57.     if (!pDisp)   
  58.     {  
  59.         _putws(L"NULL IDispatch passed to AutoWrap()");  
  60.         _exit(0);  
  61.         return E_INVALIDARG;  
  62.     }  
  63.   
  64.     // Variables used   
  65.     DISPPARAMS dp = { NULL, NULL, 0, 0 };  
  66.     DISPID dispidNamed = DISPID_PROPERTYPUT;  
  67.     DISPID dispID;  
  68.     HRESULT hr;  
  69.   
  70.     // Get DISPID for name passed   
  71.     hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);  
  72.     if (FAILED(hr))  
  73.     {  
  74.         wprintf(L"IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx\n",   
  75.             ptName, hr);  
  76.         _exit(0);  
  77.         return hr;  
  78.     }  
  79.   
  80.     // Allocate memory for arguments   
  81.     VARIANT *pArgs = new VARIANT[cArgs + 1];  
  82.     // Extract arguments...   
  83.     for(int i=0; i < cArgs; i++)   
  84.     {  
  85.         pArgs[i] = va_arg(marker, VARIANT);  
  86.     }  
  87.   
  88.     // Build DISPPARAMS   
  89.     dp.cArgs = cArgs;  
  90.     dp.rgvarg = pArgs;  
  91.   
  92.     // Handle special-case for property-puts   
  93.     if (autoType & DISPATCH_PROPERTYPUT)  
  94.     {  
  95.         dp.cNamedArgs = 1;  
  96.         dp.rgdispidNamedArgs = &dispidNamed;  
  97.     }  
  98.   
  99.     // Make the call   
  100.     hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,  
  101.         autoType, &dp, pvResult, NULL, NULL);  
  102.     if (FAILED(hr))   
  103.     {  
  104.         wprintf(L"IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx\n",   
  105.             ptName, dispID, hr);  
  106.         _exit(0);  
  107.         return hr;  
  108.     }  
  109.   
  110.     // End variable-argument section   
  111.     va_end(marker);  
  112.   
  113.     delete[] pArgs;  
  114.   
  115.     return hr;  
  116. }  
  117.   
  118.   
  119. //   
  120. //   FUNCTION: GetModuleDirectory(LPWSTR, DWORD);   
  121. //   
  122. //   PURPOSE: This is a helper function in this sample. It retrieves the    
  123. //      fully-qualified path for the directory that contains the executable    
  124. //      file of the current process. For example, "D:\Samples\".   
  125. //   
  126. //   PARAMETERS:   
  127. //      * pszDir - A pointer to a buffer that receives the fully-qualified    
  128. //      path for the directory taht contains the executable file of the    
  129. //      current process. If the length of the path is less than the size that    
  130. //      the nSize parameter specifies, the function succeeds and the path is    
  131. //      returned as a null-terminated string.   
  132. //      * nSize - The size of the lpFilename buffer, in characters.   
  133. //   
  134. //   RETURN VALUE: If the function succeeds, the return value is the length    
  135. //      of the string that is copied to the buffer, in characters, not    
  136. //      including the terminating null character. If the buffer is too small    
  137. //      to hold the directory name, the function returns 0 and sets the last    
  138. //      error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return    
  139. //      value is 0 (zero). To get extended error information, call    
  140. //      GetLastError.   
  141. //   
  142. DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize);  
  143.   
  144.   
  145. //   
  146. //   FUNCTION: AutomateWordByCOMAPI(LPVOID)   
  147. //   
  148. //   PURPOSE: Automate Microsoft Word using C++ and the COM APIs.   
  149. //   
  150. DWORD WINAPI AutomateWordByCOMAPI(LPVOID lpParam)  
  151. {  
  152.     // Initializes the COM library on the current thread and identifies the    
  153.     // concurrency model as single-thread apartment (STA).    
  154.     // [-or-] CoInitialize(NULL);   
  155.     // [-or-] CoCreateInstance(NULL);   
  156.     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);  
  157.   
  158.   
  159.     /   
  160.     // Create the Word.Application COM object using C++ and the COM APIs.   
  161.     //    
  162.   
  163.     // Get CLSID of the server   
  164.       
  165.     CLSID clsid;  
  166.     HRESULT hr;  
  167.       
  168.     // Option 1. Get CLSID from ProgID using CLSIDFromProgID.   
  169.     LPCOLESTR progID = L"Word.Application";  
  170.     hr = CLSIDFromProgID(progID, &clsid);  
  171.     if (FAILED(hr))  
  172.     {  
  173.         wprintf(L"CLSIDFromProgID(\"%s\") failed w/err 0x%08lx\n", progID, hr);  
  174.         return 1;  
  175.     }  
  176.     // Option 2. Build the CLSID directly.   
  177.     /*const IID CLSID_Application =  
  178.     {0x000209FF,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; 
  179.     clsid = CLSID_Application;*/  
  180.   
  181.     // Start the server and get the IDispatch interface   
  182.   
  183.     IDispatch *pWordApp = NULL;  
  184.     hr = CoCreateInstance(      // [-or-] CoCreateInstanceEx, CoGetObject   
  185.         clsid,                  // CLSID of the server   
  186.         NULL,  
  187.         CLSCTX_LOCAL_SERVER,    // Word.Application is a local server   
  188.         IID_IDispatch,          // Query the IDispatch interface   
  189.         (void **)&pWordApp);    // Output   
  190.   
  191.     if (FAILED(hr))  
  192.     {  
  193.         wprintf(L"Word is not registered properly w/err 0x%08lx\n", hr);  
  194.         return 1;  
  195.     }  
  196.   
  197.     _putws(L"Word.Application is started");  
  198.   
  199.   
  200.     /   
  201.     // Make Word invisible. (i.e. Application.Visible = 0)   
  202.     //    
  203.   
  204.     {  
  205.         VARIANT x;  
  206.         x.vt = VT_I4;  
  207.         x.lVal = 0;  
  208.         AutoWrap(DISPATCH_PROPERTYPUT, NULL, pWordApp, L"Visible", 1, x);  
  209.     }  
  210.   
  211.   
  212.     /   
  213.     // Create a new Document. (i.e. Application.Documents.Add)   
  214.     //    
  215.   
  216.     // Get the Documents collection   
  217.     IDispatch *pDocs = NULL;  
  218.     {  
  219.         VARIANT result;  
  220.         VariantInit(&result);  
  221.         AutoWrap(DISPATCH_PROPERTYGET, &result, pWordApp, L"Documents", 0);  
  222.         pDocs = result.pdispVal;  
  223.     }  
  224.   
  225.     // Call Documents.Add() to get a new document   
  226.     IDispatch *pDoc = NULL;  
  227.     {  
  228.         VARIANT result;  
  229.         VariantInit(&result);  
  230.         AutoWrap(DISPATCH_METHOD, &result, pDocs, L"Add", 0);  
  231.         pDoc = result.pdispVal;  
  232.     }  
  233.   
  234.     _putws(L"A new document is created");  
  235.   
  236.   
  237.     /   
  238.     // Insert a paragraph.   
  239.     //    
  240.   
  241.     _putws(L"Insert a paragraph");  
  242.   
  243.     // pParas = pDoc->Paragraphs   
  244.     IDispatch *pParas = NULL;  
  245.     {  
  246.         VARIANT result;  
  247.         VariantInit(&result);  
  248.         AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, L"Paragraphs", 0);  
  249.         pParas = result.pdispVal;  
  250.     }  
  251.   
  252.     // pPara = pParas->Add   
  253.     IDispatch *pPara = NULL;  
  254.     {  
  255.         VARIANT result;  
  256.         VariantInit(&result);  
  257.         AutoWrap(DISPATCH_METHOD, &result, pParas, L"Add", 0);  
  258.         pPara = result.pdispVal;  
  259.     }  
  260.   
  261.     // pParaRng = pPara->Range   
  262.     IDispatch *pParaRng = NULL;  
  263.     {  
  264.         VARIANT result;  
  265.         VariantInit(&result);  
  266.         AutoWrap(DISPATCH_PROPERTYGET, &result, pPara, L"Range", 0);  
  267.         pParaRng = result.pdispVal;  
  268.     }  
  269.   
  270.     // pParaRng->Text = "Heading 1"   
  271.     {  
  272.         VARIANT x;  
  273.         x.vt = VT_BSTR;  
  274.         x.bstrVal = ::SysAllocString(L"Heading 1");  
  275.         AutoWrap(DISPATCH_PROPERTYPUT, NULL, pParaRng, L"Text", 1, x);  
  276.         VariantClear(&x);  
  277.     }  
  278.   
  279.     // pFont = pParaRng->Font   
  280.     IDispatch *pFont = NULL;  
  281.     {  
  282.         VARIANT result;  
  283.         VariantInit(&result);  
  284.         AutoWrap(DISPATCH_PROPERTYGET, &result, pParaRng, L"Font", 0);  
  285.         pFont = result.pdispVal;  
  286.     }  
  287.   
  288.     // pFont->Bold = 1   
  289.     {  
  290.         VARIANT x;  
  291.         x.vt = VT_I4;  
  292.         x.lVal = 1;  
  293.         AutoWrap(DISPATCH_PROPERTYPUT, NULL, pFont, L"Bold", 1, x);  
  294.     }  
  295.   
  296.     // pParaRng->InsertParagraphAfter();   
  297.     AutoWrap(DISPATCH_METHOD, NULL, pParaRng, L"InsertParagraphAfter", 0);  
  298.   
  299.   
  300.     /   
  301.     // Save the document as a docx file and close it.   
  302.     //    
  303.   
  304.     _putws(L"Save and close the document");  
  305.   
  306.     // pDoc->SaveAs   
  307.     {  
  308.         // Make the file name   
  309.   
  310.         // Get the directory of the current exe.   
  311.         wchar_t szFileName[MAX_PATH];  
  312.         if (!GetModuleDirectory(szFileName, ARRAYSIZE(szFileName)))  
  313.         {  
  314.             _putws(L"GetModuleDirectory failed");  
  315.             return 1;  
  316.         }  
  317.   
  318.         // Concat "Sample2.docx" to the directory.   
  319.         wcsncat_s(szFileName, ARRAYSIZE(szFileName), L"Sample2.docx", 12);  
  320.   
  321.         // Convert the NULL-terminated string to BSTR.   
  322.         VARIANT vtFileName;  
  323.         vtFileName.vt = VT_BSTR;  
  324.         vtFileName.bstrVal = SysAllocString(szFileName);  
  325.         AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"SaveAs", 1, vtFileName);  
  326.         VariantClear(&vtFileName);  
  327.     }  
  328.   
  329.     // pDoc->Close()   
  330.     AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"Close", 0);  
  331.   
  332.   
  333.     /   
  334.     // Quit the Word application. (i.e. Application.Quit())   
  335.     //    
  336.   
  337.     _putws(L"Quit the Word application");  
  338.     AutoWrap(DISPATCH_METHOD, NULL, pWordApp, L"Quit", 0);  
  339.   
  340.   
  341.     /   
  342.     // Release the COM objects.   
  343.     //    
  344.   
  345.     if (pFont != NULL)  
  346.     {  
  347.         pFont->Release();  
  348.     }  
  349.     if (pParaRng != NULL)  
  350.     {  
  351.         pParaRng->Release();  
  352.     }  
  353.     if (pPara != NULL)  
  354.     {  
  355.         pPara->Release();  
  356.     }  
  357.     if (pParas != NULL)  
  358.     {  
  359.         pParas->Release();  
  360.     }  
  361.     if (pDoc != NULL)  
  362.     {  
  363.         pDoc->Release();  
  364.     }  
  365.     if (pDocs != NULL)  
  366.     {  
  367.         pDocs->Release();  
  368.     }  
  369.     if (pWordApp != NULL)  
  370.     {  
  371.         pWordApp->Release();  
  372.     }  
  373.   
  374.     // Uninitialize COM for this thread.   
  375.     CoUninitialize();  
  376.   
  377.     return 0;  
  378. }  
/****************************** 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\n", 
			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\n", 
			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\n", 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\n", 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

  1. /****************************** Module Header ******************************\ 
  2. * Module Name:  CppAutomateWord.cpp 
  3. * Project:      CppAutomateWord 
  4. * Copyright (c) Microsoft Corporation. 
  5.  
  6. * The CppAutomateWord example demonstrates how to write VC++ code to create a   
  7. * Microsoft Word instance, create a new document, insert a paragraph, save  
  8. * the document, close the Microsoft Word application and then clean up  
  9. * unmanaged COM resources. 
  10.  
  11. * There are three basic ways you can write VC++ automation codes: 
  12.  
  13. * 1. Automating Word using the #import directive and smart pointers  
  14. * (Solution1.h/cpp) 
  15. * 2. Automating Word using C++ and the COM APIs (Solution2.h/cpp) 
  16. * 3. Automating Word using MFC (This is not covered in this sample) 
  17.  
  18. * This source is subject to the Microsoft Public License. 
  19. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. 
  20. * All other rights reserved. 
  21.  
  22. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,  
  23. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED  
  24. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
  25. \***************************************************************************/  
  26.   
  27. #pragma region Includes   
  28. #include <stdio.h>   
  29. #include <windows.h>   
  30.   
  31. #include "Solution1.h"      // The example of using the #import directive    
  32.                             // and smart pointers to automate Word   
  33. #include "Solution2.h"      // The example of using the raw COM API to     
  34.                             // automate Word   
  35. #pragma endregion   
  36.   
  37.   
  38. int wmain(int argc, wchar_t* argv[])  
  39. {  
  40.     HANDLE hThread;  
  41.   
  42.     // Demonstrate automating Word using the #import directive and smart    
  43.     // pointers in a separate thread.   
  44.     hThread = CreateThread(NULL, 0, AutomateWordByImport, NULL, 0, NULL);  
  45.     WaitForSingleObject(hThread, INFINITE);   
  46.     CloseHandle(hThread);  
  47.   
  48.     _putws(L"");  
  49.   
  50.     // Demonstrate automating Word using C++ and the COM APIs in a separate    
  51.     // thread.   
  52.     hThread = CreateThread(NULL, 0, AutomateWordByCOMAPI, NULL, 0, NULL);  
  53.     WaitForSingleObject(hThread, INFINITE);  
  54.     CloseHandle(hThread);  
  55.   
  56.     return 0;  
  57. }  
  58.   
  59.   
  60. //   
  61. //   FUNCTION: GetModuleDirectory(LPWSTR, DWORD);   
  62. //   
  63. //   PURPOSE: This is a helper function in this sample. It retrieves the    
  64. //      fully-qualified path for the directory that contains the executable    
  65. //      file of the current process. For example, "D:\Samples\".   
  66. //   
  67. //   PARAMETERS:   
  68. //      * pszDir - A pointer to a buffer that receives the fully-qualified    
  69. //      path for the directory taht contains the executable file of the    
  70. //      current process. If the length of the path is less than the size that    
  71. //      the nSize parameter specifies, the function succeeds and the path is    
  72. //      returned as a null-terminated string.   
  73. //      * nSize - The size of the lpFilename buffer, in characters.   
  74. //   
  75. //   RETURN VALUE: If the function succeeds, the return value is the length    
  76. //      of the string that is copied to the buffer, in characters, not    
  77. //      including the terminating null character. If the buffer is too small    
  78. //      to hold the directory name, the function returns 0 and sets the last    
  79. //      error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return    
  80. //      value is 0 (zero). To get extended error information, call    
  81. //      GetLastError.   
  82. //   
  83. DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize)  
  84. {  
  85.     // Retrieve the path of the executable file of the current process.   
  86.     nSize = GetModuleFileName(NULL, pszDir, nSize);  
  87.     if (!nSize || GetLastError() == ERROR_INSUFFICIENT_BUFFER)  
  88.     {  
  89.         *pszDir = L'\0'// Ensure it's NULL terminated   
  90.         return 0;  
  91.     }  
  92.   
  93.     // Run through looking for the last slash in the file path.   
  94.     // When we find it, NULL it to truncate the following filename part.   
  95.   
  96.     for (int i = nSize - 1; i >= 0; i--)  
  97.     {  
  98.         if (pszDir[i] == L'\\' || pszDir[i] == L'/')  
  99.         {  
  100.             pszDir[i + 1] = L'\0';  
  101.             nSize = i + 1;  
  102.             break;  
  103.         }  
  104.     }  
  105.     return nSize;  
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值