简单的使用自动化技术实现用WORD读取一个XML文件的过程~

本文介绍了一个使用C++自动化技术来读取XML文件的简单过程,通过创建一个自动化管理类VZ_AutoManager,并派生出VZ_AutoWord类来控制Word应用程序,实现打开XML文件的功能。

最近有位朋友向我问关于自动化方面的问题,两年都没用过了,于是翻出原来的代码~自动化的调用方法有很多种,我使用的是最接近C++底层的那种(汗,主要是其他的方法看不懂,我只调用一个MS Word函数,那些方法非要引入一堆库),也许最简单的最直接~

 

四个文件,贴上来

//  class: VZ_AutoManager:自动化管理类
//
//  Author: Vonger Chin(秦炜)
//  Date: 07.13.2007

#include <ole2.h>   // 就引入这一个头文件就够了

#define VZ_MAX_ARGUMENTS 0x100
#define VZ_AutoManager  AutoManager

class VZ_AutoManager
{
public:

 VZ_AutoManager();
 ~VZ_AutoManager();

 HRESULT CreateInstance(CLSID clsid);
 HRESULT CreateInstance(LPCOLESTR ProgIDName);

 HRESULT SetInvokeParam(LONG cArgs,...);
 HRESULT SetParam(LONG lArgs,...);

 HRESULT SetIDispatch(IDispatch* pDisp);
 HRESULT SetIDispatch(LPOLESTR ptName);
 HRESULT SetIDispatch(DISPID dispID);

 IDispatch* GetIDispatch();
 IDispatch* GetIDispatch(LPOLESTR ptName);
 IDispatch* GetIDispatch(DISPID dispID);

 HRESULT InvokeByID(SHORT nType, VARIANT *pvResult, DISPID dispID, LPOLESTR ptName = NULL);
 HRESULT InvokeByName(SHORT nType, VARIANT *pvResult, LPOLESTR ptName);

private:
 DISPPARAMS m_stuParam;
 LONG  m_lArgsCnt;
 IDispatch* m_pDisp;
};

 

 

#include "stdafx.h"
#include "AutoManager.h"


VZ_AutoManager::VZ_AutoManager()
{
 // Initialize COM
 ::CoInitialize(NULL);

 ZeroMemory(&m_stuParam, sizeof(DISPPARAMS));
 m_stuParam.rgvarg = new VARIANT[VZ_MAX_ARGUMENTS];
 m_stuParam.rgdispidNamedArgs = new DISPID[VZ_MAX_ARGUMENTS];
 m_lArgsCnt = VZ_MAX_ARGUMENTS;
}


VZ_AutoManager::~VZ_AutoManager()
{
 // Uninitialize Auto
 ::CoUninitialize();

 delete[] m_stuParam.rgvarg;
 delete[] m_stuParam.rgdispidNamedArgs;
}

 

// 这个函数用来导入自动化函数通过它的ID
HRESULT VZ_AutoManager::InvokeByID(SHORT nType, VARIANT *pvResult, DISPID dispID, LPOLESTR ptName)
{
 HRESULT hr;

 // Handle special-case for property-puts!
 if(nType & DISPATCH_PROPERTYPUT)
 {
  m_stuParam.cNamedArgs = 1;
  m_stuParam.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
 }
 else
 {
  m_stuParam.cNamedArgs = 0;
 }

 hr = m_pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, nType, &m_stuParam, pvResult, NULL, NULL);
 if(FAILED(hr))
 {
  TCHAR buffer[VZ_MAX_ARGUMENTS];
  if(ptName)
   ::wsprintf(buffer, TEXT("IDispatch::Invoke(0x%x:%s) failed 0x%8x"), dispID, ptName, hr);
  else
   ::wsprintf(buffer, TEXT("IDispatch::Invoke(0x%x) failed 0x%8x"), dispID, hr);
  MessageBox(NULL, buffer, TEXT("Error"), MB_OK|MB_ICONERROR);
  return hr;
 }

 return hr;
}

 

// 这个函数用来导入自动化函数通过它的Name
HRESULT VZ_AutoManager::InvokeByName(SHORT nType, VARIANT *pvResult, LPOLESTR ptName)
{
 HRESULT hr;
 DISPID dispID;

 // Get DISPIP by Names
 hr = m_pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
 if(FAILED(hr))
 {
  TCHAR buffer[VZ_MAX_ARGUMENTS];
  ::wsprintf(buffer, TEXT("IDispatch::GetIDsOfNames(%s) failed 0x%8x"), ptName, hr);
  MessageBox(NULL, buffer, TEXT("Error"), MB_OK|MB_ICONERROR);
  return hr;
 }
 
 return InvokeByID(nType, pvResult, dispID, ptName);
}

 

// 设置调用参数
HRESULT VZ_AutoManager::SetInvokeParam(LONG cArgs, ...)
{
 // Argument List
 va_list marker;
 va_start(marker, cArgs);

 if(cArgs > m_lArgsCnt)
 {
  delete[] m_stuParam.rgvarg;
  delete[] m_stuParam.rgdispidNamedArgs;

  m_lArgsCnt+=VZ_MAX_ARGUMENTS;

  m_stuParam.rgvarg = new VARIANT[m_lArgsCnt];
  m_stuParam.rgdispidNamedArgs = new DISPID[m_lArgsCnt];
 }

 // Build DISPPARAMS
 for(int i=0; i<cArgs; i++)
 {
  m_stuParam.rgvarg[i] = va_arg(marker, VARIANT);
 }
 m_stuParam.cArgs = cArgs;

 va_end(marker);

 return S_OK;
}


HRESULT VZ_AutoManager::CreateInstance(CLSID clsid)
{
 HRESULT hr;
 hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&m_pDisp);

 if(FAILED(hr))
 {
  ::MessageBox(NULL, TEXT("Not Registered Properly!"), TEXT("Error"), MB_OK|MB_ICONERROR);
  return -1;
 }

 return S_OK;
}


HRESULT VZ_AutoManager::CreateInstance(LPCOLESTR ProgIDName)
{
 // Get CLSID
 CLSID clsid;
 HRESULT hr;
 
 // Get CLSID by ProgID(Name)
 hr = CLSIDFromProgID(ProgIDName, &clsid);
 if(FAILED(hr))
 {
  TCHAR buffer[VZ_MAX_ARGUMENTS];
  ::wsprintf(buffer, TEXT("CLSIDFromProgID(%s) failed"), ProgIDName);
  ::MessageBox(NULL, buffer, TEXT("Error"), MB_OK|MB_ICONERROR);
  return -1;
 }

 return CreateInstance(clsid);
}


HRESULT VZ_AutoManager::SetIDispatch(IDispatch* pDisp)
{
 if(pDisp == NULL)
  return -1;

 m_pDisp = pDisp;

 return S_OK;
}


HRESULT VZ_AutoManager::SetIDispatch(LPOLESTR ptName)
{
 IDispatch* m_pTempDisp;
 m_pTempDisp = GetIDispatch(ptName);
 if(!m_pTempDisp)
 {
  m_pDisp = m_pTempDisp;
  return -1;
 }
 return S_OK;
}


HRESULT VZ_AutoManager::SetIDispatch(DISPID dispID)
{
 IDispatch* m_pTempDisp;
 m_pTempDisp = GetIDispatch(dispID);
 if(!m_pTempDisp)
 {
  m_pDisp = m_pTempDisp;
  return -1;
 }
 return S_OK;
}


IDispatch* VZ_AutoManager::GetIDispatch()
{
 return m_pDisp;
}


IDispatch* VZ_AutoManager::GetIDispatch(LPOLESTR ptName)
{
 HRESULT hr;
 VARIANT varResult;

 if(ptName == NULL)
  return NULL;

 hr = SetInvokeParam(0);
 if(FAILED(hr))
  return NULL;

 hr = InvokeByName(DISPATCH_PROPERTYGET, &varResult, ptName);
 if(FAILED(hr))
  return NULL;

 return varResult.pdispVal;
}


IDispatch* VZ_AutoManager::GetIDispatch(DISPID dispID)
{
 HRESULT hr;
 VARIANT varResult;

 hr = SetInvokeParam(0);
 if(FAILED(hr))
  return NULL;

 hr = InvokeByID(DISPATCH_PROPERTYGET, &varResult, dispID);
 if(FAILED(hr))
  return NULL;

 return varResult.pdispVal;
}


/* VARIANT STRUCTURE
 *
 *  VARTYPE vt;
 *  WORD wReserved1;
 *  WORD wReserved2;
 *  WORD wReserved3;
 *  union {
 *    LONGLONG       VT_I8
 *    LONG           VT_I4
 *    BYTE           VT_UI1
 *    SHORT          VT_I2
 *    FLOAT          VT_R4
 *    DOUBLE         VT_R8
 *    VARIANT_BOOL   VT_BOOL
 *    SCODE          VT_ERROR
 *    CY             VT_CY
 *    DATE           VT_DATE
 *    BSTR           VT_BSTR
 *    IUnknown *     VT_UNKNOWN
 *    IDispatch *    VT_DISPATCH
 *    SAFEARRAY *    VT_ARRAY
 *    BYTE *         VT_BYREF|VT_UI1
 *    SHORT *        VT_BYREF|VT_I2
 *    LONG *         VT_BYREF|VT_I4
 *    LONGLONG *     VT_BYREF|VT_I8
 *    FLOAT *        VT_BYREF|VT_R4
 *    DOUBLE *       VT_BYREF|VT_R8
 *    VARIANT_BOOL * VT_BYREF|VT_BOOL
 *    SCODE *        VT_BYREF|VT_ERROR
 *    CY *           VT_BYREF|VT_CY
 *    DATE *         VT_BYREF|VT_DATE
 *    BSTR *         VT_BYREF|VT_BSTR
 *    IUnknown **    VT_BYREF|VT_UNKNOWN
 *    IDispatch **   VT_BYREF|VT_DISPATCH
 *    SAFEARRAY **   VT_BYREF|VT_ARRAY
 *    VARIANT *      VT_BYREF|VT_VARIANT
 *    PVOID          VT_BYREF (Generic ByRef)
 *    CHAR           VT_I1
 *    USHORT         VT_UI2
 *    ULONG          VT_UI4
 *    ULONGLONG      VT_UI8
 *    INT            VT_INT
 *    UINT           VT_UINT
 *    DECIMAL *      VT_BYREF|VT_DECIMAL
 *    CHAR *         VT_BYREF|VT_I1
 *    USHORT *       VT_BYREF|VT_UI2
 *    ULONG *        VT_BYREF|VT_UI4
 *    ULONGLONG *    VT_BYREF|VT_UI8
 *    INT *          VT_BYREF|VT_INT
 *    UINT *         VT_BYREF|VT_UINT
 *  }
 */

HRESULT VZ_AutoManager::SetParam(LONG cArgs,...)
{
 // Argument List
 va_list marker;
 va_start(marker, cArgs);

 if(cArgs > m_lArgsCnt)
 {
  delete[] m_stuParam.rgvarg;
  delete[] m_stuParam.rgdispidNamedArgs;

  m_lArgsCnt+=VZ_MAX_ARGUMENTS;

  m_stuParam.rgvarg = new VARIANT[m_lArgsCnt];
  m_stuParam.rgdispidNamedArgs = new DISPID[m_lArgsCnt];
 }

 // Build DISPPARAMS
 for(int i=0; i<cArgs; i++)
 {
  m_stuParam.rgvarg[i].vt = va_arg(marker, VARTYPE);

  switch(m_stuParam.rgvarg[i].vt)
  {
  case VT_I8:
   m_stuParam.rgvarg[i].llVal = va_arg(marker, LONGLONG);
   break;
  case VT_I4:
   m_stuParam.rgvarg[i].lVal = va_arg(marker, LONG);
   break;
  case VT_UI1:
   m_stuParam.rgvarg[i].bVal = va_arg(marker,BYTE);
   break;
  case VT_I2:
   m_stuParam.rgvarg[i].iVal = va_arg(marker,SHORT);
   break;
  case VT_R4:               
   m_stuParam.rgvarg[i].fltVal = va_arg(marker,FLOAT);
   break;
  case VT_R8:
   m_stuParam.rgvarg[i].dblVal = va_arg(marker,DOUBLE);
   break;
  case VT_BOOL:
   m_stuParam.rgvarg[i].boolVal = va_arg(marker,VARIANT_BOOL);
   break;
  case VT_ERROR:
   m_stuParam.rgvarg[i].scode = va_arg(marker,SCODE);
   break;
  case VT_CY:
   m_stuParam.rgvarg[i].cyVal = va_arg(marker,CY);
   break;
  case VT_DATE:
   m_stuParam.rgvarg[i].date = va_arg(marker,DATE);
   break;
  case VT_BSTR:
   m_stuParam.rgvarg[i].bstrVal = va_arg(marker,BSTR);
   break;
  case VT_UNKNOWN:
   m_stuParam.rgvarg[i].punkVal = va_arg(marker,IUnknown*);
   break;
  case VT_DISPATCH:
   m_stuParam.rgvarg[i].pdispVal = va_arg(marker,IDispatch*);
   break;
  case VT_ARRAY:
   m_stuParam.rgvarg[i].parray = va_arg(marker,SAFEARRAY*);
   break;
  case VT_BYREF|VT_UI1:             
   m_stuParam.rgvarg[i].pbVal = va_arg(marker,BYTE*);
   break;
  case VT_BYREF|VT_I2:
   m_stuParam.rgvarg[i].piVal = va_arg(marker,SHORT*);
   break;
  case VT_BYREF|VT_I4:
   m_stuParam.rgvarg[i].plVal = va_arg(marker,LONG*);
   break;
  case VT_BYREF|VT_I8:
   m_stuParam.rgvarg[i].pllVal = va_arg(marker,LONGLONG*);
   break;
  case VT_BYREF|VT_R4:
   m_stuParam.rgvarg[i].pfltVal = va_arg(marker,FLOAT*);
   break;
  case VT_BYREF|VT_R8:
   m_stuParam.rgvarg[i].pdblVal = va_arg(marker,DOUBLE*);
   break;
  case VT_BYREF|VT_BOOL:
   m_stuParam.rgvarg[i].pboolVal = va_arg(marker,VARIANT_BOOL*);
   break;
  case VT_BYREF|VT_CY:
   m_stuParam.rgvarg[i].pcyVal = va_arg(marker,CY*);
   break;
  case VT_BYREF|VT_DATE:
   m_stuParam.rgvarg[i].pdate = va_arg(marker,DATE*);
   break;
  case VT_BYREF|VT_BSTR:             
   m_stuParam.rgvarg[i].pbstrVal = va_arg(marker, BSTR *);
   break;
  case VT_BYREF|VT_UNKNOWN:
   m_stuParam.rgvarg[i].ppunkVal = va_arg(marker, IUnknown **);
   break;
  case VT_BYREF|VT_DISPATCH:
   m_stuParam.rgvarg[i].ppdispVal = va_arg(marker, IDispatch **);
   break;
  case VT_BYREF|VT_ARRAY:
   m_stuParam.rgvarg[i].pparray = va_arg(marker, SAFEARRAY **);
   break;
  case VT_BYREF|VT_VARIANT:
   m_stuParam.rgvarg[i].pvarVal = va_arg(marker, VARIANT *);
   break;
  case VT_BYREF:
   m_stuParam.rgvarg[i].byref = va_arg(marker, PVOID);
   break;
  case VT_I1:
   m_stuParam.rgvarg[i].cVal = va_arg(marker, CHAR);
   break;
  case VT_UI2:
   m_stuParam.rgvarg[i].uiVal = va_arg(marker, USHORT);
   break;
  case VT_UI4:
   m_stuParam.rgvarg[i].ulVal = va_arg(marker, ULONG);
   break;
  case VT_UI8:
   m_stuParam.rgvarg[i].ullVal = va_arg(marker, ULONGLONG);
   break;
  case VT_INT:   
   m_stuParam.rgvarg[i].intVal = va_arg(marker, INT);
   break;
  case VT_UINT:
   m_stuParam.rgvarg[i].uintVal = va_arg(marker, UINT);
   break;
  case VT_BYREF|VT_DECIMAL:
   m_stuParam.rgvarg[i].pdecVal = va_arg(marker, DECIMAL*);
   break;
  case VT_BYREF|VT_I1:
   m_stuParam.rgvarg[i].pcVal = va_arg(marker, CHAR *);
   break;
  case VT_BYREF|VT_UI2:
   m_stuParam.rgvarg[i].puiVal = va_arg(marker, USHORT*);
   break;
  case VT_BYREF|VT_UI4:
   m_stuParam.rgvarg[i].pulVal = va_arg(marker, ULONG *);
   break;
  case VT_BYREF|VT_UI8:
   m_stuParam.rgvarg[i].pullVal = va_arg(marker, ULONGLONG *);
   break;
  case VT_BYREF|VT_INT:
   m_stuParam.rgvarg[i].pintVal = va_arg(marker, INT *);
   break;
  case VT_BYREF|VT_UINT:
   m_stuParam.rgvarg[i].puintVal = va_arg(marker, UINT *);
   break;
  default:
   MessageBox(NULL, TEXT("This type is not allowed"),TEXT("Error"), MB_OK|MB_ICONERROR);
   return -1;
  }
 }
 m_stuParam.cArgs = cArgs;

 va_end(marker);

 return S_OK;
}

 

 

好了,基础的控制类写好了,现在通过继承它我们来写一个控制WORD的类.

 
//  VZ_AutoWord:Word自动化派生类
//  用于调用Word的自动化函数
//
//  Author: Vonger Zake
//  Date: 07.13.2007

 

#include "AutoManager.h"

#define VZ_AutoWord AutoWord

class VZ_AutoWord:VZ_AutoManager
{
public:
 VZ_AutoWord();
 ~VZ_AutoWord();

 //初始化相关接口
 HRESULT Init();
 //用Word打开指定文件
 HRESULT Open(TCHAR* FileName);

private:
 IDispatch *m_pApp;
 IDispatch *m_pDocs;
};

 

这个类比较简单,就两个函数一个初始化,一个用来打开Word

 

#include "stdafx.h"
#include "AutoWord.h"

#define SAFE_RELEASE(p) if(p){p->Release();p=NULL;}

VZ_AutoWord::VZ_AutoWord()
{
 CreateInstance(TEXT("Word.Application"));
 m_pApp = NULL;
 m_pDocs = NULL;
}

VZ_AutoWord::~VZ_AutoWord()
{
 SAFE_RELEASE(m_pApp);
 SAFE_RELEASE(m_pDocs);
}

HRESULT VZ_AutoWord::Init()
{
 m_pApp = GetIDispatch();
 if(m_pApp == NULL)
  return -1;

 m_pDocs = GetIDispatch(TEXT("Documents"));
 if(m_pDocs == NULL)
  return -1;

 return S_OK;
}

HRESULT VZ_AutoWord::Open(TCHAR *FileName)
{
 if(!m_pDocs||!m_pApp)
 {
  MessageBox(NULL, TEXT("AutoWord class must invoke Init() first!"), TEXT("Error"), MB_OK|MB_ICONERROR);
  return -1;
 }

 SetIDispatch(m_pDocs);
 {
  BSTR bstrFileName = ::SysAllocString(FileName);
  SetParam(1, VT_BSTR, bstrFileName);
  InvokeByName(DISPATCH_METHOD, NULL, TEXT("Open"));
  ::SysFreeString(bstrFileName);
 }

 SetIDispatch(m_pApp);
 {
  SetParam(1, VT_I4, 1);
  InvokeByName(DISPATCH_PROPERTYPUT, NULL, TEXT("Visible"));
 }
 return S_OK;
}

 

好了,最后一个文件~

int _stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
 AutoWord* autoword;
 autoword = new AutoWord;

 autoword->Init();
 autoword->Open(TEXT("C://me.xml"));

 delete autoword;

 return 0;
}

 

 

最后,啥都不说了,代码能告诉你一切~

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值