How to print the content of a Rich Edit Control
2008-12-31 10:11
489 查看
How to print the content of a Rich Edit Control
By Roger AllenDownload demo project - 31.2 Kb
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 iscovered 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
NULLas 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 goingto 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 tothe 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 http://www.ryushinkan.co.uk/ 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!
|
相关文章推荐
- [转]How to set the control word of FPU in delphi
- flex/in the datagrid,how to get the new value of cell in the datagrid after edit
- How to show the content of renderbufferobject?
- how to print the spend time of one function
- How to get IOleSite interface of the WebBrowser in an ActiveX control
- How to set the width of columns?about chart control for .net
- How to Control the [Add document] button on the bottom of every view?
- How To Call Run() Method of the Microsoft Script Control in C++
- How to find child controls that are located in the template of a parent control
- How to print property if declaring in the format of @synthesize a=_a;
- how to implement the version control of static files
- Ruby: how to sort array of string parsing the content
- How to get the content of the 'identity' section in web.config
- 如何窥探PDB的秘密?(How to Inspect the Content of a Program Database (PDB) File)
- How to change the background color of an Edit Box
- How to customize the context menus of a WebBrowser control via the IDocHostUIHandler interface.
- how to edit the grub to change the sequance of system
- How to align content of a div to the bottom with css?
- How To Change the Background Color of a Tab Control
- 1. How to Inspect the Content of a Program Data...