使用 IPrintDialogCallback::SelectionChange() 获取和更改打印机设置时如何使用 IPrintDialogServices 接口?

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

请告诉我在使用

IPrintDialogServices
获取和更改打印机设置时如何使用
IPrintDialogCallback::SelectionChange
界面。

我正在尝试使用这个构造,但我不明白如何初始化

IPrintDialogServices

struct PrintDialogCallback : public IPrintDialogCallback
{
public:
    PrintDialogCallback()
    {}
private:
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv) noexcept final {
        if (riid == IID_IUnknown || riid == IID_IPrintDialogCallback) {
            *ppv = static_cast<IPrintDialogCallback*>(this);
            AddRef();
            return S_OK;
        }
        *ppv = nullptr;
        return E_NOINTERFACE;
    }
    virtual ULONG STDMETHODCALLTYPE AddRef() noexcept final {
        return 1;
    }
    virtual ULONG STDMETHODCALLTYPE Release() noexcept final {
        return 1;
    }
    virtual HRESULT STDMETHODCALLTYPE HandleMessage(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
                                                       LRESULT *pResult) noexcept final {
        return S_FALSE;
    }
    virtual HRESULT STDMETHODCALLTYPE InitDone() noexcept final {
        return S_FALSE;
    }
    virtual HRESULT STDMETHODCALLTYPE SelectionChange() noexcept final {
        IPrintDialogServices *pServices = nullptr;
        // ? how to init pServices ?
        if (pServices) {
            wchar_t printerName[256] = {};
            UINT psize = ARRAYSIZE(printerName);
            HRESULT hr = pServices->GetCurrentPrinterName(printerName, &psize);
            if (SUCCEEDED(hr)) {
                wprintf(L"Selected printer: %s\n", printerName);
            }
            // Other settings
            // DEVMODE *pDevMode = ...;
            // UINT pcbSize = sizeof(DEVMODE);
            // hr = pServices->GetCurrentDevMode(pDevMode, &pcbSize);
            // if (SUCCEEDED(hr) && pDevMode) {
            //     wprintf(L"Printer paper size: %d\n", pDevMode->dmPaperSize);
            // }
            pServices->Release();
        }
        return S_FALSE;
    }
};
c++ winapi
1个回答
1
投票

根据

PRINTDLGEX
文档

lpCallback

类型:LPUNKNOWN

指向应用程序定义的回调对象的指针。

该对象应包含

IPrintDialogCallback
类,以接收常规页面下部子对话框的消息。

回调对象还应包含

IObjectWithSite
类,以接收指向
IPrintDialogServices
接口的指针。
PrintDlgEx
函数在
IUnknown::QueryInterface
IID_IPrintDialogCallback
的回调对象上调用
IID_IObjectWithSite
来确定哪个支持接口。

如果您不想检索任何回调信息,请将

lpCallback
设置为 NULL。

根据

IPrintDialogCallback::InitDone()
文档

如果您的回调对象实现了

IObjectWithSite
接口,则
PrintDlgEx
函数会调用
IObjectWithSite::SetSite
方法以将
IPrintDialogServices
指针传递给回调对象。
PrintDlgEx
函数称为在调用
IObjectWithSite::SetSite
方法之前先调用
InitDone
方法。这使您的
InitDone
实现能够使用
IPrintDialogServices
方法来检索有关当前所选打印机的信息。

例如:

struct PrintDialogCallback : public IObjectWithSite, public IPrintDialogCallback
{
private:
    IUnknown* m_Site = nullptr;
    IPrintDialogServices* m_Services = nullptr;

public:
    PrintDialogCallback() = default;
    ~PrintDialogCallback() { SetSite(nullptr); }

    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv) noexcept final {
        if (riid == IID_IUnknown) {
            *ppv = static_cast<IUnknown*>(static_cast<IPrintDialogCallback*>(this));
            AddRef();
            return S_OK;
        }
        else if (riid == IID_IObjectWithSite) {
            *ppv = static_cast<IObjectWithSite*>(this);
            AddRef();
            return S_OK;
        }
        else if (riid == IID_IPrintDialogCallback) {
            *ppv = static_cast<IPrintDialogCallback*>(this);
            AddRef();
            return S_OK;
        }
        *ppv = nullptr;
        return E_NOINTERFACE;
    }

    virtual ULONG STDMETHODCALLTYPE AddRef() noexcept final {
        return 1;
    }

    virtual ULONG STDMETHODCALLTYPE Release() noexcept final {
        return 1;
    }

    virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite) noexcept final {
        if (m_Site)
            return m_Site->QueryInterface(riid, ppvSite);
        *ppvSite = nullptr;
        return E_NOINTERFACE;
    }

    virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite) noexcept final {
        if (m_Services) {
            m_Services->Release();
            m_Services = nullptr;
        }
        if (m_Site) {
            m_Site->Release();
            m_Site = nullptr;
        }
        if (pUnkSite) {
            m_Site = pUnkSite;
            m_Site->AddRef();
            m_Site->QueryInterface(IID_PPV_ARGS(&m_Services));
        }
        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE HandleMessage(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
                                                       LRESULT *pResult) noexcept final {
        return S_FALSE;
    }

    virtual HRESULT STDMETHODCALLTYPE InitDone() noexcept final {
        return S_FALSE;
    }

    virtual HRESULT STDMETHODCALLTYPE SelectionChange() noexcept final {
        if (m_Services) {
            wchar_t printerName[256] = {};
            UINT psize = ARRAYSIZE(printerName);
            HRESULT hr = m_Services->GetCurrentPrinterName(printerName, &psize);
            if (SUCCEEDED(hr)) {
                wprintf(L"Selected printer: %s\n", printerName);
            }
            // Other settings
            // DEVMODE *pDevMode = ...;
            // UINT pcbSize = sizeof(DEVMODE);
            // hr = m_Services->GetCurrentDevMode(pDevMode, &pcbSize);
            // if (SUCCEEDED(hr) && pDevMode) {
            //     wprintf(L"Printer paper size: %d\n", pDevMode->dmPaperSize);
            // }
            // ...
        }
        return S_FALSE;
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.