📄 disktreectrl.cpp
字号:
if(pDC == NULL || pInfo==NULL)
return;
TitleStr = t_title;
DateStr = t_date;
//create lc font, and Bold lc Font
int nFontSize = -((pDC->GetDeviceCaps(LOGPIXELSY) * 10) / 72);
CString strFontName = "Arial";
lcFont.CreateFont(-11, 0,0,0, FW_NORMAL, 0,0,0, DEFAULT_CHARSET,
OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, strFontName);
BoldFont.CreateFont(-13, 0,0,0, FW_BOLD, 0,0,0, DEFAULT_CHARSET,
OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, strFontName);
compute_metrics(pDC);
int nMaxPage = m_nMaxRowCount/m_nRowsPerPage + 1;//Compute this again in case user changed printer
pInfo->SetMaxPage(nMaxPage);
pInfo->m_nCurPage = 1; // start printing at page# 1
return;
}
//***********************ONPRINT*************************
void CTreeListPrinting::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
if(NULL == pDC || NULL == pInfo)
return;
//This has to be in OnPrint() or else PrintPreview goes screwy
pOldFont = pDC->GetCurrentFont();
//Fit all columns to 1 page, regardless of column number.
pDC->SetMapMode(MM_ANISOTROPIC);
//For every 1 List Control pixel
pDC->SetWindowExt(1, 1);
//The printer has ratio more dots
pDC->SetViewportExt(m_ratiox, m_ratioy);
int nStartRow = (pInfo->m_nCurPage - 1)*m_nRowsPerPage;
int nEndRow = nStartRow+m_nRowsPerPage;
if(nEndRow > m_nMaxRowCount)
nEndRow = m_nMaxRowCount;
PrintHeader(pDC, pInfo); //print the header
pDC->SetWindowOrg(-1*page_rc.left, 0);
PrintFooter(pDC, pInfo); //Print the footer
pDC->SetWindowOrg(-1*page_rc.left, -1*HEADER_HEIGHT*m_nRowHeight);
PrintHeaderControl(pDC, pInfo);//Print the header Control, Manually
pDC->SelectObject(&lcFont);//Use the LC normal font
pDC->SetTextColor(RGB(0,0,0));//Black text on
pDC->SetBkColor(RGB(255,255,255));//White paper
CRect rcBounds;
lc->GetItemRect(nStartRow, &rcBounds, LVIR_BOUNDS);
//offset top margin of rcBounds by ListControl header
CRect rc;
lc->GetHeaderCtrl()->GetClientRect(&rc);
rcBounds.OffsetRect(0, -rc.Height());
pDC->OffsetWindowOrg(rcBounds.left, rcBounds.top);
//start printing rows
for(int i = nStartRow; i < nEndRow; i++)
DrawRow(pDC, i);
//SetWindowOrg back for next page
pDC->SetWindowOrg(0,0);
pDC->SelectObject(pOldFont);//Put the old font back
return;
}
//Set the extents after calling this function because it uses printer extents
//He is using a list in here have to figure out what to do.
//********************************PRINT_HEADER************************************
void CTreeListPrinting::PrintHeader(CDC *pDC, CPrintInfo *pInfo)
{
pDC->SelectObject(&BoldFont);
pDC->SetTextColor(RGB(0,0,0));//Black text on
pDC->SetBkColor(RGB(255,255,255));//White paper
CRect rc = page_rc;
rc.bottom = rc.top+m_nRowHeight;
//print App title on top right margin
pDC->DrawText(TitleStr, &rc, DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_RIGHT | DT_NOCLIP);
return;
}
//print footer with a line and date, and page number
//****************************PRINT_FOOTER****************************************
void CTreeListPrinting::PrintFooter(CDC *pDC, CPrintInfo *pInfo)
{
CRect rc = page_rc;
rc.top = rc.bottom - FOOTER_HEIGHT*m_nRowHeight;
rc.bottom = rc.top + m_nRowHeight;
draw_line_at(pDC, rc.top); //draw line
//draw page number
CString sTemp ;
rc.OffsetRect(0, m_nRowHeight/2);
sTemp.Format("%d", pInfo->m_nCurPage);
pDC->DrawText(sTemp,-1,rc, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
//Now draw the DateStr at bottom of page
pDC->DrawText(DateStr,-1,rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
return;
}
//Do the cleanup
//********************ONEND_PRINTING*****************
void CTreeListPrinting::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
lcFont.DeleteObject();
BoldFont.DeleteObject();
return;
}
//This function sets alls of the row and metric member vars
//************************COMPUTE_METRICS*********************
void CTreeListPrinting::compute_metrics(CDC *pDC)
{
//This includes width for all columns
CRect row_rc; lc->GetItemRect(0, &row_rc, LVIR_BOUNDS);
//Get the list control window DC
CDC *pCtlDC = lc->GetDC(); if(NULL == pCtlDC) return;
//so we can get the avg character width
TEXTMETRIC tm; pCtlDC->GetTextMetrics(&tm);
//Lets get the ratios for scaling to printer DC
//Fit all columns to 1 page, regardless of column number.
m_ratiox = pDC->GetDeviceCaps(HORZRES)/(row_rc.Width() + (LEFT_MARGIN+RIGHT_MARGIN)*tm.tmAveCharWidth);
//width of pDC/whats got to fit into it in lcDC units
m_ratioy = pDC->GetDeviceCaps(LOGPIXELSY)/pCtlDC->GetDeviceCaps(LOGPIXELSY);
lc->ReleaseDC(pCtlDC);
//Set up a page rc in list control units that accounts for left and right margins
page_rc.SetRect(0,0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
page_rc.bottom = page_rc.bottom/m_ratioy;//Convert units to List Control
page_rc.right = page_rc.right/m_ratiox;
page_rc.left = LEFT_MARGIN*tm.tmAveCharWidth;//adjust sides for magins
page_rc.right -= RIGHT_MARGIN*tm.tmAveCharWidth;
m_nRowHeight = row_rc.Height();//Get the height of a row.
int pRowHeight = (int)(m_nRowHeight*m_ratioy);//Get RowHeight in printer units.
m_nRowsPerPage = pDC->GetDeviceCaps(VERTRES)/pRowHeight;//How many rows will fit on page?
m_nRowsPerPage -= (HEADER_HEIGHT+FOOTER_HEIGHT);//After header and footer rows
m_nRowsPerPage -= 1; //After header Control row
return;
}
//You can't just have the header control print itself. 1st of all it looks crappy.
//2nd if part of header control is off screen does not print itself.
//So we will manually print it.
//************************PRINTHEADERCONTROL****************************
void CTreeListPrinting::PrintHeaderControl(CDC *pDC, CPrintInfo *pInfo)
{
UINT dtFlags = DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER|DT_LEFT;//drawing flags
CHeaderCtrl* hc = lc->GetHeaderCtrl();
hc_items = hc->GetItemCount();
if (hc_items < 1) return; //Remember that hc_items is also used to draw rows.
int order_array[30];//Shouln't have more than 30 columns
hc->GetOrderArray(order_array, hc_items);
char temp_str[1024];
HDITEM phi;
phi.mask = HDI_TEXT | HDI_WIDTH ;
phi.cchTextMax = 1024;
phi.pszText = temp_str;
CRect rc(0,0,0,m_nRowHeight);
for (int i = 0; i < hc_items; i++)
{
hc->GetItem(order_array[i], &phi);//Get in viewed order
rc.right += phi.cxy;
pDC->DrawText(temp_str, -1, rc, dtFlags);
rc.left += phi.cxy;
}
//Now draw the line below header control
draw_line_at(pDC, rc.bottom);
return;
}
//*************************************DRAWROW********************************************
void CTreeListPrinting::DrawRow(CDC *pDC, int nItem)
{
if (hc_items < 1) //Then nothing to print
return;
int order_array[30];//Shouln't have more than 30 columns
lc->GetColumnOrderArray(order_array, hc_items);
CString temp_str;
LV_COLUMN lvc;
lvc.mask = LVCF_WIDTH;
CRect rc; lc->GetItemRect(nItem, rc, LVIR_BOUNDS);
int offset = pDC->GetTextExtent(" ", 1).cx;//Returns CSIZE so get cx member of CSIZE object.
rc.left += offset/2;//This makes it so that label will be over a little bit
rc.right -= offset;//Just keep this stuff it DOES look better.
CRect r(rc);
for (int i = 0; i < hc_items; i++)
{
int nOffset = 0;
if (i==0)
nOffset = lc->DrawLine(pDC, nItem, r);
lc->GetColumn(order_array[i], &lvc);//Get in viewed order
temp_str = lc->GetItemText(nItem, order_array[i]);
r.left += nOffset;
pDC->DrawText(temp_str, -1, r, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER|DT_LEFT);
r.left += (lvc.cx - nOffset);
}
pDC->MoveTo(rc.Width() - lc->GetColumnWidth(0) + offset, rc.bottom);
pDC->LineTo(page_rc.right, rc.bottom);//Use the page_rc to figure out the width of the line
return;
}
//Just pass this function a y position to draw the line at.
//*************************DRAW_LINE_AT************************************
void CTreeListPrinting::draw_line_at(CDC *pDC, unsigned int y)
{
pDC->MoveTo(0, y);
pDC->LineTo(page_rc.right, y);//Use the page_rc to figure out the width of the line
return;
}
int CDiskTreeCtrl::DrawLine(CDC* pDC, int nItem, const CRect& rc)
{
CRect rcBounds(rc);
rcBounds.OffsetRect(0,rc.Height()/3);
int nLeft = 0;
int m_cxImage = rcBounds.Height()/2;
int m_cyImage = rcBounds.Height();
int nColWidth = GetColumnWidth(0);
int nOffset = (rcBounds.Height() - m_cyImage) >> 1;
CPen psPen(PS_SOLID, 1, RGB(192,192,192));
CPen* pOldPen = pDC->SelectObject(&psPen);
CTreeItem *pSelItem = reinterpret_cast<CTreeItem*>(GetItemData(nItem));
CTreeItem* pRoot = GetRootItem();
int iIndent = GetIndent(pSelItem);
//setup plus/minus rectangle
int nHalfImage = (m_cxImage >> 1);
int yDown = rcBounds.top;
int nBottomDown = yDown + nHalfImage+nOffset;
SIZE right_bottom = {(m_cxImage>>1)+2+1, (m_cyImage>>1)+2+1};//from ANDY : the '+ 1' is to center the [+] or [-]
int left = rcBounds.left + GetIndent(pSelItem) * m_cxImage - nHalfImage;
int top = nBottomDown - (right_bottom.cy >> 1);
POINT left_top = {left - (right_bottom.cx >> 1), top};
BOOL bChild = ItemHasChildren(pSelItem);
BOOL bCollapsed = IsCollapsed(pSelItem);
//draw outline
while(pRoot != pSelItem)
{
CTreeItem* pParent = GetParentItem(pSelItem);
POSITION pos = pParent->m_listChild.GetTailPosition();
while(pos!=NULL)
{
CTreeItem *pLastChild = (CTreeItem*)pParent->m_listChild.GetPrev(pos);
int nIndex = GetCurIndex(pLastChild);
//no drawing outside the 1st columns right
int xLine = rcBounds.left + GetIndent(pLastChild) * m_cxImage - nHalfImage;
if(nIndex == nItem && (GetIndent(pLastChild)==iIndent))
{
//draw '-
int x;
pDC->MoveTo(xLine, yDown);
pDC->LineTo(xLine, nBottomDown);
// -
xLine + nHalfImage > nColWidth ? x = nColWidth: x = xLine + nHalfImage;
pDC->MoveTo(xLine, nBottomDown);
pDC->LineTo(x, nBottomDown);
nLeft += nHalfImage;
break;
}
else
if(nIndex > nItem && (GetIndent(pLastChild)==iIndent))
{
//draw |-
int x;
xLine + nHalfImage > nColWidth ? x = nColWidth : x = xLine + nHalfImage;
pDC->MoveTo(xLine, nBottomDown);
pDC->LineTo(x, nBottomDown);
//-
pDC->MoveTo(xLine, yDown);
pDC->LineTo(xLine, rcBounds.bottom);
nLeft += nHalfImage;
break;
}
else
if(nIndex > nItem && (GetIndent(pLastChild) < iIndent))
{
//draw |
pDC->MoveTo(xLine, yDown);
pDC->LineTo(xLine, rcBounds.bottom);
nLeft += nHalfImage;
break;
}else
nLeft += nHalfImage;
}
pSelItem = pParent;//next
}
//draw plus/minus sign
if(bChild)
{
//erase bkgrnd
CRect rcBounds(left_top, right_bottom);
pDC->FillRect(rcBounds, &CBrush(RGB(255,255,255)));
//draw rectangle
pDC->Rectangle(rcBounds);
//draw plus/minus sign
int topdown = nBottomDown;
if(bCollapsed)
{
//plus
pDC->MoveTo(left, topdown-2);
pDC->LineTo(left, topdown+3);
//
pDC->MoveTo(left-2, topdown);
pDC->LineTo(left+3, topdown);
}
else {
//minus
pDC->MoveTo(left-2, topdown);
pDC->LineTo(left+3, topdown);
int nOffset = (rcBounds.Height() - m_cyImage)/2;
pDC->MoveTo(left+ m_cxImage, rcBounds.top + m_cyImage+(nOffset/2));
pDC->LineTo(left + m_cxImage, rcBounds.bottom);
}
}
pDC->SelectObject(pOldPen);
return iIndent*nHalfImage*2+nHalfImage;
/*int nOffset=0;
int nOffsetWidth = 8;
CTreeItem* pRoot = GetRootItem();
CTreeItem *pParent = reinterpret_cast<CTreeItem*>(GetItemData(nItem));
CTreeItem *pItem = pParent;
CItemInfo* lp = GetData(pItem);
int iIndent = GetIndent(pItem);
int nListItem = GetCurIndex(pItem);
CTreeItem *pSelItem = pItem;
while(pRoot != pSelItem)
{
CTreeItem* pParent = GetParentItem(pSelItem);
POSITION pos = pParent->m_listChild.GetTailPosition();
while(pos!=NULL)
{
CTreeItem *pLastChild = (CTreeItem*)pParent->m_listChild.GetPrev(pos);
int nIndex = GetCurIndex(pLastChild);
//no drawing outside the 1st columns right
if (nIndex == nListItem && (GetIndent(pLastChild)==iIndent))
{
pDC->MoveTo(rc.left + nOffset, (rc.bottom-rc.top)/2 + rc.top);
pDC->LineTo(rc.left + nOffset + nOffsetWidth, (rc.bottom-rc.top)/2 + rc.top);
nOffset += nOffsetWidth;
break;
}
else if(nIndex > nListItem && (GetIndent(pLastChild)==iIndent))
{
//draw |-
pDC->MoveTo(rc.left + nOffset, rc.top);
pDC->LineTo(rc.left + nOffset, rc.bottom);
pDC->MoveTo(rc.left + nOffset, (rc.bottom-rc.top)/2 + rc.top);
pDC->LineTo(rc.left + nOffset + nOffsetWidth, (rc.bottom-rc.top)/2 + rc.top);
nOffset += nOffsetWidth;
break;
}
else if(nIndex > nListItem && (GetIndent(pLastChild) < iIndent))
{
//draw |
pDC->MoveTo(rc.left + nOffset, rc.top);
pDC->LineTo(rc.left + nOffset, rc.bottom);
nOffset += nOffsetWidth;
break;
}else
{
nOffset += nOffsetWidth;
break;
}
}
pSelItem = pParent;//next
}
return nOffset;*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -