最近有位朋友向我问关于自动化方面的问题,两年都没用过了,于是翻出原来的代码~自动化的调用方法有很多种,我使用的是最接近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;
}
最后,啥都不说了,代码能告诉你一切~
本文介绍了一个使用C++自动化技术来读取XML文件的简单过程,通过创建一个自动化管理类VZ_AutoManager,并派生出VZ_AutoWord类来控制Word应用程序,实现打开XML文件的功能。

2534

被折叠的 条评论
为什么被折叠?



