📄 tlmouse.c
字号:
pWD->iNumberSelected = 0;
pHit->state |= TLIS_DRAGGEDOVER;
(pWD->iNumberSelected)++;
pWD->nmTreeList.itemNew.hItem = (HTLITEM)pHit;
pWD->nmTreeList.itemNew.state = pHit->state;
pWD->nmTreeList.hdr.code = TLN_DRAGGEDOVER;
if (pWD->focusItem != pHit)
{
if (pWD->focusItem)
{
pWD->focusItem->state &= ~TLIS_FOCUSED;
pWD->nmTreeList.itemOld.hItem = (HTLITEM)pWD->focusItem;
pWD->nmTreeList.itemOld.state = pWD->focusItem->state;
}
}
bRet = TRUE;
break;
}
if (pWD->nmTreeList.hdr.code)
{
pWD->nmTreeList.flags |= TLC_BYMOUSE;
pWD->nmTreeList.ptDrag = mpt;
SendMessage (pWD->hWndParent,
WM_NOTIFY, pWD->id, (LPARAM)&(pWD->nmTreeList));
}
return bRet;
}
// _______________________________________________
//
// cursor is moving during internal drag operation
static BOOL
sDragOverInternalBetween (
TLWndData* pWD,
LPARAM lParam)
{
INT irow, ihalf, iquarter, iHitType;
TLTreeItem* pHit;
POINT mpt, mpt2;
BOOL bRet;
BOOL bShift = FALSE;
BOOL bAfter = FALSE;
BOOL bOver = FALSE;
mpt.x = LOWORD (lParam);
mpt.y = HIWORD (lParam);
ihalf = (pWD->iRowHeight) >> 1;
iquarter = (pWD->iRowHeight) >> 2;
mpt2.x = mpt.x;
mpt2.y = mpt.y + ihalf;
pWD->nmTreeList.hdr.code = 0;
pWD->nmTreeList.itemNew.hItem = NULL;
pWD->nmTreeList.itemNew.state = 0;
pWD->nmTreeList.itemOld.hItem = NULL;
pWD->nmTreeList.flags = 0;
if (mpt2.y < iquarter)
{
pHit = pWD->rootItem;
iHitType = TLK_SELECT;
}
else
{
pHit = sPointSearch (pWD->rootItem, mpt, &iHitType);
if (pHit)
{
if (pHit->state & TLIS_DROPONALLOWED)
{
if (mpt.y > (pHit->selectRect.bottom - iquarter))
bAfter = TRUE;
else if (mpt.y > (pHit->selectRect.top + iquarter))
bOver = TRUE;
}
else
{
if (mpt.y > (pHit->selectRect.top + ihalf))
bAfter = TRUE;
}
}
}
switch (iHitType) {
case TLK_NONE :
TLDeDragOverTree (pWD, pWD->rootItem, NULL);
if (PtInRect (&pWD->tlRect, mpt))
{
SetCursor (pWD->hCursorDragging);
pWD->nmTreeList.flags |= TLC_DRAGAFTEREND;
}
else
SetCursor (pWD->hCursorNoDrag);
pWD->firstSelectItem = NULL;
if (pWD->focusItem)
{
pHit = pWD->focusItem;
pWD->focusItem = NULL;
}
pWD->nmTreeList.itemNew.hItem = NULL;
pWD->nmTreeList.itemNew.state = 0;
pWD->nmTreeList.hdr.code = TLN_DRAGGEDOVER;
bRet = FALSE;
break;
default :
if (pWD->uDragScrollState == 0)
{
irow = 0;
TLGetRow (pWD->rootItem, pHit, &irow);
if (irow == pWD->iFirstRow)
{
pWD->iFirstRow--;
if (pWD->iFirstRow < 0)
pWD->iFirstRow = 0;
else
{
SetTimer (pWD->hWnd,
DRAGSCROLLTIMERID, DRAGSCROLLTIME, NULL);
pWD->uDragScrollState = DRAGSCROLL_DOWN;
pWD->nmTreeList.itemNew.hItem = NULL;
pWD->nmTreeList.itemNew.state = 0;
pWD->nmTreeList.hdr.code = TLN_AUTOSCROLLED;
pWD->nmTreeList.flags |= TLC_BYMOUSE;
SendMessage (pWD->hWndParent, WM_NOTIFY,
pWD->id, (LPARAM)&(pWD->nmTreeList));
}
}
if (irow == (pWD->iFirstRow + pWD->iMaxRows))
{
pWD->iFirstRow++;
SetTimer (pWD->hWnd,
DRAGSCROLLTIMERID, DRAGSCROLLTIME, NULL);
pWD->uDragScrollState = DRAGSCROLL_UP;
pWD->nmTreeList.itemNew.hItem = NULL;
pWD->nmTreeList.itemNew.state = 0;
pWD->nmTreeList.hdr.code = TLN_AUTOSCROLLED;
pWD->nmTreeList.flags |= TLC_BYMOUSE;
SendMessage (pWD->hWndParent, WM_NOTIFY, pWD->id,
(LPARAM)&(pWD->nmTreeList));
}
}
TLDeDragOverTree (pWD, pWD->rootItem, pHit);
SetCursor (pWD->hCursorDragging);
pWD->iNumberSelected = 0;
if (bAfter)
{
pHit->state &= ~(TLIS_DRAGGEDOVER|TLIS_DRAGGEDBEFORE);
pHit->state |= TLIS_DRAGGEDAFTER;
pWD->nmTreeList.flags |= TLC_DRAGAFTER;
}
else if (bOver)
{
pHit->state &= ~(TLIS_DRAGGEDBEFORE|TLIS_DRAGGEDAFTER);
pHit->state |= TLIS_DRAGGEDOVER;
}
else
{
pHit->state &= ~(TLIS_DRAGGEDOVER|TLIS_DRAGGEDAFTER);
pHit->state |= TLIS_DRAGGEDBEFORE;
pWD->nmTreeList.flags |= TLC_DRAGBEFORE;
}
(pWD->iNumberSelected)++;
pWD->nmTreeList.itemNew.hItem = (HTLITEM)pHit;
pWD->nmTreeList.itemNew.state = pHit->state;
pWD->nmTreeList.hdr.code = TLN_DRAGGEDOVER;
if (pWD->focusItem != pHit)
{
if (pWD->focusItem)
{
pWD->focusItem->state &= ~TLIS_FOCUSED;
pWD->nmTreeList.itemOld.hItem = (HTLITEM)pWD->focusItem;
pWD->nmTreeList.itemOld.state = pWD->focusItem->state;
}
}
bRet = TRUE;
break;
}
if (pWD->nmTreeList.hdr.code)
{
pWD->nmTreeList.flags |= TLC_BYMOUSE;
pWD->nmTreeList.ptDrag = mpt;
SendMessage (pWD->hWndParent,
WM_NOTIFY, pWD->id, (LPARAM)&(pWD->nmTreeList));
}
return bRet;
}
// _______________________________________________
//
// Show tooltip text if text is truncated
static BOOL
sStringContainsUTF8 (
CHAR* psz)
{
// ok, so this is bogus, we're really just determining
// if the string is ASCII or not. UTF8 is too complicated.
while (*psz)
{
if (*psz & 0x80)
return TRUE;
psz++;
}
return FALSE;
}
// _______________________________________________
//
// Show tooltip text if text is truncated
static void
sShowTooltipText (
TLWndData* pWD,
TLTreeItem* pHit,
int iHitSubItem)
{
BOOL bActivate = FALSE;
TLListItem* pli;
TLColumnItem* pci;
POINT pt;
int i;
LPTSTR psz;
UINT state;
if (pHit && pWD->bTreeFocused)
{
if (!pWD->bToolTipEnabled)
{
pWD->bToolTipEnabled = TRUE;
return;
}
if (iHitSubItem == 0)
{
if (pHit->state & TLIS_TRUNCATED)
{
pt.x = pHit->hiliteRect.left -1;
pt.y = pHit->hiliteRect.top -1;
psz = pHit->pszText;
state = pHit->state;
bActivate = TRUE;
}
}
else
{
pli = pHit->listItem;
for (i=1; i<iHitSubItem; i++) pli = pli->nextItem;
if (pli->state & TLIS_TRUNCATED)
{
pt.x = pWD->iFirstColumnWidth - pWD->iHorizontalPos +3;
pt.y = pHit->selectRect.top -1;
pci = pWD->columnItem;
for (i=1; i<iHitSubItem; i++)
{
pt.x += pci->cx;
pci = pci->nextItem;
}
psz = pli->pszText;
state = pli->state;
bActivate = TRUE;
}
}
}
// if string contains UTF8, bail out. This type of
// tooltip does not support Unicode.
if (bActivate)
{
if (sStringContainsUTF8 (psz))
bActivate = FALSE;
}
if (bActivate)
{
TOOLINFO ti;
LPSTR p;
p = strchr (psz, '\n');
if (p)
psz = p+1;
ZeroMemory (&ti, sizeof(TOOLINFO));
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_ABSOLUTE|TTF_TRACK|TTF_IDISHWND|TTF_TRANSPARENT;
ti.hwnd = pWD->hWnd;
ti.uId = (LPARAM)pWD->hWnd;
ti.lpszText = psz;
ClientToScreen (pWD->hWnd, &pt);
SendMessage (pWD->hWndToolTip,
TTM_TRACKPOSITION, 0, MAKELONG (pt.x, pt.y));
if (state & TLIS_ITALICS)
{
SendMessage (pWD->hWndToolTip,
WM_SETFONT, (WPARAM)pWD->hFontItalic, 0);
}
else
{
SendMessage (pWD->hWndToolTip,
WM_SETFONT, (WPARAM)pWD->hFont, 0);
}
SendMessage (pWD->hWndToolTip, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
SendMessage (pWD->hWndToolTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);
SetTimer (pWD->hWnd, TOOLTIPTIMERID, TOOLTIPTIME, NULL);
}
else
SendMessage (pWD->hWndToolTip, TTM_TRACKACTIVATE, FALSE, 0);
}
// _______________________________________________
//
// Item is being drag-selected -- scroll window appropriately
static BOOL
sDragSelectAutoScroll (
TLWndData* pWD,
TLTreeItem* p)
{
int itemRow = 0;
if (TLGetRow (pWD->rootItem, p, &itemRow))
{
if ((itemRow-pWD->iFirstRow) >= (pWD->iMaxRows-1))
{
pWD->iFirstRow = itemRow - pWD->iMaxRows +2;
if (pWD->iFirstRow < 0)
pWD->iFirstRow = 0;
return TRUE;
}
if (itemRow <= pWD->iFirstRow)
{
pWD->iFirstRow = max (0, itemRow-1);
return TRUE;
}
}
return FALSE;
}
// _______________________________________________
//
// query parent via notification and display tooltip
void
TLShowNotifyToolTip (
TLWndData* pWD,
BOOL bShow)
{
TOOLINFOW ti;
POINT mpt;
RECT rc;
if (!bShow)
{
pWD->tooltipTreeItem = NULL;
SendMessage (pWD->hWndToolTip, TTM_TRACKACTIVATE, FALSE, 0);
return;
}
pWD->nmTreeList.itemNew.hItem = (HTLITEM)(pWD->tooltipTreeItem);
pWD->nmTreeList.hdr.code = TLN_TOOLTIPQUERY;
SendMessage (pWD->hWndParent,
WM_NOTIFY, pWD->id, (LPARAM)&(pWD->nmTreeList));
ZeroMemory (&ti, sizeof(TOOLINFO));
ti.cbSize = sizeof(TOOLINFO);
ti.hwnd = pWD->hWnd;
ti.uId = (LPARAM)pWD->hWnd;
ti.lpszText = pWD->nmTreeList.pszText;
GetCursorPos (&mpt);
GetWindowRect (pWD->hWnd, &rc);
if (PtInRect (&rc, mpt))
{
SendMessage (pWD->hWndToolTip,
TTM_TRACKPOSITION, 0, MAKELONG (mpt.x, mpt.y+TOOLTIPVERTICALOFFSET));
SendMessage (pWD->hWndToolTip, TTM_UPDATETIPTEXTW, 0, (LPARAM)&ti);
SendMessage (pWD->hWndToolTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);
SetTimer (pWD->hWnd, TOOLTIPTIMERID, TOOLTIPTIME, NULL);
}
}
// _______________________________________________
//
// Handle mouse move event
void
TLMouseMove (
TLWndData* pWD,
WPARAM wParam,
LPARAM lParam)
{
int iHitSubItem = 0;
int iHitType;
POINT mpt;
TLTreeItem* pHit;
mpt.x = LOWORD (lParam);
mpt.y = HIWORD (lParam);
// check if mouse is in drag selection region
if (pWD->style & TLS_DRAGSELECTION)
{
if (mpt.x < (DRAGSELECTINDENT - pWD->iHorizontalPos))
SetCursor (pWD->hCursorDragSelect);
else
SetCursor (pWD->hCursorNormal);
}
else
SetCursor (pWD->hCursorNormal);
// if left button is not pressed, make sure dragging is finished
if (!(wParam & MK_LBUTTON))
{
pWD->bSelectDragging = FALSE;
if (pWD->bDragging)
{
TLEndDrag (pWD, lParam);
pWD->bDragging = FALSE;
}
// then worry about whether we should display tooltip text
if (wParam == 0)
{
pHit = sTextItemSearch (pWD->rootItem, pWD->columnItem,
pWD->iFirstColumnWidth - pWD->iHorizontalPos,
mpt, &iHitSubItem);
if (pWD->style & TLS_TOOLTIPNOTIFY)
{
if (pHit != pWD->tooltipTreeItem)
{
KillTimer (pWD->hWnd, TOOLTIPDWELLTIMERID);
TLShowNotifyToolTip (pWD, FALSE);
}
if (pHit)
{
if (pHit != pWD->tooltipTreeItem)
{
pWD->tooltipTreeItem = pHit;
SetTimer (pWD->hWnd,
TOOLTIPDWELLTIMERID, TOOLTIPDWELLTIME, NULL);
}
}
}
else
sShowTooltipText (pWD, pHit, iHitSubItem);
}
return;
}
// user is doing a drag selection
if (pWD->bSelectDragging)
{
pHit = sPointSearchDragSelect (pWD->rootItem, mpt, &iHitType);
if (iHitType == TLK_SELECT)
{
TLDeselectTree (pWD, pWD->rootItem, NULL);
pWD->iNumberSelected = 0;
TLSelectRange (pWD, pWD->rootItem, pHit, NULL);
if (pHit->state & TLIS_SELECTED)
{
pWD->nmTreeList.itemNew.hItem = (HTLITEM)pHit;
pWD->nmTreeList.itemNew.state = pHit->state;
pWD->nmTreeList.hdr.code = TLN_SELCHANGED;
pWD->nmTreeList.flags |= TLC_BYMOUSE;
if (pWD->iNumberSelected > 1)
pWD->nmTreeList.flags |= TLC_MULTIPLE;
pWD->nmTreeList.ptDrag = mpt;
SendMessage (pWD->hWndParent,
WM_NOTIFY, pWD->id, (LPARAM)&(pWD->nmTreeList));
}
if (sDragSelectAutoScroll (pWD, pHit))
{
InvalidateRect (pWD->hWnd, &pWD->tlInval, TRUE);
SetTimer (pWD->hWnd, DRAGSCROLLTIMERID, DRAGSCROLLTIME, NULL);
}
}
}
// user is dragging something around within window
else if (pWD->bDragging && (pWD->style & TLS_INTERNALDRAG))
{
if (pWD->style & TLS_DROPBETWEEN)
sDragOverInternalBetween (pWD, lParam);
else
sDragOverInternal (pWD, lParam);
}
// if user has previously pressed an active region
else if (pWD->clickedTreeItem)
{
if (pWD->clickedListItem)
{
if (sPointInActiveArea (pWD->clickedTreeItem, pWD->columnItem,
pWD->iFirstColumnWidth - pWD->iHorizontalPos, mpt))
{
pWD->clickedListItem->state |= TLIS_CLICKED;
}
else
pWD->clickedListItem->state &= ~TLIS_CLICKED;
TLInvalidateItem (pWD, pWD->clickedTreeItem);
}
}
// user is starting a drag operation
else if (pWD->bTreeFocused && !pWD->bDragging)
{
if ((pWD->iNumberSelected > 0) && (pWD->ptButtonDown.x > 0))
{
if ((abs(pWD->ptButtonDown.x-LOWORD(lParam))>DRAGDEADZONE) ||
(abs(pWD->ptButtonDown.y-HIWORD(lParam))>DRAGDEADZONE))
{
NMHDR nmhdr;
nmhdr.code = TLN_BEGINDRAG;
SendMessage (pWD->hWndParent,
WM_NOTIFY, pWD->id, (LPARAM)&nmhdr);
if (nmhdr.code == TLN_BEGINDRAG)
{
pWD->bDragging = TRUE;
if (pWD->style & TLS_INTERNALDRAG)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -