How to print the content of a Rich Edit Control

本文介绍如何实现富文本编辑控件的内容打印,包括设置目标设备、确定打印范围及实际绘制过程。作者解决了实际打印问题,但指出预览功能仍存在问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

How to print the content of a Rich Edit Control

By Roger Allen

Introduction

I see many questions about printing, when helping people on the VC++ forum here at CP, but the one thing I have never been able to help people with, was printing the content of a Rich Edit Control. So off I went to the documentation to try and do something about it.

So how did I do?

  • Yes, you can print a Rich Edit Control
  • But the print preview sucks

I will be continuing to look into the print preview problems with the Rich Edit Control, but in the meantime, I though I would make available my solution to actual printing.

What to do to get a Rich Edit Control to print?

A Rich Edit Control has built in support for printing, but it is covered by a number of functions which have to be used in the correct way to get output on your target printer DC. These 3 functions are:

  • SetTargetDevice()

    This function in effect attaches the printer DC to the Rich Edit control, until you do another call to this function passing NULL as the new HDC.

  • FormatRange()

    This procedure looks at the start/end characters provided and see what part of the control's content will be visible in the output range.

  • DisplayBand()

    This procedure actually does the plotting of the output.

What steps do I need to take?

First you need to determine how many pages of output you are going to require for your printout. This will depend on the control content and the printable area of the paper etc. My example assumes that the Rich Edit Control will print all its content and have all of every page to print to when generating output, so this is how I calculate the number of pages:

BOOL CRichEditPrintView::OnPreparePrinting(CPrintInfo* pInfo)
{
CDC dc;
CRect page;
FORMATRANGE fmtRange;
long lLineWidth;
int last = 0;

AfxGetApp()->CreatePrinterDC(dc);
if (!dc.m_hDC)
{
TRACE("Failed to get printer DC/n");
return FALSE;
}
dc.SaveDC();

pInfo->SetMaxPage(0);
// get the page size in twips (1440 twips/inch)

page.left = 0;
page.top = 0;
page.right = ::MulDiv(dc.GetDeviceCaps(PHYSICALWIDTH),
1440, dc.GetDeviceCaps(LOGPIXELSX));
page.bottom = ::MulDiv(dc.GetDeviceCaps(PHYSICALHEIGHT),
1440, dc.GetDeviceCaps(LOGPIXELSY));
lLineWidth = ::MulDiv(dc.GetDeviceCaps(PHYSICALWIDTH),
1440, dc.GetDeviceCaps(LOGPIXELSX));
// setup the format range attributes

fmtRange.hdc = dc.m_hDC;
fmtRange.hdcTarget = dc.m_hAttribDC;
fmtRange.rc = page;
fmtRange.rcPage = page;

// determine the correct output for this page

m_Control.SetTargetDevice(dc, lLineWidth);
while (last < m_Control.GetTextLength())
{
fmtRange.chrg.cpMin = last;
fmtRange.chrg.cpMax = -1;
// measure the data that goes on this page


// just measuring, not displaying

last = m_Control.FormatRange(&fmtRange, FALSE);
fmtRange.chrg.cpMax = last;
pInfo->SetMaxPage(pInfo->GetMaxPage() + 1);
}
m_Control.FormatRange(NULL, FALSE);
// release the cached DC information stored in SetTargetDevice

dc.RestoreDC(-1);
dc.DeleteDC();
return DoPreparePrinting(pInfo);
}

This should give us the correct number of pages of output for the content.

Do the OnPrint() version

The actual version that does the printing is very similar except that:

  • It skips over pages already printed.
  • It prints the output.

The code looks like:

void CRichEditPrintView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
long lLineWidth = ::MulDiv(pDC->GetDeviceCaps(PHYSICALWIDTH),
1440, pDC->GetDeviceCaps(LOGPIXELSX));
FORMATRANGE fmtRange;
CRect rect;
CRect page;
int last = 0;

// get the page size in twips (1440 twips/inch)

page.left = 0;
page.top = 0;
page.right = ::MulDiv(pDC->GetDeviceCaps(PHYSICALWIDTH),
1440, pDC->GetDeviceCaps(LOGPIXELSX));
page.bottom = ::MulDiv(pDC->GetDeviceCaps(PHYSICALHEIGHT),
1440, pDC->GetDeviceCaps(LOGPIXELSY));
// for our example, the rect is the page

rect = page;

// setup the format range attributes

fmtRange.hdc = pDC->m_hDC;
fmtRange.hdcTarget = pDC->m_hAttribDC;
fmtRange.rc = rect;
fmtRange.rcPage = page;

pDC->SaveDC();
// determine the correct output for this page

m_Control.SetTargetDevice(*pDC, lLineWidth);
for (UINT i = 0 ; i < pInfo->m_nCurPage ; i++)
{
fmtRange.chrg.cpMin = last;
fmtRange.chrg.cpMax = -1;
// measure the data that goes on this page


// just measuring, not displaying

last = m_Control.FormatRange(&fmtRange, TRUE);
fmtRange.chrg.cpMax = last;
// when we drop out of the loop, we should

//print the correct part of the output for the current page

}
m_Control.DisplayBand(&rect);
m_Control.FormatRange(NULL, FALSE);
// release the cached DC information stored in SetTargetDevice

pDC->RestoreDC(-1);
}

And that's it basically.

Problems, problems, problems

As mentioned earlier, the print preview of the output sucks due to the Rich Edit Control not scaling the font(s) and spacing the text correctly for the Screen DC used during the preview process. I will be continuing to look into this. My best guess at the moment may be to implement a complete RTF output library, that will be able to plot the RTF text correctly for preview and print, but its a lot of work.

Enjoy - or not when it comes to Rich Edit Controls.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Roger Allen


A research and development programmer working for a pharmaceutical instrument company.

I am one of those lucky people who enjoys his work and spends more time than he should either doing work or reseaching new stuff. I can also be found on the odd counter-strike server sometimes, or playing DDO on the european Devourer server (Send a tell to "Ordinary" who is my current main)

I am also a keep fit fanatic, doing cross country running and am seriously into [url]http://www.ryushinkan.co.uk/[/url] Karate at this time of my life, training from 4-6 times a week.

Apart from computer games and fitness, I also enjoy Juggeling, unicycling and other circus type skills.

I also have 2 step daughters, aged 21 and 23. They are both nice girls, but expensive to keep in food/clothes/mobile phones/cello's/travel etc, Plus I get insulted by them a lot!

Occupation: Software Developer (Senior)
Company: Sirius Analytical Instruments
Location: United Kingdom United Kingdom

From: http://www.codeproject.com/KB/printing/richeditprint.aspx
内容概要:本文档详细介绍了Analog Devices公司生产的AD8436真均方根-直流(RMS-to-DC)转换器的技术细节及其应用场景。AD8436由三个独立模块构成:轨到轨FET输入放大器、高动态范围均方根计算内核和精密轨到轨输出放大器。该器件不仅体积小巧、功耗低,而且具有广泛的输入电压范围和快速响应特性。文档涵盖了AD8436的工作原理、配置选项、外部组件选择(如电容)、增益调节、单电源供电、电流互感器配置、接地故障检测、三相电源监测等方面的内容。此外,还特别强调了PCB设计注意事项和误差源分析,旨在帮助工程师更好地理解和应用这款高性能的RMS-DC转换器。 适合人群:从事模拟电路设计的专业工程师和技术人员,尤其是那些需要精确测量交流电信号均方根值的应用开发者。 使用场景及目标:①用于工业自动化、医疗设备、电力监控等领域,实现对交流电压或电流的精准测量;②适用于手持式数字万用表及其他便携式仪器仪表,提供高效的单电源解决方案;③在电流互感器配置中,用于检测微小的电流变化,保障电气安全;④应用于三相电力系统监控,优化建立时间和转换精度。 其他说明:为了确保最佳性能,文档推荐使用高质量的电容器件,并给出了详细的PCB布局指导。同时提醒用户关注电介质吸收和泄漏电流等因素对测量准确性的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值