如何在CView的OnPreparePrinting()调用基类前判断页面方向?
问题
需要在CView的OnPreparePrinting()函数中调用基类(或显示任何对话框)之前,判断打印将采用横向(Landscape)还是纵向(Portrait)模式。尝试了两种方法但都存在问题:
- 始终返回纵向的方法(即使页面设置改为横向也无效):
// 即使在“页面设置”中改为横向,仍始终返回纵向的方法 BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo) { bool landscape=false; { CPrintDialog pd(TRUE); if (pd.GetDefaults()) { DEVMODE* pdevmode=pd.GetDevMode(); if (pdevmode) { landscape=(pdevmode->dmOrientation==DMORIENT_LANDSCAPE); } } } // ... }
- 首次调用失败但后续正常的方法:
// 首次调用theApp.CreatePrinterDC(dc)失败,但后续调用正常的方法 BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo) { bool landscape=false; { CDC dc; if (theApp.CreatePrinterDC(dc)) { pInfo->m_rectDraw.SetRect(0, 0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES)); if (pInfo->m_rectDraw.Width()>pInfo->m_rectDraw.Height()) { landscape=true; } dc.DeleteDC(); } } // .... }
请问在OnPreparePrinting()中调用基类(或显示任何对话框)之前,判断横向/纵向的正确方法是什么?
正确解决方案
直接从CPrintInfo关联的打印对话框对象中获取当前的DEVMODE结构即可,这是最可靠的方式,因为CPrintInfo已经维护了当前的打印设置上下文,无需额外创建对话框或打印机DC。
具体实现代码:
BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo) { bool landscape = false; // 从CPrintInfo的打印对话框实例中获取DEVMODE if (pInfo->m_pPD != nullptr) { DEVMODE* pDevMode = pInfo->m_pPD->GetDevMode(); if (pDevMode != nullptr) { landscape = (pDevMode->dmOrientation == DMORIENT_LANDSCAPE); } } // 此处根据landscape的值执行自定义逻辑 // ... // 最后调用基类的OnPreparePrinting return CView::OnPreparePrinting(pInfo); }
原方法问题分析
- 第一种方法:重新创建
CPrintDialog并调用GetDefaults(),只会读取打印机的出厂默认设置,而非用户之前在页面设置中修改的自定义配置,因此无法获取正确的横向/纵向状态。 - 第二种方法:首次调用
CreatePrinterDC失败是因为此时CPrintInfo的打印上下文尚未完成初始化,后续调用时上下文就绪才成功,但这种方式依赖时机且效率低下,不具备可靠性。
内容的提问来源于stack exchange,提问作者user3161924
相关产品推荐
相关产品推荐

