总是碰到各种PDF相关的转换问题。故记录一二,以作总结。
此处是借助Acrobat来进行转换,首先要安装Acrobat,装完后,系统中会有Acrobat 的COM库,同时,安装目录下有一个Acrobat.tlb和Acrobat.dll文件,这都是我们所需要的。
1.建立C++工程,将tlb添加到工程中(为了方便使用,其实不添加也可以)。在代码中#import "Acrobat.tlb"。
2.定义两个类成员变量:
Acrobat::CAcroAppPtr acrapp;
Acrobat::CAcroPDDocPtr acrdoc;
3.在类构造函数中,对COM进行初始化,同时初始化以上两个变量,析构函数反之(这里COM初始化和卸载因实际需要而谨慎处理):
CSigner()
: strError(L"")
, acrapp(NULL)
, acrdoc(NULL)
{
::CoInitialize(NULL);
}
~CSigner()
{
::CoUninitialize();
}
4.在类的初始化函数中,创建COM实例:
if(NULL == acrapp)
{
acrapp.CreateInstance(Acrobat::CLSID_AcroApp);
acrapp->Hide(&ret);
}
if(NULL == acrdoc)
{
acrdoc.CreateInstance(Acrobat::CLSID_AcroPDDoc);
}
5.关键部分来了。调用Acrobat COM组件的SaveAs方法,做“另存为”操作,即可将PDF转为其它格式(具体格式字符串网上可查):
// TODO: 在此添加实现代码
HRESULT hr = S_OK;
try
{
VARIANT_BOOL ret = VARIANT_TRUE;
hr = acrdoc->Open(strPdfPath, &ret);
if(FAILED(hr))throw (hr);
IDispatch FAR* jso = NULL;
hr = acrdoc->GetJSObject(&jso);
if(FAILED(hr))throw (hr);
DISPID dispId;
OLECHAR FAR* szMember = L"SaveAs";
hr = jso->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispId);
if(FAILED(hr))throw (hr);
DISPPARAMS dispParams;
memset(&dispParams, 0, sizeof(dispParams));
dispParams.cArgs = 2;
CComVariant* pVars = new CComVariant[2];
pVars[1] = strTifPath;
pVars[0] = L"com.adobe.acrobat.tiff";
pVars[1].ChangeType(VT_BSTR);
pVars[0].ChangeType(VT_BSTR);
dispParams.rgvarg = pVars;
dispParams.cNamedArgs = 0;
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof(excepInfo));
CComVariant vaResult;
UINT nArgErr = (UINT)-1;
hr = jso->Invoke(dispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispParams, &vaResult, &excepInfo, &nArgErr);
delete[] pVars;
*state = hr;
return hr;
}
catch(_com_error ce)
{
strError = ce.ErrorMessage();
*state = hr;
return S_FALSE;
}
catch(...)
{
*state = hr;
return S_OK;
}
第5步骤同时也展示了C++中调用JSObject的方法,即使用最原始的COM调用手段,MSDN上也有说明,但很不详细。