orderedtreectrl.cpp
来自「管理项目进度工具的原代码」· C++ 代码 · 共 715 行 · 第 1/2 页
CPP
715 行
// ToDoCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "orderedtreeCtrl.h"
#include "..\shared\holdredraw.h"
#include "..\shared\themed.h"
#include "..\shared\treectrlhelper.h"
#include "..\shared\misc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// COrderedTreeCtrl
const UINT MINGUTTER = 16;
static CMap<int, int&, UINT, UINT&> g_mapWidths;
COrderedTreeCtrl::COrderedTreeCtrl(DWORD dwGutterStyles) :
// because CTreeCtrlHelper wants a reference passed
// to its constructor we have to pass '*this'. however
// the compiler complains because 'this' is not yet
// fully constructed.
#pragma warning (disable: 4355)
m_ht(*this),
#pragma warning (default: 4355)
m_gutter(dwGutterStyles),
m_bShowingPosColumn(TRUE),
m_crGridlines(OTC_GRIDCOLOR),
m_crAltLines((COLORREF)-1),
m_bWantInit(FALSE)
{
AddGutterColumn(OTC_POSCOLUMNID, "Pos"); // for the pos string
EnableGutterColumnHeaderClicking(OTC_POSCOLUMNID, FALSE);
}
COrderedTreeCtrl::~COrderedTreeCtrl()
{
}
BEGIN_MESSAGE_MAP(COrderedTreeCtrl, CTreeCtrl)
//{{AFX_MSG_MAP(COrderedTreeCtrl)
ON_WM_SETTINGCHANGE()
//}}AFX_MSG_MAP
ON_WM_STYLECHANGED()
ON_NOTIFY_REFLECT_EX(TVN_ITEMEXPANDED, OnItemexpanded)
ON_NOTIFY_REFLECT_EX(NM_CUSTOMDRAW, OnCustomDraw)
ON_NOTIFY_REFLECT_EX(NM_CLICK, OnClick)
ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
ON_REGISTERED_MESSAGE(WM_NCG_GETFIRSTVISIBLETOPLEVELITEM, OnGutterGetFirstVisibleTopLevelItem)
ON_REGISTERED_MESSAGE(WM_NCG_GETNEXTITEM, OnGutterGetNextItem)
ON_REGISTERED_MESSAGE(WM_NCG_DRAWITEM, OnGutterDrawItem)
ON_REGISTERED_MESSAGE(WM_NCG_RECALCCOLWIDTH, OnGutterRecalcColWidth)
ON_REGISTERED_MESSAGE(WM_NCG_POSTNCDRAW, OnGutterPostNcDraw)
ON_REGISTERED_MESSAGE(WM_NCG_GETITEMRECT, OnGutterGetItemRect)
ON_REGISTERED_MESSAGE(WM_NCG_GETFIRSTCHILDITEM, OnGutterGetFirstChildItem)
ON_REGISTERED_MESSAGE(WM_NCG_POSTDRAWITEM, OnGutterPostDrawItem)
ON_REGISTERED_MESSAGE(WM_NCG_HITTEST, OnGutterHitTest)
ON_REGISTERED_MESSAGE(WM_NCG_NOTIFYITEMCLICK, OnGutterNotifyItemClick)
ON_REGISTERED_MESSAGE(WM_NCG_ISITEMSELECTED, OnGutterIsItemSelected)
ON_REGISTERED_MESSAGE(WM_NCG_GETSELECTEDCOUNT, OnGutterGetSelectedCount)
ON_REGISTERED_MESSAGE(WM_NCG_GETPARENTITEM, OnGutterGetParentID)
ON_REGISTERED_MESSAGE(WM_NCG_WANTRECALC, OnGutterWantRecalc)
ON_REGISTERED_MESSAGE(WM_NCG_WANTREDRAW, OnGutterWantRedraw)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COrderedTreeCtrl message handlers
void COrderedTreeCtrl::PreSubclassWindow()
{
m_gutter.AddRecalcMessage(TVM_INSERTITEM);
m_gutter.AddRecalcMessage(TVM_DELETEITEM);
m_gutter.AddRecalcMessage(TVM_EXPAND);
m_gutter.AddRedrawMessage(WM_KEYUP); // only way to catch keyboard navigation (at present)
m_gutter.AddRedrawMessage(WM_SYSKEYUP); // only way to catch ALT+keyboard navigation (at present)
m_gutter.AddRedrawMessage(WM_KEYDOWN); // only way to catch keyboard navigation (at present)
m_gutter.AddRedrawMessage(WM_SYSKEYDOWN); // only way to catch ALT+keyboard navigation (at present)
m_gutter.AddRedrawMessage(TVM_SELECTITEM);
m_gutter.AddRedrawMessage(TVM_SORTCHILDREN);
m_gutter.AddRedrawMessage(TVM_SORTCHILDRENCB);
m_gutter.AddRedrawMessage(WM_COMMAND, EN_KILLFOCUS);
CTreeCtrl::PreSubclassWindow();
// note: its too early to initialize the gutter here because
// MFC hasn't done its bit yet, so initilization is done
// in WindowProc (for now)
m_bWantInit = TRUE;
}
LRESULT COrderedTreeCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if (m_bWantInit && !m_gutter.IsInitialized())
{
m_bWantInit = FALSE;
m_gutter.Initialize(GetSafeHwnd());
}
return CTreeCtrl::WindowProc(message, wParam, lParam);
}
void COrderedTreeCtrl::SetAlternateLineColor(COLORREF color)
{
if (m_crAltLines != color)
{
m_crAltLines = color;
Invalidate();
RedrawGutter();
}
}
BOOL COrderedTreeCtrl::PtInHeader(CPoint ptScreen) const
{
return m_gutter.PtInHeader(ptScreen);
}
COLORREF COrderedTreeCtrl::GetItemLineColor(HTREEITEM hti)
{
if (m_crAltLines != -1 && TCH().ItemLineIsOdd(hti))
return m_crAltLines;
// else
return GetSysColor(COLOR_WINDOW);
}
BOOL COrderedTreeCtrl::ShowGutterPosColumn(BOOL bShow)
{
if (m_bShowingPosColumn != bShow)
{
m_bShowingPosColumn = bShow;
m_gutter.RecalcGutter();
return TRUE;
}
// else no change
return FALSE;
}
void COrderedTreeCtrl::SetGridlineColor(COLORREF color)
{
if (m_crGridlines != color)
{
m_crGridlines = color;
if (GetSafeHwnd())
{
m_gutter.Redraw();
Invalidate();
}
}
}
int COrderedTreeCtrl::AddGutterColumn(UINT nColID, LPCTSTR szTitle, UINT nWidth, UINT nTextAlign)
{
return m_gutter.AddColumn(nColID, szTitle, nWidth, nTextAlign);
}
void COrderedTreeCtrl::PressGutterColumnHeader(UINT nColID, BOOL bPress)
{
m_gutter.PressHeader(nColID, bPress);
}
void COrderedTreeCtrl::SetGutterColumnHeaderTitle(UINT nColID, LPCTSTR szTitle, LPCTSTR szFont)
{
m_gutter.SetHeaderTitle(nColID, szTitle, szFont, FALSE);
}
void COrderedTreeCtrl::SetGutterColumnHeaderTitle(UINT nColID, UINT nSymbol, LPCTSTR szFont)
{
// Valik - cast to TCHAR is necessary or the compiler complains under VC 7.1
m_gutter.SetHeaderTitle(nColID, CString(static_cast<TCHAR>(nSymbol)), szFont, TRUE);
}
void COrderedTreeCtrl::SetGutterColumnSort(UINT nColID, NCGSORT nSortDir)
{
m_gutter.SetColumnSort(nColID, nSortDir);
}
void COrderedTreeCtrl::EnableGutterColumnHeaderClicking(UINT nColID, BOOL bEnable)
{
m_gutter.EnableHeaderClicking(nColID, bEnable);
}
LRESULT COrderedTreeCtrl::OnGutterGetFirstVisibleTopLevelItem(WPARAM /*wParam*/, LPARAM lParam)
{
ASSERT (lParam);
return (LRESULT)TCH().GetFirstVisibleTopLevelItem(*((LPINT)lParam));
}
LRESULT COrderedTreeCtrl::OnGutterGetNextItem(WPARAM /*wParam*/, LPARAM lParam)
{
return (LRESULT)CTreeCtrl::GetNextItem((HTREEITEM)lParam, TVGN_NEXT);
}
LRESULT COrderedTreeCtrl::OnGutterWantRecalc(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
TCH().BuildVisibleIndexMap();
// do not recalc if editing a label
if (GetEditControl() != NULL)
return 1L; // cancel recalc
// else
return 0L;
}
LRESULT COrderedTreeCtrl::OnGutterWantRedraw(WPARAM /*wParam*/, LPARAM lParam)
{
MSG* pMsg = (MSG*)lParam;
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
{
switch (pMsg->wParam) // what key
{
// ignore modifiers
case VK_CONTROL:
case VK_SHIFT:
case VK_MENU:
return TRUE; // prevent redraw
}
}
break;
}
return FALSE; // allow redraw
}
LRESULT COrderedTreeCtrl::OnGutterGetFirstChildItem(WPARAM /*wParam*/, LPARAM lParam)
{
HTREEITEM hti = (HTREEITEM)lParam;
if (ItemHasChildren(hti) && (GetItemState(hti, TVIS_EXPANDED) & TVIS_EXPANDED))
return (LRESULT)GetChildItem(hti);
return 0;
}
LRESULT COrderedTreeCtrl::OnGutterDrawItem(WPARAM /*wParam*/, LPARAM lParam)
{
NCGDRAWITEM* pNCGDI = (NCGDRAWITEM*)lParam;
if (pNCGDI->nColID == OTC_POSCOLUMNID)
{
CRect rItem(pNCGDI->rItem);
NcDrawItem(pNCGDI->pDC, pNCGDI->dwItem, pNCGDI->dwParentItem,
pNCGDI->nColID, rItem, pNCGDI->nLevel,
pNCGDI->nItemPos, pNCGDI->bSelected, pNCGDI->rWindow);
return TRUE; // we handled it
}
// else
return FALSE;
}
LRESULT COrderedTreeCtrl::OnGutterPostDrawItem(WPARAM /*wParam*/, LPARAM lParam)
{
NCGDRAWITEM* pNCGDI = (NCGDRAWITEM*)lParam;
if (pNCGDI->dwParentItem)
PostNcDrawItem(pNCGDI->pDC, pNCGDI->dwParentItem, pNCGDI->rItem, pNCGDI->nLevel);
return FALSE; // to let our parent handle it too
}
LRESULT COrderedTreeCtrl::OnGutterPostNcDraw(WPARAM /*wParam*/, LPARAM lParam)
{
NCGDRAWITEM* pNCGDI = (NCGDRAWITEM*)lParam;
PostNcDraw(pNCGDI->pDC, pNCGDI->rWindow);
return FALSE; // to let our parent handle it too
}
LRESULT COrderedTreeCtrl::OnGutterRecalcColWidth(WPARAM /*wParam*/, LPARAM lParam)
{
NCGRECALCCOLUMN* pNCRC = (NCGRECALCCOLUMN*)lParam;
return RecalcColumnWidth(pNCRC->pDC, pNCRC->nColID, pNCRC->nWidth);
}
LRESULT COrderedTreeCtrl::OnGutterGetItemRect(WPARAM /*wParam*/, LPARAM lParam)
{
NCGITEMRECT* pNCGGI = (NCGITEMRECT*)lParam;
return GetItemRect((HTREEITEM)pNCGGI->dwItem, &pNCGGI->rItem, TRUE);
}
LRESULT COrderedTreeCtrl::OnGutterGetParentID(WPARAM /*wParam*/, LPARAM lParam)
{
return (DWORD)GetParentItem((HTREEITEM)lParam);
}
LRESULT COrderedTreeCtrl::OnGutterIsItemSelected(WPARAM /*wParam*/, LPARAM lParam)
{
NCGITEMSELECTION* pNCGIS = (NCGITEMSELECTION*)lParam;
HTREEITEM hti = (HTREEITEM)pNCGIS->dwItem;
pNCGIS->bSelected = (GetItemState(hti, TVIF_STATE) & TVIS_SELECTED);
return TRUE;
}
LRESULT COrderedTreeCtrl::OnGutterGetSelectedCount(WPARAM /*wParam*/, LPARAM lParam)
{
int* pCount = (int*)lParam;
*pCount = GetSelectedItem() ? 1 : 0;
return TRUE;
}
LRESULT COrderedTreeCtrl::OnGutterHitTest(WPARAM /*wParam*/, LPARAM lParam)
{
CPoint point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
UINT nFlags = 0;
HTREEITEM hti = HitTest(point, &nFlags);
return (LRESULT)hti;
}
void COrderedTreeCtrl::PostNcDraw(CDC* pDC, const CRect& rWindow)
{
// vertical divider
if (m_crGridlines != -1 && GutterHasStyle(NCGS_RIGHTCOLUMNS) && !(GetStyle() & WS_VSCROLL))
{
pDC->FillSolidRect(rWindow.left, rWindow.top, 1, rWindow.Height(), m_crGridlines);
}
}
void COrderedTreeCtrl::NcDrawItem(CDC* pDC, DWORD dwItem, DWORD dwParentItem, UINT nColID, CRect& rItem,
int nLevel, int nPos, BOOL bSelected, const CRect& rWindow)
{
HTREEITEM hti = (HTREEITEM)dwItem;
if (nColID == OTC_POSCOLUMNID) // this is all we deal with
{
// extract the parent pos
CString sPos, sParentPos;
static CMap<DWORD, DWORD, CString, LPCTSTR> mapParentPos;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?