科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件VC中基于CEditView的打印和打印预览设计

VC中基于CEditView的打印和打印预览设计

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在CEditView框架基础上进行程序设计,即可起到事半功倍的效果

作者:丁有和 来源:yesky 2007年11月16日

关键字: VC CEditView 打印预览 设计

  • 评论
  • 分享微博
  • 分享邮件
Visual C++中的MFC文档视图结构为我们提供了打印和打印预览程序结构框架,使得我们只需在OnPrint或OnDraw等重载函数中添加相关代码就可实现文档内容或图像的打印和打印预览功能。但是,如果程序仅仅是用来实现ASCII文档内容的显示和打印,那么就没有必要从头开始,若能在CEditView框架基础上进行程序设计,即可起到事半功倍的效果。

  一、 CEditView程序框架的功能特点

  在用MFC AppWizard(exe)创建一个单文档或多文档应用程序的过程中,若在向导的第六步将视图类的基类选定为CEditView,那么该应用程序就具有文档的自动显示、编辑、查找和替换、剪贴板的剪切、复制和粘贴、打印以及打印预览等功能。(作为示例,设这里创建的是单文档应用程序Ex_Prn1)

  但是,CEditView也存在下列缺陷:

   (1) CEditView不具有所见即所得编辑功能。

   (2) CEditView只能将文本作单一字体的显示,不支持特殊格式的字符。

   (3) CEditView可以容纳的文本总数有限,在32位Windows中最多不超过1M。

   (4) 打印和打印预览功能还很勉强。

  因此,很有必要在CEditView基础上进行更深入的程序设计,尤其是在打印和打印预览方面。

  二、 打印和打印预览的程序设计

  完整的打印和打印预览设计工作包括控制页边距和行距、设计页眉页脚、控制打印字体、选择打印模式、多页打印以及预览功能实现等。好在CEditView已经实现了多页打印和预览功能,因此,我们只要在此基础上添加页边距设置、页眉页脚以及控制打印字体等功能,就一定能满足绝大多数ASCII文档打印的需要。

  1.设置页边距

  页边距是指打印的文本区域与打印纸边界之间的距离,包括左、右、上和下边距。设置时可参考CPrintInfo的成员变量m_rectDraw的数值,但m_rectDraw的数值表示的是有效打印区域,它本身与打印纸边界有一定的边距,这个边距是打印机自身造成的,因此称之为物理边距,并且这些物理边距在不同大小的纸张中是不一样的,因此首先要获取这些数值。这时就需要调用全局函数GetDeviceCaps,它的原型如下:

int GetDeviceCaps( HDC hdc, int nIndex);

  其中,hdc用来指定设备环境句柄,nIndex用来指定要获取的参量索引,对于打印机而言,它常常需要下列的预定义值:

   LOGPIXELSX   打印机水平分辨率

   LOGPIXELSY   打印机垂直分辨率

   PHYSICALWIDTH  打印纸的实际宽度

   PHYSICALHEIGHT 打印纸的实际高度

   PHYSICALOFFSETX 实际可打印区域的物理左边距

   PHYSICALOFFSETY 实际可打印区域的物理上边距

  需要说明的是,若一张打印纸的大小为A4(210 x 297毫米),且打印机的分辨率为300 x 300dpi,当指定函数的参数值为PHYSICALWIDTH时,则返回的值不是210毫米,而是2480。这个结果是这样计算来的:首先将毫米单位转换成英寸,即210毫米变成8.267英寸,然后乘以300dpi。

  下面的函数代码就是用来设置页边距,并且还计算页面的物理边距:

void CEx_Prn1View::SetPageMargin(CDC *pDC, CPrintInfo *pInfo, int l, int t, int r, int b)
// l, t, r, b分别表示左上右下边距, 单位为0.1mm
{
int nOldMode = pDC->GetMapMode();
pDC->SetMapMode(MM_LOMETRIC);
// 计算一个设备单位等于多少0.1mm
double scaleX = 254.0 / (double)GetDeviceCaps(
pDC->m_hAttribDC, LOGPIXELSX);
double scaleY = 254.0 / (double)GetDeviceCaps(
pDC->m_hAttribDC, LOGPIXELSY);
int x = GetDeviceCaps(pDC->m_hAttribDC,
PHYSICALOFFSETX);
int y = GetDeviceCaps(pDC->m_hAttribDC,
PHYSICALOFFSETY);
int w = GetDeviceCaps(pDC->m_hAttribDC,
PHYSICALWIDTH);
int h = GetDeviceCaps(pDC->m_hAttribDC,
PHYSICALHEIGHT);
int nPageWidth = (int)((double)w*scaleX + 0.5);
// 纸宽,单位0.1mm
int nPageHeight = (int)((double)h*scaleY + 0.5);
// 纸高,单位0.1mm
m_nPhyLeft = (int)((double)x*scaleX + 0.5);
// 物理左边距,单位0.1mm
m_nPhyTop = (int)((double)y*scaleY + 0.5);
// 物理上边距,单位0.1mm
pDC->DPtoLP(&pInfo->m_rectDraw);
CRect rcTemp = pInfo->m_rectDraw;
rcTemp.NormalizeRect();
m_nPhyRight = nPageWidth - rcTemp.Width() -
m_nPhyLeft; // 物理右边距,单位0.1mm
m_nPhyBottom = nPageHeight - rcTemp.Height() -
m_nPhyTop; // 物理下边距,单位0.1mm
// 若边距小于物理边距,则调整它们
if (l < m_nPhyLeft) l = m_nPhyLeft;
if (t < m_nPhyTop) t = m_nPhyTop;
if (r < m_nPhyRight) r = m_nPhyRight;
if (b < m_nPhyBottom) b = m_nPhyBottom;
// 计算并调整pInfo->m_rectDraw的大小
pInfo->m_rectDraw.left = l - m_nPhyLeft;
pInfo->m_rectDraw.top = - t + m_nPhyTop;
pInfo->m_rectDraw.right -= r - m_nPhyRight;
pInfo->m_rectDraw.bottom += b - m_nPhyBottom;
pDC->LPtoDP(&pInfo->m_rectDraw);
pDC->SetMapMode(nOldMode);
// 恢复原来的映射模式
}

  需要说明的是,由于CEditView中的设置环境映射模式是MM_TEXT,即逻辑坐标和设备坐标相同,因此需要通过LPtoDP和DPtoLP函数在逻辑坐标(LP)和设备坐标(DP)之间进行转换。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章