You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PrintDlgEx调用返回E_INVALIDARG错误,PrintDlg正常工作求排查

问题

项目中需要使用PrintDlgEx,但无论采用何种参数组合(包括微软官方示例的配置),调用后始终返回E_INVALIDARG错误。换成PRINTDLG结构体和PrintDlg函数(移除PrintDlgEx专属参数)就能正常运行。

因为设计和预览需求,必须用PrintDlgEx来获取Apply按钮功能,实现不打印时修改打印机或属性表的需求。

以下是简化后的测试代码,目前无法弹出对话框,求排查原因:

#include <QDebug>
#include <QWindow>
#include <windows.h>
void showPrintDialog()
{
    // Simplifying the setup: real code passes in a QWidget *
    QWidget *caller = this;
    // Not returning a value or doing any work. I just want the dialog to pop up for now

    // Create the standard windows print dialog
    PRINTDLGEX printDialog;
    memset(&printDialog, 0, sizeof(PRINTDLGEX));
    printDialog.lStructSize = sizeof(PRINTDLGEX);

    printDialog.Flags = PD_RETURNDC |           // Return a printer device context. Without this, HDC may be undefined
                        PD_USEDEVMODECOPIESANDCOLLATE |
                        PD_NOSELECTION |        // Don't allow selecting individual document pages to print
                        PD_NOPAGENUMS |         // Disables some boxes
                        PD_NOCURRENTPAGE |      // Disables some boxes
                        PD_NONETWORKBUTTON |    // Don't allow networking  (but it show "Find printer") so what does this do ?
                        PD_HIDEPRINTTOFILE;     // Don't allow print to file

    // Only on PRINTDLGEX
        // Theis block copied from https://learn.microsoft.com/en-us/windows/win32/dlgbox/using-common-dialog-boxes?redirectedfrom=MSDN
        // I have tried multiple combinations of options, including none, I really don't want any of them
        printDialog.nStartPage = START_PAGE_GENERAL;
        printDialog.nPageRanges = 1;
        printDialog.nMaxPageRanges = 10;
        LPPRINTPAGERANGE pageRange = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
        printDialog.lpPageRanges = pageRange;
        printDialog.lpPageRanges[0].nFromPage = 1;
        printDialog.lpPageRanges[0].nToPage = 1;
        printDialog.Flags2 = 0;
        printDialog.ExclusionFlags = 0;
        printDialog.dwResultAction = 0; // This will tell me if PRINT

        // Rest of options are also on PRINTDLG
        printDialog.nMinPage = 1;
        printDialog.nMaxPage = 10;

    // The only options I really need
    printDialog.nCopies = 1;
    printDialog.hDevMode = Q_NULLPTR;   // which will be better once this works
    printDialog.hDevNames = Q_NULLPTR;   // which will be better once this works
    printDialog.hwndOwner = reinterpret_cast<HWND>(caller->windowHandle()->winId());

    // Calling...
    int result = PrintDlgEx(&printDialog);
    qDebug() << (result == E_INVALIDARG ? "Invalid Argument" : "Success");

    // It always is E_INVALIDARG

    // Cleanup
    if (printDialog.hDevMode)
       GlobalFree(printDialog.hDevMode);
    if (printDialog.hDevNames)
       GlobalFree(printDialog.hDevNames);
    if (printDialog.hDC)
       DeleteDC(printDialog.hDC);
}

平台信息:Windows 10最新版本;Qt版本5.12.7及以上(测试环境为5.15.1)

排查与解决

核心问题

你设置的Flags中包含PD_NOPAGENUMS,但同时又初始化了nPageRanges、lpPageRanges等页码范围相关参数,这两者冲突。PD_NOPAGENUMS的作用是禁用页码选择功能,此时系统不允许提供页码范围数据,否则会直接返回E_INVALIDARG错误。

修复方案

任选以下一种方式修改:

  1. 移除PD_NOPAGENUMS标志,保留页码范围参数(适合需要用户选择页码的场景)
  2. 保留PD_NOPAGENUMS,同时删除所有页码范围相关的初始化代码(包括nStartPage、nPageRanges、nMaxPageRanges、lpPageRanges的分配与赋值)

额外注意事项

  • 代码中用GlobalAlloc分配的pageRange未在清理阶段释放,需添加GlobalFree(pageRange);避免内存泄漏。
  • 确认caller->windowHandle()->winId()能获取到有效HWND,可通过qDebug()输出该值验证是否非空。

修改后的示例代码(保留PD_NOPAGENUMS的情况)

#include <QDebug>
#include <QWindow>
#include <windows.h>
void showPrintDialog()
{
    QWidget *caller = this;

    PRINTDLGEX printDialog;
    memset(&printDialog, 0, sizeof(PRINTDLGEX));
    printDialog.lStructSize = sizeof(PRINTDLGEX);

    printDialog.Flags = PD_RETURNDC |
                        PD_USEDEVMODECOPIESANDCOLLATE |
                        PD_NOSELECTION |
                        PD_NOCURRENTPAGE |
                        PD_NONETWORKBUTTON |
                        PD_HIDEPRINTTOFILE;

    // 移除所有页码范围相关参数的初始化
    printDialog.Flags2 = 0;
    printDialog.ExclusionFlags = 0;
    printDialog.dwResultAction = 0;

    printDialog.nMinPage = 1;
    printDialog.nMaxPage = 10;
    printDialog.nCopies = 1;
    printDialog.hDevMode = Q_NULLPTR;
    printDialog.hDevNames = Q_NULLPTR;
    printDialog.hwndOwner = reinterpret_cast<HWND>(caller->windowHandle()->winId());

    int result = PrintDlgEx(&printDialog);
    qDebug() << (result == E_INVALIDARG ? "Invalid Argument" : "Success");

    // 清理资源
    if (printDialog.hDevMode)
       GlobalFree(printDialog.hDevMode);
    if (printDialog.hDevNames)
       GlobalFree(printDialog.hDevNames);
    if (printDialog.hDC)
       DeleteDC(printDialog.hDC);
}

内容的提问来源于stack exchange,提问作者Thalia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 22:10:24