Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / MFC

Code to Allow You to Print the Content of a CTreeCtrl

Rate me:
Please Sign up or sign in to vote.
4.23/5 (14 votes)
16 Mar 2003CPOL3 min read 143K   3K   26   28
A base class that provides all the functions you need to print a CTreeCtrl

Sample Image - examplePreview.gif

Introduction

Once again, I present a small printing class I recently developed to allow me to print the content of a CTreeCtrl. The code in itself is contained within a small class from which you can inherit your view/dialog that needs to be able to print the content of a CTreeCtrl.

So How Do We Use It?

To gain all the functionality you will require to print the content of a CTreeCtrl, you need to inherit the class that will be handling the actual printing from the supplied class TreeCtrlPrint.

C++
#include "TreeCtrlPrint.h"

class CExampleView : public CFormView, TreeCtrlPrint
{

Doing this gives you access to the following functions in the class:

C++
HTREEITEM GetNextTreeItem(const CTreeCtrl& treeCtrl, HTREEITEM hItem)

You use this function to iterate through the tree control in the order of all items as they would be drawn if all nodes in the tree control have been expanded. This lets you plot all the items in the correct order.

C++
void DrawTreeItem(const CTreeCtrl& treeCtrl, HTREEITEM hPrintItem, CDC *pDC, CRect rect, CWnd *pWnd)

This function actually does the drawing of the specific tree item, you need to pass in the handle of the tree item to print, the rectangle on the target DC which you want to print the output into. Some assumptions are made about the DC in that it will have the correct font selected into it to render with and the height of the rectangle supplied will be used as the size of an icon/image when plotted.

C++
ExpandAll(CTreeCtrl& treeCtrl)

This function will automatically expand all tree items with children.

Typical Printing Code

You have to do some work when printing the content of the tree control:

Select the Correct Font

If you look in the example application, you will see that I make use of the font being used by the tree control for printing, but just scaled correctly for the DPI of the printer:

C++
CFont        font ;
LOGFONT        lf ;

pTreeCtrl->GetFont()->GetLogFont(&lf);
// This aims to get the same size font for the printer as in use by the control 
// on the screen printer resolution
lf.lfHeight = -MulDiv(abs(lf.lfHeight), pDC->GetDeviceCaps(LOGPIXELSY), 72);
VERIFY(font.CreateFontIndirect(&lf));
pDC->SelectObject(&font) ;

Get the Number of Items that Can Fit on a Page

Once you have the correct font selected, you can calculate how many items can fit on a page, and from there, calculate the number of pages required to print the tree control content.

C++
CString text("A") ;
CSize cs = dc.GetTextExtent(text) ;
linesPerPage = abs(pInfo->m_rectDraw.Height() / cs.cy) -1;
if ((numTreeItems % linesPerPage) != 0)
{
    // we need to include the partial page
    numberOfPages++;
}
// Add in the whole pages
numberOfPages += (numTreeItems / linesPerPage);

The Actual Print Loop

When printing, your OnPrint() function gets called once per page of output, so we may need to navigate to the correct start position in the tree control before we start to print the tree items.

C++
// navigate to correct start position, if printing the 2nd or later page

HTREEITEM hPrintItem = pTreeCtrl->GetRootItem();
for (int i = 0 ; i < linesPerPage * currentPage && i < numTreeItems ; i++)
{
    hPrintItem = GetNextTreeItem(*pTreeCtrl, hPrintItem);
}

Once we're at the correct start position in the tree, we just keep printing items until either we run out of items or page space:

C++
// continue printing from this point onwards until we run oot of page area

for (i = linesPerPage * currentPage ; 
    (i < numTreeItems) && (i < (linesPerPage * (currentPage + 1))) ; i++)
{
    // calculate the rectangle for this tree item
    CRect    rect(pInfo->m_rectDraw.left + (cs.cx * 2), 
                  pInfo->m_rectDraw.top + (cs.cy * line_number), 
                  pInfo->m_rectDraw.left + pInfo->m_rectDraw.Width(), 
                  pInfo->m_rectDraw.top + (cs.cy * (line_number + 1)));
    DrawTreeItem(*pTreeCtrl, hPrintItem, pDC, rect, this);
    line_number++;
    hPrintItem = GetNextTreeItem(*pTreeCtrl, hPrintItem);
}

This code uses one extra variable currentPage which is taken from pInfo->m_nCurPage - 1, as we need a 0 based page numbering scheme to correctly work out the starting print item for following pages.

Well, that's all there is to it really.

Problems Encountered

As I said earlier, this is recently developed code for one of my applications. I ported it across for the CodeProject article and setup the example application. It was then that I found out that my code did not work properly for cases where you had more than 1 root item (my app only has 1 root item). My code was indenting the following root items and generally making a mess of things, so in a way, this article improved my application...

History

  • 17th March, 2003

    A bug fix for the GetNextTreeItem() function as reported by bhtang - should now work correctly with any type of populated tree. The example application was updated to call UpdatePrinterSelection(TRUE); in InitInstance() so that a default printer will be automatically selected at start-up, as suggested by Michael A. Rusakov

    A new function ExpandAll(CTreeCtrl& treeCtrl) was added to the class to expand all tree items which have children.

  • 5th March, 2003 - Initial version

Enjoy!

License

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


Written By
Software Developer (Senior) Sirius Analytical Instruments
United Kingdom United Kingdom
A research and development programmer working for a pharmaceutical instrument company for the past 17 years.

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 playing DDO on the Cannith server (Send a tell to "Maetrim" 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 and recently achieved my 1st Dan after 6 years.

Comments and Discussions

 
GeneralGetNextTreeItem Pin
portej052-Jan-09 3:13
portej052-Jan-09 3:13 
GeneralQ&D Transparent Printing Fix (for tree images) Pin
James R. Twine20-Nov-07 3:23
James R. Twine20-Nov-07 3:23 
Generalhelp - "AfxGetApp()->CreatePrinterDC(dc)" Pin
asfur4-Jul-07 10:00
asfur4-Jul-07 10:00 
GeneralRe: help - &quot;AfxGetApp()-&gt;CreatePrinterDC(dc)&quot; [modified] Pin
Davide Zaccanti24-Jul-07 19:09
Davide Zaccanti24-Jul-07 19:09 
GeneralRe: help - &quot;AfxGetApp()-&gt;CreatePrinterDC(dc)&quot; Pin
asfur18-Aug-07 9:29
asfur18-Aug-07 9:29 
QuestionMinutes or hours? Pin
-Dy27-Jul-05 5:54
-Dy27-Jul-05 5:54 
Generalyour project is excelent! Pin
haodate29-Nov-03 18:41
haodate29-Nov-03 18:41 
GeneralBug ( I think....) Pin
atul arora24-Aug-03 4:59
atul arora24-Aug-03 4:59 
GeneralA minor fix when looking for rest of tree node. Pin
ChaoJui6-May-06 5:02
ChaoJui6-May-06 5:02 
GeneralIcons won't be printed!! Pin
Ambat4-Jun-03 23:10
Ambat4-Jun-03 23:10 
GeneralAgain good job Roger Pin
Mike Wild13-Mar-03 21:42
Mike Wild13-Mar-03 21:42 
GeneralI should add some code into InitInstance of your example Pin
Michael Rusakow12-Mar-03 17:51
Michael Rusakow12-Mar-03 17:51 
GeneralRe: I should add some code into InitInstance of your your example Pin
Roger Allen13-Mar-03 1:04
Roger Allen13-Mar-03 1:04 
Generalyou should add some codes for GetNextTreeItem Pin
bhtang12-Mar-03 15:54
sussbhtang12-Mar-03 15:54 
GeneralRe: you should add some codes for GetNextTreeItem Pin
Roger Allen13-Mar-03 1:08
Roger Allen13-Mar-03 1:08 
GeneralRe: you should add some codes for GetNextTreeItem Pin
tbh13-Mar-03 3:00
tbh13-Mar-03 3:00 
GeneralRe: you should add some codes for GetNextTreeItem Pin
CharlieCurry20-Mar-03 7:20
CharlieCurry20-Mar-03 7:20 
GeneralError: Cannot find file to open Pin
WREY11-Mar-03 6:43
WREY11-Mar-03 6:43 
GeneralRe: Error: Cannot find file to open Pin
Michael Rusakow12-Mar-03 17:41
Michael Rusakow12-Mar-03 17:41 
GeneralRe: Error: Cannot find file to open Pin
WREY12-Mar-03 18:25
WREY12-Mar-03 18:25 
GeneralRe: Error: Cannot find file to open Pin
Roger Allen13-Mar-03 1:06
Roger Allen13-Mar-03 1:06 
Wooops! This is a left over from when I ported the class across into the example app. In my app the code that draws the icons/bitmaps which are part of this class are not in my app and are external functions it needs to link to. So yes, just delete the line from the source.
Blush | :O

I need to go over hese with a fine tooth comb in the future.


Roger Allen
Sonork 100.10016

Were you different as a kid? Did you ever say "Ooohhh, shiny red" even once? - Paul Watson 11-February-2003
GeneralWM_PRINTCLIENT Pin
Andreas Saurwein5-Mar-03 5:34
Andreas Saurwein5-Mar-03 5:34 
GeneralRe: WM_PRINTCLIENT Pin
Roger Allen5-Mar-03 6:21
Roger Allen5-Mar-03 6:21 
GeneralYou must be Canadian! Pin
NGS 5496725-Mar-03 4:45
NGS 5496725-Mar-03 4:45 
GeneralRe: You must be Canadian! Pin
Roger Allen5-Mar-03 4:50
Roger Allen5-Mar-03 4:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.