📄 xhtmltree.cpp
字号:
}
}
else // not over an item
{
SetInsertMark(0, 0); // remove insert mark
m_hPreviousDropItem = 0;
if (m_hNoDropCursor)
SetCursor(m_hNoDropCursor); // set to no-drop cursor
else
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO)); // set to no-drop cursor
}
SetFocus();
}
else
#endif // XHTMLDRAGDROP
if (hItem)
{
// if mouse is on a different item, or has moved off state icon
if ((m_hHotItem && (m_hHotItem != hItem)) ||
(m_hHotItem && ((flags & TVHT_ONITEMSTATEICON) == 0)))
{
int nState = GetStateImage(m_hHotItem);
// a hot item can only be UNCHECKED, CHECKED, or CHECKED_TRISTATE
nState &= ~HDCheckboxImageList::HOT_INDEX;
// remove hot from previous hot item
SetItemState(m_hHotItem, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK);
m_hHotItem = NULL;
}
if ((m_hHotItem == NULL) && (flags & TVHT_ONITEMSTATEICON))
{
TRACE(_T("cursor over state image\n"));
int nState = GetStateImage(hItem);
if ((nState & HDCheckboxImageList::DISABLED_INDEX) == 0) // is it enabled?
{
// a hot item can only be UNCHECKED, CHECKED, or CHECKED_TRISTATE
nState |= HDCheckboxImageList::HOT_INDEX;
// remove hot from previous hot item
SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK);
m_hHotItem = hItem;
SetTimer(HOT_TIMER, 100, NULL); // timer in case mouse leaves window
}
}
CRect rect;
BOOL bOverAnchor = IsOverAnchor(hItem, point, &rect);
//TRACE(_T("bOverAnchor=%d\n"), bOverAnchor);
#ifdef XHTMLHTML
if (bOverAnchor)
m_Links.SetLinkCursor();
#endif // XHTMLHTML
if ((m_hAnchorItem && (m_hAnchorItem != hItem)) ||
(m_hAnchorItem && !bOverAnchor))
{
TRACE(_T("removing anchor 0x%X-----\n"), m_hAnchorItem);
GetItemRect(m_hAnchorItem, &rect, FALSE); // note: must get entire
// rect, since text might
// be shifted left
m_hAnchorItem = NULL;
InvalidateRect(&rect, FALSE);
}
else if ((m_hAnchorItem == NULL) && bOverAnchor)
{
TRACE(_T("adding anchor 0x%X-----\n"), hItem);
m_hAnchorItem = hItem;
TRACE(_T("mouse over anchor 0x%X-----\n"), hItem);
GetItemRect(hItem, &rect, FALSE); // note: must get entire
// rect, since text might
// be shifted left
InvalidateRect(&rect, FALSE);
SetTimer(HOT_TIMER, 80, NULL); // timer in case mouse leaves window
}
}
CTreeCtrl::OnMouseMove(nFlags, point);
}
//=============================================================================
HTREEITEM CXHtmlTree::IsOverItem(LPPOINT lpPoint /*= NULL*/)
//=============================================================================
{
CPoint point;
if (lpPoint)
{
point = *lpPoint;
}
else
{
::GetCursorPos(&point);
ScreenToClient(&point);
}
UINT flags = 0;
HTREEITEM hItem = HitTest(point, &flags);
return hItem;
}
//=============================================================================
BOOL CXHtmlTree::IsOverAnchor(HTREEITEM hItem, CPoint point, CRect *pRect /*= NULL*/)
//=============================================================================
{
BOOL rc = FALSE;
CRect rect(0,0,0,0);
XHTMLTREEDATA *pXTCD = GetItemDataStruct(hItem);
if (pXTCD && pXTCD->ds.bHasAnchor && pXTCD->bEnabled)
{
GetItemRect(hItem, &rect, TRUE);
// set rect to anchor boundaries
rect.left = pXTCD->ds.rectAnchor.left;
rect.right = pXTCD->ds.rectAnchor.right;
if (rect.PtInRect(point))
{
rc = TRUE;
}
}
if (pRect)
*pRect = rect;
return rc;
}
//=============================================================================
HCURSOR CXHtmlTree::SetCursor(HCURSOR hCursor)
//=============================================================================
{
if (hCursor == m_hCurrentCursor)
return m_hCurrentCursor;
m_hCurrentCursor = hCursor;
TRACE(_T("calling ::SetCursor %X\n"), hCursor);
return ::SetCursor(hCursor);
}
//=============================================================================
BOOL CXHtmlTree::IsLeftButtonUp()
//=============================================================================
{
BOOL rc = FALSE;
SHORT state = 0;
if (GetSystemMetrics(SM_SWAPBUTTON)) // check if buttons have been swapped
state = GetAsyncKeyState(VK_RBUTTON); // buttons swapped, get right button state
else
state = GetAsyncKeyState(VK_LBUTTON);
// if the most significant bit is set, the button is down
if (state >= 0)
rc = TRUE;
return rc;
}
//=============================================================================
// OnTimer - check if mouse has left, turn off underlining and hot state
void CXHtmlTree::OnTimer(UINT nIDEvent)
//=============================================================================
{
CPoint point;
::GetCursorPos(&point);
ScreenToClient(&point);
if (nIDEvent == HOT_TIMER)
{
// if mouse has left window, turn off hot and anchor highlighting
CRect rectClient;
GetClientRect(&rectClient);
if (!rectClient.PtInRect(point))
{
KillTimer(nIDEvent);
// mouse has left the window
if (m_hHotItem)
{
int nState = GetStateImage(m_hHotItem);
// a hot item can only be UNCHECKED, CHECKED, or CHECKED_TRISTATE
nState &= ~HDCheckboxImageList::HOT_INDEX;
// remove hot from previous hot item
SetItemState(m_hHotItem, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK);
m_hHotItem = NULL;
}
if (m_hAnchorItem)
{
// remove underline
CRect rectAnchor;
GetItemRect(m_hAnchorItem, &rectAnchor, FALSE);
m_hAnchorItem = NULL;
InvalidateRect(&rectAnchor, TRUE);
}
}
}
else if (nIDEvent == LBUTTONDOWN_TIMER) // timer set by WM_LBUTTONDOWN
{
HTREEITEM hItem = IsOverItem(&point);
if (IsLeftButtonUp())
{
TRACE(_T("mouse button is up >>>>>\n"));
KillTimer(nIDEvent);
HTREEITEM hItemSelected = GetSelectedItem();
#ifdef XHTMLDRAGDROP
if (m_bDragging) // case 1: user is dragging
{
if (hItem &&
(hItem != m_hItemButtonDown) &&
(!IsChildNodeOf(hItem, m_hItemButtonDown)))
{
HTREEITEM hAfter = hItem;
HTREEITEM hParent = GetParentItem(m_hItemButtonDown);
HTREEITEM hNewParent = GetParentItem(hAfter);
TRACE(_T("hParent=%X\n"), hParent);
// check if Shift key down
if ((m_dwDragOps & XHTMLTREE_DO_SHIFT_KEY) &&
(GetAsyncKeyState(VK_SHIFT) < 0) &&
!IsSeparator(hAfter)) //+++1.6
{
TRACE(_T("VK_SHIFT down, creating child item\n"));
hNewParent = hAfter;
hAfter = TVI_LAST;
}
else if (hParent == hAfter)
{
// dropping on parent
hNewParent = hParent;
hAfter = TVI_FIRST;
}
else if (ItemHasChildren(hAfter) && IsExpanded(hAfter)) //+++1.6
{
// dropping on node that is expanded
hNewParent = hAfter;
hAfter = TVI_FIRST;
}
else if (hNewParent == 0) //+++1.6
{
// multiple roots
}
StartMoveBranch(m_hItemButtonDown, hNewParent, hAfter);
}
else
{
TRACE(_T("ERROR can't drop on %X\n"), hItem);
SendRegisteredMessage(WM_XHTMLTREE_END_DRAG, 0, 0);
}
EndDragScroll();
}
else
#endif // XHTMLDRAGDROP
if (hItem && (hItem == hItemSelected)
&& !IsSeparator(hItem)) // case 2: user wants to edit a label
{
// clicking on a selected item
CEdit *pEdit = GetEditControl();
CRect rect;
GetItemRect(hItem, &rect, TRUE);
if (rect.PtInRect(point))
{
TRACE(_T("sending TVM_EDITLABEL\n"));
// click on item text, begin edit
SendMessage(TVM_EDITLABEL, 0, (LPARAM)hItem);
}
else if (pEdit && IsWindow(pEdit->m_hWnd))
{
TRACE(_T("sending WM_CLOSE to edit box\n"));
// click outside item text, end edit
pEdit->SendMessage(WM_CLOSE);
}
}
}
#ifdef XHTMLDRAGDROP
else // left button is down
{
//TRACE(_T("mouse button is down >>>>>\n"));
if (m_bDragging)
{
// check how long we've been hovering over same item
if (hItem && (hItem == m_hPreviousDropItem))
{
if (GetBit(m_dwDragOps, XHTMLTREE_DO_AUTO_EXPAND))
{
// still over same item
if ((GetTickCount() - m_dwDropHoverTime) > MIN_HOVER_TIME)
{
// min hover time has passed, expand node if it has children
Expand(hItem, TVE_EXPAND);
}
}
}
if (m_bAutoScroll)
AutoScroll(hItem);
}
}
#endif // XHTMLDRAGDROP
}
#ifdef XHTMLDRAGDROP
else if (nIDEvent == CTRL_UP_TIMER)
{
// check if Ctrl key down
if (!IsCtrlDown())
{
TRACE(_T("VK_CONTROL up\n"));
KillTimer(nIDEvent);
if (IsOverItem() && m_bDragging)
{
SetDragCursor();
}
}
}
else if (nIDEvent == SHIFT_UP_TIMER)
{
if ((m_dwDragOps & XHTMLTREE_DO_SHIFT_KEY) &&
(GetAsyncKeyState(VK_SHIFT) >= 0))
{
TRACE(_T("VK_SHIFT up\n"));
KillTimer(nIDEvent);
HTREEITEM hItem = IsOverItem();
if (hItem)
SetInsertMark(hItem, TRUE);
SelectDropTarget(NULL);
}
}
else if (nIDEvent == SELECT_TIMER) // timer set by WM_LBUTTONDOWN
{
KillTimer(nIDEvent);
HTREEITEM hItem = IsOverItem();
if (hItem)
{
SelectItem(hItem);
}
}
#endif // XHTMLDRAGDROP
CTreeCtrl::OnTimer(nIDEvent);
}
//=============================================================================
BOOL CXHtmlTree::OnEraseBkgnd(CDC* pDC)
//=============================================================================
{
CRect rectClientx;
GetClientRect(&rectClientx);
pDC->FillSolidRect(rectClientx, m_crWindow);
return TRUE;
}
//=============================================================================
CXHtmlTree& CXHtmlTree::SetCheck(HTREEITEM hItem, BOOL fCheck /*= TRUE*/)
//=============================================================================
{
ASSERT(hItem);
if (hItem && m_bCheckBoxes)
{
TRACE(_T("in CXHtmlTree::SetCheck: %d <%s>\n"), fCheck, GetItemText(hItem));
XHTMLTREEDATA *pXTCD = GetItemDataStruct(hItem);
if (pXTCD && pXTCD->bEnabled && !pXTCD->bSeparator) //+++1.6
{
BOOL bOldChecked = pXTCD->bChecked;
pXTCD->bChecked = fCheck;
UINT nState = GetStateImage(hItem);
//TRACE(_T("nState=0x%X nOldState=0x%X ~~~~~\n"), nState, nOldState);
SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK);
if (m_bSmartCheck && (bOldChecked != fCheck))
{
HTREEITEM hParent = hItem;
int nCount = 0;
if (fCheck)
nCount = pXTCD->nChildren - pXTCD->nChecked + 1;//bOldCheck ? 1 : 0;
else
nCount = -(pXTCD->nChecked + 1);//bOldCheck ? 1 : 0);
SetCheckChildren(hItem, fCheck);
// find all parents, adjust their checked counts
TRACE(_T("starting nCount=%d\n"), nCount);
while ((hParent = GetParentItem(hParent)) != NULL)
{
nCount = SetCheckParent(hParent, nCount);
}
}
SendRegisteredMessage(WM_XHTMLTREE_CHECKBOX_CLICKED, hItem, fCheck);
}
}
return *this;
}
//=============================================================================
void CXHtmlTree::SetHotItem(HTREEITEM hItem, UINT nFlags)
//=============================================================================
{
if (m_hHotItem && (m_hHotItem != hItem))
{
int nState = GetStateImage(m_hHotItem);
// a hot item can only be UNCHECKED, CHECKED, or CHECKED_TRISTATE
nState &= ~HDCheckboxImageList::HOT_INDEX;
// remove hot from previous hot item
SetItemState(m_hHotItem, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK);
m_hHotItem = NULL;
}
if (hItem && (m_hHotItem == NULL) && (nFlags & TVHT_ONITEMSTATEICON))
{
TRACE(_T("cursor over state image\n"));
int nState = GetStateImage(hItem);
// a hot item can only be UNCHECKED, CHECKED, or CHECKED_TRISTATE
nState |= HDCheckboxImageList::HOT_INDEX;
// remove hot from previous hot item
SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK);
m_hHotItem = hItem;
}
}
//=============================================================================
LRESULT CXHtmlTree::SendRegisteredMessage(UINT nMessage,
HTREEITEM hItem,
LPARAM lParam /*= 0*/)
//=============================================================================
{
LRESULT lResult = 0;
CWnd *pWnd = GetParent();
if (!pWnd)
pWnd = GetOwner();
if (pWnd && ::IsWindow(pWnd->m_hWnd))
{
XHTMLTREEMSGDATA msgdata = { 0 };
msgdata.hCtrl = m_hWnd;
msgdata.nCtrlId = GetDlgCtrlID();
msgdata.hItem = hItem;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -