程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 自動化操作Word

C++ 自動化操作Word

編輯:C++入門知識

介紹:

這個事例演示了如何寫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服務的庫文件


[csharp]
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 - 

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


[cpp]
/****************************** 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); 

/****************************** 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


[cpp]
/****************************** 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); 

/****************************** 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


[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\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; 

/****************************** 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[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\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; 

/****************************** 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

 

[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'\0'; // 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'\0'; 
            nSize = i + 1; 
            break; 
        } 
    } 
    return nSize; 

/****************************** 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'\0'; // 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'\0';
   nSize = i + 1;
            break;
  }
    }
 return nSize;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved