Direct2D 允许通过
ID2D1Device::CreatePrintControl
进行打印,这可能会将 XPS 渲染为中间表示形式。使用 XPS Document Writer 或其他打印机,我可以通过 Direct2D 重定向创建 xps 文件。我可以针对没有打印队列的 XPS 文档创建 ID2D1PrintControl
或 ID2D1DeviceContext
吗?
有没有我遗漏的
ID2D1DeviceMagic::CreatePrintControlOnStream(IStream* ...)
或IPrintDocumentPackageTargetFactoryMagic::CreateOnXpsOM(IXpsOMPage* pPage, ...)
?
这不是魔法,但也差不多了。您可以自己实现 IPrintDocumentPackageTarget COM 接口,并在调用 ID2D1Device::CreatePrintControl 方法时使用它。
在您的实现中,您可以将工作委托给 IXpsOMObjectFactory::CreatePackageWriterOnStream 方法,因此,它可以是这样的:
CTarget *target = new CTarget();
auto hr = d2dDevice->CreatePrintControl(
wicFactory,
target, // use my own target
nullptr,
&printControl
);
delete target;
这是实现
CTarget
和 IPrintDocumentPackageTarget
:的
IXpsDocumentPackageTarget
示例类
// needs <initguid.h>, <shlwapi.h> and shlwapi.lib
class CTarget : public IPrintDocumentPackageTarget, IXpsDocumentPackageTarget
{
// make sure this get release *before* CoUninitialize call
CComPtr<IXpsOMObjectFactory> _factory; // uses ATL needs <atlbase.h>
public:
CTarget() {}
STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
{
static QITAB rgqit[] =
{
QITABENT(CTarget, IPrintDocumentPackageTarget),
QITABENT(CTarget, IXpsDocumentPackageTarget),
{ 0},
};
return QISearch(this, rgqit, riid, ppv);
}
// for testing we just send something static
STDMETHODIMP_(ULONG) AddRef() { return 1; }; STDMETHODIMP_(ULONG) Release() { return 1; };
// IPrintDocumentPackageTarget
STDMETHODIMP GetPackageTargetTypes(UINT32* targetCount, GUID** targetTypes)
{
if (!targetCount || !targetTypes) return E_INVALIDARG;
*targetTypes = (GUID*)CoTaskMemAlloc(sizeof(GUID));
if (!*targetTypes)
{
*targetCount = 0;
return E_OUTOFMEMORY;
}
*targetCount = 1;
**targetTypes = ID_DOCUMENTPACKAGETARGET_MSXPS;
return S_OK;
}
STDMETHODIMP GetPackageTarget(REFGUID guidTargetType, REFIID riid, void** ppvTarget)
{
if (guidTargetType == ID_DOCUMENTPACKAGETARGET_MSXPS)
return QueryInterface(riid, ppvTarget);
return E_FAIL;
}
STDMETHODIMP Cancel()
{
return S_OK;
}
// IXpsDocumentPackageTarget
STDMETHODIMP GetXpsOMPackageWriter(IOpcPartUri* documentSequencePartName, IOpcPartUri* discardControlPartName, IXpsOMPackageWriter** packageWriter)
{
// here you can create your own stream, file, memory, etc.
CComPtr<IStream> stream;
SHCreateStreamOnFile(L"c:\\temp\\d2d1.xps", STGM_CREATE | STGM_WRITE, &stream);
// ... and delegate to factory w/o more effort
// you can also configure custom properties, etc.
return _factory->CreatePackageWriterOnStream(stream, FALSE, XPS_INTERLEAVING_OFF, documentSequencePartName, nullptr, nullptr, nullptr, discardControlPartName, packageWriter);
}
STDMETHODIMP GetXpsOMFactory(IXpsOMObjectFactory** xpsFactory)
{
HRESULT hr = S_OK;
if (!_factory)
{
if (FAILED(hr = _factory.CoCreateInstance(CLSID_XpsOMObjectFactory)))
return hr;
}
return _factory.QueryInterface(xpsFactory);
}
STDMETHODIMP GetXpsType(XPS_DOCUMENT_TYPE* documentType)
{
if (!documentType) return E_INVALIDARG;
*documentType = XPS_DOCUMENT_TYPE_XPS;
return S_OK;
}
};