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

为何通过CPrintDialog::GetPrinterDC()获取的DC调用CDC::IsPrinting()返回FALSE?

为什么CDC::IsPrinting()对从CPrintDialog获取的DC返回FALSE?

你遇到的这个问题其实是MFC的CDC::IsPrinting()方法的设计逻辑导致的,先结合你的代码来拆解原因:

CPrintDialog pd ( TRUE , PD_RETURNDC );
if ( pd.DoModal () == IDOK ) {
    HDC hDC = pd.GetPrinterDC();
    CDC printDC;
    printDC.Attach ( hDC );
    /*...调用drawSomething(printDC)...*/
}

在drawSomething里调用DC.IsPrinting()却返回FALSE,核心原因如下:

原因分析

CDC::IsPrinting()本质是返回其内部的m_bPrinting成员变量值,这个变量默认是FALSE。只有当CDC对象是通过MFC打印框架初始化时(比如OnPrint函数中传递的CDC、或者调用CDC::StartDoc启动打印作业后),MFC才会自动把m_bPrinting设为TRUE。

而你通过CPrintDialog::GetPrinterDC()拿到的是一个原始的打印机HDC,手动Attach到空的CDC对象上时,MFC并不会自动设置m_bPrinting为TRUE——因为这个CDC只是简单封装了打印机句柄,并没有关联到MFC的打印上下文流程里。

解决办法

有两种实用的解决思路:

方法1:手动标记打印状态(派生CDC类)

因为m_bPrinting是CDC的protected成员,你可以派生一个自定义CDC类,添加方法来修改这个变量:

class CMyPrintDC : public CDC
{
public:
    void SetPrinting(bool bPrinting) { m_bPrinting = bPrinting; }
};

然后替换原有代码使用:

if ( pd.DoModal () == IDOK ) {
    HDC hDC = pd.GetPrinterDC();
    CMyPrintDC printDC;
    printDC.Attach ( hDC );
    printDC.SetPrinting(TRUE); // 手动设置打印状态
    drawSomething(printDC);
}

这样IsPrinting()就会返回TRUE了。

方法2:直接判断DC是否为打印机设备

如果不想派生类,也可以跳过IsPrinting(),直接通过Windows API判断设备类型:

void drawSomething ( CDC& DC ) {
    int deviceTech = DC.GetDeviceCaps(TECHNOLOGY);
    if (deviceTech == DT_RASPRINTER) {
        //仅针对打印机的特殊绘图
    }
    //标准绘图
}

GetDeviceCaps(TECHNOLOGY)会返回设备类型,DT_RASPRINTER代表打印机设备,这种判断更直接,也不依赖MFC内部状态。

额外提示

其实CPrintDialog在PD_RETURNDC标志下,m_pd.hDC也持有这个打印机DC,你直接用pd.m_pd.hDC来Attach效果和GetPrinterDC()一致,但本质问题还是一样的,需要手动处理打印状态或用API判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:07:48