直接2D到XPS文件,无需打印队列

问题描述 投票:0回答:1

Direct2D 允许通过

ID2D1Device::CreatePrintControl
进行打印,这可能会将 XPS 渲染为中间表示形式。使用 XPS Document Writer 或其他打印机,我可以通过 Direct2D 重定向创建 xps 文件。我可以针对没有打印队列的 XPS 文档创建
ID2D1PrintControl
ID2D1DeviceContext
吗?

有没有我遗漏的

ID2D1DeviceMagic::CreatePrintControlOnStream(IStream* ...)
IPrintDocumentPackageTargetFactoryMagic::CreateOnXpsOM(IXpsOMPage* pPage, ...)

winapi direct2d xps
1个回答
0
投票

这不是魔法,但也差不多了。您可以自己实现 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;
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.