/****************************************************************************/
/* SftTree/DLL 7.0 - Tree Control for C/C++ */
/* SftTree/DLL 7.0 - Itanium Edition */
/* SftTree/DLL 7.0 - x64 Edition */
/* SftTree/DLL 7.0 - Windows Mobile Edition */
/* Copyright (C) 1995, 2012 Softel vdm, Inc. All Rights Reserved. */
/****************************************************************************/
#include "stdafx.h"
#include "OwnerDraw.h"
#include "sampldoc.h"
#include "samplvw.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSampleView
IMPLEMENT_DYNCREATE(CSampleView, CView)
BEGIN_MESSAGE_MAP(CSampleView, CView)
//{{AFX_MSG_MAP(CSampleView)
ON_WM_CREATE()
ON_WM_SIZE()
//}}AFX_MSG_MAP
ON_SFTTREEN_LBUTTONDBLCLK_TEXT(IDC_TREE, OnLButtonExpandCollapse)
ON_SFTTREEN_LBUTTONDOWN_BUTTON(IDC_TREE, OnLButtonExpandCollapse)
ON_SFTTREEN_LBUTTONDBLCLK_BUTTON(IDC_TREE, OnLButtonExpandCollapse)
ON_SFTTREEN_EXPANDALL(IDC_TREE, OnExpandAll)
ON_SFTTREEN_LBUTTONDBLCLK_COLUMNRES(IDC_TREE, OnLButtonDblClkColumnResize)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSampleView construction/destruction
CSampleView::CSampleView()
{
// create a vertical font
LOGFONT lf;
CFont* pGuiFont = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
pGuiFont->GetLogFont(&lf);
lf.lfEscapement = 900;
lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = FF_DONTCARE;
lstrcpy(lf.lfFaceName, _T("Arial"));
m_hFontVertical.CreateFontIndirect(&lf);
// load sample bitmap
m_hBitmap.LoadBitmap(IDB_LOGO);
}
CSampleView::~CSampleView()
{
}
/////////////////////////////////////////////////////////////////////////////
// CSampleView drawing
void CSampleView::OnDraw(CDC* pDC)
{
CSampleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
/////////////////////////////////////////////////////////////////////////////
// CSampleView diagnostics
#ifdef _DEBUG
void CSampleView::AssertValid() const
{
CView::AssertValid();
}
void CSampleView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSampleDoc* CSampleView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSampleDoc)));
return (CSampleDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CSampleView message handlers
int CSampleView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_Tree.CreateEx(
WS_EX_CLIENTEDGE,
SFTTREESTYLE_NOTIFY | /* Notify parent window */
SFTTREESTYLE_VARIABLE | /* Variable height items */
SFTTREESTYLE_LEFTBUTTONONLY | /* Only respond to left mouse button */
SFTTREESTYLE_SCROLL | /* Honor WS_H/VSCROLL */
WS_HSCROLL | WS_VSCROLL | /* Vertical and horizontal scrollbars */
WS_VISIBLE | WS_CHILD, /* Visible, child window */
CRect(0,0,0,0), /* Location */
this, /* Parent window */
IDC_TREE)) /* Tree control ID */
return -1;
m_Tree.SetShowHeader(TRUE); /* Show column headers */
/* Register the item pictures. These pictures are used */
/* for all items in the tree control. All three pictures */
/* must be the same size. */
{
SFT_PICTURE aPic[3];
Sft_InitPicture(&aPic[0]);
Sft_InitPicture(&aPic[1]);
Sft_InitPicture(&aPic[2]);
m_aThreeItemBitmaps[0].LoadBitmap(IDB_EXPANDABLE);/* Expandable bitmap */
Sft_SetPictureBitmap(&aPic[0], m_aThreeItemBitmaps[0]);/* Assign bitmap */
m_aThreeItemBitmaps[1].LoadBitmap(IDB_EXPANDED);/* Expanded bitmap */
Sft_SetPictureBitmap(&aPic[1], m_aThreeItemBitmaps[1]);/* Assign bitmap */
m_aThreeItemBitmaps[2].LoadBitmap(IDB_LEAF);/* Leaf bitmap */
Sft_SetPictureBitmap(&aPic[2], m_aThreeItemBitmaps[2]);/* Assign bitmap */
m_Tree.SetPictures(aPic); /* Use item pictures */
}
m_Tree.SetItemPictureAlign(TRUE); /* Align item bitmaps */
m_Tree.SetTreeLineStyle(SFTTREE_TREELINE_AUTOMATIC0);/* Dotted tree lines (incl. level 0) */
m_Tree.SetShowButtons(TRUE); /* Expand/collapse buttons (level 1..n) */
m_Tree.SetShowButton0(TRUE); /* Show expand/collapse buttons (level 0) */
m_Tree.SetButtons(SFTTREE_BUTTON_AUTOMATIC3);/* Automatic button style 3 */
m_Tree.SetShowGrid(TRUE); /* Show grid */
m_Tree.SetGridStyle(SFTTREE_GRID_BOTH_DOT);/* Dotted grid lines */
m_Tree.SetShowTruncated(TRUE); /* Show ... if truncated */
m_Tree.SetSelectionStyle(SFTTREE_SELECTION_CELL1 | SFTTREE_SELECTION_OUTLINE);/* Select first cell only using outline */
m_Tree.SetSelectionArea(SFTTREE_SELECTIONAREA_ALLCELLS);/* Selection changes by clicking on an item's cells */
m_Tree.SetFlyby(TRUE); /* Flyby highlighting */
m_Tree.SetUpdateCaretExpandCollapse(FALSE);/* don't update caret location when expand/collapse button clicked */
m_Tree.SetScrollTips(TRUE); /* Show Scrolltips */
m_Tree.SetInheritBgColor(TRUE); /* Inherit background color of first cell */
m_Tree.SetReorderColumns(TRUE); /* Column reordering */
m_Tree.SetOpenEnded(TRUE); /* Last column width */
m_Tree.SetShowHeaderButtons(TRUE); /* Show column header as buttons */
/* Define columns */
{
SFTTREE_COLUMN_EX aCol[3] = {
{ 0, 0, /* Reserved */
221, /* Width (in pixels) */
ES_LEFT | SFTTREE_TOOLTIP, /* Cell alignment */
ES_LEFT | SFTTREE_HEADER_UP, /* Title style */
_T("Vertical Titles"), /* Column header title */
NULL, NULL, /* Reserved field and bitmap handle */
SFTTREE_BMP_RIGHT, /* Picture alignment */
0, 0, 0, /* Reserved fields */
SFTTREE_NOCOLOR, /* Cell background color */
SFTTREE_NOCOLOR, /* Cell foreground color */
SFTTREE_NOCOLOR, /* Selected cell background color */
SFTTREE_NOCOLOR, /* Selected cell foreground color */
0, /* Real column position (set by SetColumns call) */
0, /* Display column number (display position) */
0, /* Column flag */
0, /* Minimum column width */
},
{ 0, 0, /* Reserved */
253, /* Width (in pixels) */
ES_LEFT | SFTTREE_TOOLTIP, /* Cell alignment */
ES_LEFT | SFTTREE_HEADER_UP, /* Title style */
_T("Second Column"), /* Column header title */
NULL, NULL, /* Reserved field and bitmap handle */
SFTTREE_BMP_RIGHT, /* Picture alignment */
0, 0, 0, /* Reserved fields */
SFTTREE_NOCOLOR, /* Cell background color */
SFTTREE_NOCOLOR, /* Cell foreground color */
SFTTREE_NOCOLOR, /* Selected cell background color */
SFTTREE_NOCOLOR, /* Selected cell foreground color */
0, /* Real column position (set by SetColumns call) */
1, /* Display column number (display position) */
0, /* Column flag */
0, /* Minimum column width */
},
{ 0, 0, /* Reserved */
100, /* Width (in pixels) */
ES_LEFT | SFTTREE_TOOLTIP, /* Cell alignment */
ES_LEFT | SFTTREE_HEADER_UP, /* Title style */
_T("Third Column"), /* Column header title */
NULL, NULL, /* Reserved field and bitmap handle */
SFTTREE_BMP_RIGHT, /* Picture alignment */
0, 0, 0, /* Reserved fields */
SFTTREE_NOCOLOR, /* Cell background color */
SFTTREE_NOCOLOR, /* Cell foreground color */
SFTTREE_NOCOLOR, /* Selected cell background color */
SFTTREE_NOCOLOR, /* Selected cell foreground color */
0, /* Real column position (set by SetColumns call) */
2, /* Display column number (display position) */
0, /* Column flag */
0, /* Minimum column width */
}
};
m_Tree.SetColumns(3, aCol); /* Set column attributes */
}
m_Tree.SetShowRowHeader(SFTTREE_ROWSTYLE_BUTTONCOUNT1);/* Row style */
m_Tree.SetRowColHeaderText(_T("?")); /* Row/column header text */
m_Tree.SetRowColHeaderStyle(ES_LEFT | SFTTREE_HEADER_UP);/* Row/column header style */
m_Tree.SetCharSearchMode(SFTTREE_CHARSEARCH_ALLCHARS, -1);/* Consider all characters typed */
/* Use an ownerdraw callback routine */
{
SFTTREE_OWNERDRAWPARM Parm; /* Parameter list */
Parm.lpfnOwnerDrawProc = (LPFNSFTTREE_OWNERDRAWPROC) CSampleView::OwnerDrawCallback;/* User supplied drawing routine */
Parm.OwnerDrawUserData = (SFTTREE_DWORD_PTR)this;/* User supplied data */
m_Tree.SetOwnerDrawCallback(&Parm);
}
/* Change the default colors */
{
SFTTREE_COLORS Colors;
m_Tree.GetCtlColors(&Colors); /* Get current color settings */
Colors.colorTreeLines = COLOR_3DDKSHADOW | 0x80000000L;/* Tree line color */
Colors.colorSelBgNoFocus = COLOR_BTNFACE | 0x80000000L;/* Selection background color (no input focus) */
Colors.colorSelFgNoFocus = COLOR_BTNTEXT | 0x80000000L;/* Selection foreground color (no input focus) */
m_Tree.SetCtlColors(&Colors); /* Set new colors */
}
/*------------------------------------------------------------------------------*/
/* Add a few items. */
/*------------------------------------------------------------------------------*/
for (int i = 0 ; i < 50 ; ++i) {
int index;
index = m_Tree.AddString(_T("An item"));/* Add an item */
m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */
m_Tree.SetText(index, 2, _T("3nd Column"));/* Set text in next column */
index = m_Tree.AddString(_T("Another item"));/* Add another item */
m_Tree.SetItemLevel(index, 1);/* change level */
m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */
m_Tree.SetText(index, 2, _T("3nd Column"));/* Set text in next column */
/* Set an item's row header text using: */
m_Tree.SetRowText(index, _T("?"));/* Row header text */
index = m_Tree.AddString(_T("A third item"));/* Add another item */
m_Tree.SetItemLevel(index, 2);/* change level */
m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */
m_Tree.SetText(index, 2, _T("3nd Column"));/* Set text in next column */
index = m_Tree.AddString(_T("A fourth item"));/* Add another item */
m_Tree.SetItemLevel(index, 1);/* change level */
m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */
m_Tree.SetText(index, 2, _T("3nd Column"));/* Set text in next column */
}
/*------------------------------------------------------------------------------*/
/* Once ALL TREE CONTROL ITEMS HAVE BEEN ADDED, you can set additional tree */
/* control attributes. */
/*------------------------------------------------------------------------------*/
/* Make all column widths optimal, so text and pictures are */
/* not clipped horizontally. */
m_Tree.MakeColumnOptimal(-1, 0, FALSE);/* Make column widths optimal */
/* Make row header width optimal, so text and pictures are */
/* not clipped horizontally. */
m_Tree.MakeRowHeaderOptimal(0, FALSE);/* Make row header width optimal */
m_Tree.RecalcHorizontalExtent(0, FALSE);/* Update horizontal scroll bar */
m_Tree.SetCurSel(4); // select the 4th item
m_Tree.SetCaretIndex(4); // and make it current
m_Tree.SetTopIndex(0); // show the first item
return 0;
}
void CSampleView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
m_Tree.MoveWindow(0, 0, cx, cy);
}
/* Respond to events as the user clicks on different tree */
/* components. The events handled here can be changed to */
/* suit your application. */
void CSampleView::OnLButtonExpandCollapse()
{
/* get index of item to expand/collapse */
int index = m_Tree.GetExpandCollapseIndex();
/* get current expand/collapsed status */
BOOL fExpanded = m_Tree.GetItemExpand(index);
/* if control key is used we'll expand all dependents */
BOOL fDepth = (::GetKeyState(VK_CONTROL)&0x8000);
if (fExpanded)
m_Tree.Collapse(index, TRUE);
else
m_Tree.Expand(index, TRUE, fDepth);
}
/* Respond to numeric keypad multiply key. */
void CSampleView::OnExpandAll()
{
/* get index of item to expand/collapse */
int index = m_Tree.GetExpandCollapseIndex();
m_Tree.Expand(index, TRUE, TRUE);
}
/* Respond to events as the user double-clicks on the */
/* column resizing area. The events handled here can be */
/* changed to suit your application. */
void CSampleView::OnLButtonDblClkColumnResize()
{
/* Resize column optimally */
int realCol = m_Tree.GetResizeColumn();
if (realCol >= 0) {
m_Tree.MakeColumnOptimal(realCol);/* Make column width optimal */
m_Tree.RecalcHorizontalExtent(0, FALSE);/* Update horizontal scroll bar */
}
}
/**********************************************************************/
/* Ownerdraw Callback */
/**********************************************************************/
void CSampleView::OwnerDraw_Column_Header(LPSFTTREE_OWNERDRAW lpInfo)
{
// This function paints the column header using a vertical font
// it even takes themes into consideration, so it's a bit more complicated
// than the average application.
// get general information about tree control and columns
LPSFTTREE_COLUMN_EX lpCol;
int nCols = m_Tree.GetColumns(&lpCol);/* Get column attributes */
// Set up CDC
CDC* pDC = CDC::FromHandle(lpInfo->hDC);
// calculate the text size
RECT rect, textRect;
int len = lstrlen(lpCol[lpInfo->col].lpszTitle); // column title
COLORREF clrFg = pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
int mode = pDC->SetBkMode(TRANSPARENT);
CFont* pOldFont = (CFont*) pDC->SelectObject(&m_hFontVertical);
SetRectEmpty(&rect);
pDC->DrawText(lpCol[lpInfo->col].lpszTitle, len, &rect, DT_CALCRECT|DT_LEFT);
SetRect(&textRect, rect.top, rect.left, rect.bottom, rect.right);
if (lpInfo->style == SFTTREE_OD_CALC) {
// we need to return just the size of the header we want to paint
rect = textRect;
if (lpInfo->fThemed) {
// Windows themes are used
RECT extentRect;
GetThemeBackgroundExtent(lpInfo->hThemeHeader, lpInfo->hDC, HP_HEADERITEM, HIS_NORMAL, &rect, &extentRect);
rect = extentRect;
InflateRect(&rect, 3, 6); // leave a slight gap
} else {
// No windows themes
InflateRect(&rect, 4, 4); // leave a slight gap
}
lpInfo->DrawRect.bottom = rect.bottom-rect.top;
lpInfo->DrawRect.right = rect.right-rect.left;
} else {
// we need to paint the header
int xOffs, yOffs;
if (lpInfo->fThemed) {
// Windows themes are used
int iPartId = HP_HEADERITEM;
int iStateId = HIS_NORMAL;
if (lpInfo->fSelected)
iStateId = HIS_PRESSED;
if (lpInfo->fFlyby)
iStateId = HIS_HOT;
DrawThemeBackground(lpInfo->hThemeHeader, lpInfo->hDC, iPartId, iStateId, &lpInfo->DrawRect, &lpInfo->DrawRect);
GetThemeBackgroundContentRect(lpInfo->hThemeHeader, lpInfo->hDC, iPartId, iStateId, &lpInfo->DrawRect, &rect);
} else {
// No windows themes
pDC->DrawFrameControl(&lpInfo->DrawRect, DFC_BUTTON, DFCS_BUTTONPUSH | (lpInfo->fSelected ? DFCS_PUSHED : 0));
rect = lpInfo->DrawRect;
}
xOffs = max(0, ((lpInfo->DrawRect.right-lpInfo->DrawRect.left) - (textRect.right-textRect.left))/2);
yOffs = max(0, ((lpInfo->DrawRect.bottom-lpInfo->DrawRect.top) - (textRect.bottom-textRect.top))/2);
if (lpInfo->fSelected) {
xOffs++;
yOffs--;
}
pDC->ExtTextOut(lpInfo->DrawRect.left+xOffs, lpInfo->DrawRect.bottom-yOffs, 0, &lpInfo->DrawRect, lpCol[lpInfo->col].lpszTitle, len, NULL);
}
pDC->SelectObject(pOldFont);
pDC->SetBkMode(mode);
pDC->SetTextColor(clrFg);
}
void CSampleView::OwnerDraw_Cell(LPSFTTREE_OWNERDRAW lpInfo)
{
// calculate the cell size
RECT rect;
BITMAP bm;
// Set up CDC
CDC* pDC = CDC::FromHandle(lpInfo->hDC);
CDC DCTemp;
DCTemp.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = (CBitmap*) DCTemp.SelectObject(&m_hBitmap); // Select the bitmap
m_hBitmap.GetObject(sizeof(BITMAP), &bm);
SetRect(&rect, 0, 0, bm.bmWidth, bm.bmHeight);
if (lpInfo->style == SFTTREE_OD_CALC) {
// we need to return just the size of the cell we want to paint
lpInfo->DrawRect = rect;
} else {
// we need to paint the cell
::FillRect(*pDC, &lpInfo->DrawRect, (HBRUSH) (COLOR_WINDOW+1));
pDC->BitBlt(lpInfo->DrawRect.left, lpInfo->DrawRect.top, lpInfo->DrawRect.right-lpInfo->DrawRect.left, lpInfo->DrawRect.bottom-lpInfo->DrawRect.top,
&DCTemp, 0, 0, SRCCOPY);
}
DCTemp.SelectObject(pOldBitmap);
}
void CSampleView::OwnerDraw_Text(LPSFTTREE_OWNERDRAW lpInfo)
{
CString strText;
// Set up CDC for painting
CDC* pDC = CDC::FromHandle(lpInfo->hDC);
CSftTree* pTree = (CSftTree*) CWnd::FromHandle(lpInfo->hwndCtl);
ASSERT(pTree);
CFont* pFont = pTree->GetFont();
CFont* pOldFont = pDC->SelectObject(pFont);
pOldFont = pDC->SelectObject(pFont);
pTree->GetText(lpInfo->index, lpInfo->col, strText); // retrieve the cell text
if (lpInfo->style == SFTTREE_OD_CALC) {
// we need to return just the size of the cell we want to paint
RECT r;
SetRectEmpty(&r);
pDC->DrawText(strText, &r, DT_CALCRECT | DT_LEFT | DT_SINGLELINE);
InflateRect(&r, lpInfo->gap/2, 0);
lpInfo->DrawRect = r;
} else {
// we need to paint the cell
RECT r;
CBrush br;
br.CreateSysColorBrush(COLOR_3DFACE);
pDC->FillRect(&lpInfo->DrawRect, &br);
if (lpInfo->fSelected)
pTree->DrawSelectionOutline(lpInfo->hDC, &lpInfo->DrawRect, RGB(128,0,0), RGB(255,100,100), RGB(255,255,255), RGB(255,0,0));
r = lpInfo->DrawRect;
InflateRect(&r, -lpInfo->gap/2, 0);
pDC->DrawText(strText, &r, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
}
pDC->SelectObject(pOldFont);
}
BOOL CALLBACK CSampleView::OwnerDrawCallback(HWND hwnd, LPSFTTREE_OWNERDRAW lpInfo, SFTTREE_DWORD_PTR UserData)
{
CSampleView* pThis = (CSampleView*) UserData; // we defined CSampleView this pointer as user data in SetOwnerDrawCallback call
if (lpInfo->itemType == SFTTREE_OD_COLHEADER) {
pThis->OwnerDraw_Column_Header(lpInfo);
return TRUE;
}
if ((lpInfo->itemType == SFTTREE_OD_CELL || lpInfo->itemType == SFTTREE_OD_CELLTOOLTIP) && lpInfo->col == 1) {
if ((lpInfo->index % 5) == 0) {
pThis->OwnerDraw_Cell(lpInfo);
return TRUE;
} else if ((lpInfo->index % 4) == 0) {
pThis->OwnerDraw_Text(lpInfo);
return TRUE;
}
}
return FALSE;
}
sample_cpp_ownerdraw.htmlSftTreeDLL70_sample_cpp_ownerdraw.htmlFeedback / comments / error reports for this topic
© 2015 - Softel vdm, Inc. - www.softelvdm.com