允许打印 CTreeCtrl 内容的代码






4.23/5 (13投票s)
一个提供打印 CTreeCtrl 所需所有功能的基类。
引言
再次,我展示了一个最近开发的打印类,它允许我打印一个 CTreeCtrl
的内容。代码本身包含在一个小类中,您可以从该类继承您的视图/对话框,该视图/对话框需要能够打印 CTreeCtrl
的内容。
我们如何使用它?
要获得打印 CTreeCtrl
内容所需的所有功能,您需要从提供的类 TreeCtrlPrint
继承将处理实际打印的类。
#include "TreeCtrlPrint.h"
class CExampleView : public CFormView, TreeCtrlPrint
{
这样做使您可以访问该类中的以下函数
HTREEITEM GetNextTreeItem(const CTreeCtrl& treeCtrl, HTREEITEM hItem)
您可以使用此函数按照树控件中所有项目的顺序进行迭代,就像树控件中的所有节点都已展开时绘制的那样。 这使您可以按正确的顺序绘制所有项目。
void DrawTreeItem(const CTreeCtrl& treeCtrl, HTREEITEM hPrintItem, CDC *pDC, CRect rect, CWnd *pWnd)
此函数实际上执行特定树项目的绘制,您需要传入要打印的树项目的句柄、要在目标 DC 上将输出打印到的矩形。 做出了一些关于 DC 的假设,即它将选择正确的字体进行渲染,并且提供的矩形的高度将用作绘制时图标/图像的大小。
ExpandAll(CTreeCtrl& treeCtrl)
此函数将自动展开所有带有子项的树项目。
典型的打印代码
打印树控件的内容时,您必须做一些工作
选择正确的字体
如果您查看示例应用程序,您会看到我使用了树控件使用的字体进行打印,但只是针对打印机的 DPI 进行了正确缩放
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) ;
获取一页可以容纳的项目数
选择正确的字体后,您可以计算出一页可以容纳多少个项目,并从那里计算出打印树控件内容所需的页数。
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);
实际的打印循环
打印时,您的 OnPrint()
函数每页输出调用一次,因此我们可能需要在开始打印树项目之前导航到树控件中的正确起始位置。
// 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);
}
一旦我们到达树中的正确起始位置,我们只需继续打印项目,直到我们用完项目或页面空间为止
// 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);
}
此代码使用一个额外的变量 currentPage
,该变量取自 pInfo->m_nCurPage - 1
,因为我们需要一个从 0 开始的页码方案才能正确计算出后续页面的起始打印项目。
好吧,这就是全部了。
遇到的问题
正如我之前所说,这是我应用程序最近开发的代码。 我将其移植到 CodeProject 文章并设置了示例应用程序。 那时我发现我的代码对于有多个根项目的情况无法正常工作(我的应用程序只有 1 个根项目)。 我的代码缩进了后续的根项目,并且通常搞得一团糟,所以在某种程度上,这篇文章改进了我的应用程序...
历史
- 2003年3月17日
bhtang 报告的
GetNextTreeItem()
函数的错误修复 - 现在应该可以正确处理任何类型的填充树。示例应用程序已更新为在InitInstance()
中调用UpdatePrinterSelection(TRUE);
,以便在启动时自动选择默认打印机,如 Michael A. Rusakov 建议的那样向类中添加了一个新函数
ExpandAll(CTreeCtrl& treeCtrl)
,用于展开所有具有子项的树项目。 - 2003年3月5日 - 初始版本
尽情享用!