📄 tlmouse.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
TLMouse.c - handle tree list mouse events
$Id: TLMouse.c,v 1.24 2002/10/01 18:27:00 pbj Exp $
____________________________________________________________________________*/
#include "TLIntern.h"
#include "math.h"
#define DRAGDEADZONE 2
#define WHEELTHRESHOLD WHEEL_DELTA
#define TLK_NONE 0x0000
#define TLK_BUTTON 0x0001
#define TLK_SELECT 0x0002
#define TLK_ACTIVE 0x0003
#define TOOLTIPVERTICALOFFSET 20
// _______________________________________________
//
// remove tooltip text
BOOL
TLKillToolTip (
TLWndData* pWD)
{
POINT pt;
RECT rc;
GetCursorPos (&pt);
ScreenToClient (pWD->hWnd, &pt);
GetClientRect (pWD->hWnd, &rc);
if (!PtInRect (&rc, pt))
{
SendMessage (pWD->hWndToolTip, TTM_TRACKACTIVATE, FALSE, 0);
return TRUE;
}
else
return FALSE;
}
// _______________________________________________
//
// Determine if mouse is over item element
static INT
sPointInItemArea (
TLTreeItem* p,
TLColumnItem* pci,
int ix,
POINT mpt)
{
TLListItem* pli;
RECT rc;
int iSubItem;
pli = p->listItem;
iSubItem = 0;
while (pci && pli)
{
iSubItem++;
if (pli->state & TLIS_VISIBLE)
{
rc.left = ix;
rc.right = rc.left + pci->cx;
rc.top = p->selectRect.top;
rc.bottom = p->selectRect.bottom;
if (PtInRect (&rc, mpt))
return iSubItem;
}
ix += pci->cx;
pci = pci->nextItem;
pli = pli->nextItem;
}
return 0;
}
// _______________________________________________
//
// Search for object containing given point
static TLTreeItem*
sTextItemSearch (
TLTreeItem* pStart,
TLColumnItem* pci,
int ix,
POINT mpt,
int* iSubItem)
{
TLTreeItem* p;
TLTreeItem* pp;
p = pStart;
while (p)
{
if (PtInRect (&p->selectRect, mpt))
{
if (PtInRect (&p->hiliteRect, mpt))
{
*iSubItem = sPointInItemArea (p, pci, ix, mpt);
return p;
}
}
if (p->state & TLIS_EXPANDED)
{
pp = sTextItemSearch (p->childItem, pci, ix, mpt, iSubItem);
if (pp)
return pp;
}
if (p->buttonRect.right < p->buttonRect.left)
return NULL;
p = p->nextItem;
}
return NULL;
}
// _______________________________________________
//
// Determine if mouse is over active list element
static INT
sPointInActiveArea (
TLTreeItem* p,
TLColumnItem* pci,
int ix,
POINT mpt)
{
TLListItem* pli;
RECT rc;
int iSubItem;
pli = p->listItem;
iSubItem = 1;
while (pci && pli)
{
if (pci->bMouseNotify)
{
if (pli->state & TLIS_VISIBLE)
{
rc.left = ix + pci->cxImageOffset;
rc.right = rc.left + BITMAPWIDTH;
rc.top = p->selectRect.top;
rc.bottom = p->selectRect.bottom;
if (PtInRect (&rc, mpt))
return iSubItem;
}
}
iSubItem++;
ix += pci->cx;
pci = pci->nextItem;
pli = pli->nextItem;
}
return 0;
}
// _______________________________________________
//
// Search for object containing given point
static TLTreeItem*
sPointSearchEx (
TLWndData* pWD,
TLTreeItem* pStart,
TLColumnItem* pci,
int ix,
POINT mpt,
int* iType,
int* iSubItem)
{
TLTreeItem* p;
p = pStart;
while (p)
{
if (pWD->style & TLS_DRAGSELECTION)
{
RECT rcDragSelect;
rcDragSelect.left = 0;
rcDragSelect.right = DRAGSELECTINDENT - pWD->iHorizontalPos;
rcDragSelect.top = p->selectRect.top;
rcDragSelect.bottom = p->selectRect.bottom;
if (PtInRect (&rcDragSelect, mpt))
{
*iType = TLK_SELECT;
return p;
}
}
*iSubItem = sPointInActiveArea (p, pci, ix, mpt);
if (*iSubItem)
{
*iType = TLK_ACTIVE;
return p;
}
if (PtInRect (&p->buttonRect, mpt))
{
*iType = TLK_BUTTON;
return p;
}
if (PtInRect (&p->selectRect, mpt))
{
if (mpt.x < (p->selectRect.left + BITMAPWIDTH))
*iType = TLK_ACTIVE;
else
*iType = TLK_SELECT;
return p;
}
if (p->state & TLIS_EXPANDED)
{
TLTreeItem* pp;
pp = sPointSearchEx (pWD,
p->childItem, pci, ix, mpt, iType, iSubItem);
if (pp)
return pp;
}
if (p->buttonRect.right < p->buttonRect.left)
{
*iType = TLK_NONE;
return NULL;
}
p = p->nextItem;
}
*iType = TLK_NONE;
return NULL;
}
// _______________________________________________
//
// Search for object containing given point
static TLTreeItem*
sPointSearch (
TLTreeItem* pStart,
POINT mpt,
int* iType)
{
TLTreeItem* p;
TLTreeItem* pp;
p = pStart;
while (p)
{
if (PtInRect (&p->buttonRect, mpt))
{
*iType = TLK_BUTTON;
return p;
}
if (PtInRect (&p->selectRect, mpt))
{
if (mpt.x < (p->selectRect.left + BITMAPWIDTH))
*iType = TLK_ACTIVE;
else
*iType = TLK_SELECT;
return p;
}
if (p->state & TLIS_EXPANDED)
{
pp = sPointSearch (p->childItem, mpt, iType);
if (pp) return pp;
}
if (p->buttonRect.right < p->buttonRect.left)
{
*iType = TLK_NONE;
return NULL;
}
p = p->nextItem;
}
*iType = TLK_NONE;
return NULL;
}
// _______________________________________________
//
// Search for object containing given point for drag selection
static TLTreeItem*
sPointSearchDragSelect (
TLTreeItem* pStart,
POINT mpt,
int* iType)
{
TLTreeItem* p;
TLTreeItem* pp;
RECT rc;
rc.left = 0;
rc.right = 32000;
p = pStart;
while (p)
{
rc.top = p->selectRect.top;
rc.bottom = p->selectRect.bottom;
if (PtInRect (&rc, mpt))
{
*iType = TLK_SELECT;
return p;
}
if (p->state & TLIS_EXPANDED)
{
pp = sPointSearchDragSelect (p->childItem, mpt, iType);
if (pp)
return pp;
}
p = p->nextItem;
}
*iType = TLK_NONE;
return NULL;
}
// _______________________________________________
//
// Select range of lines
TLTreeItem*
TLSelectRange (
TLWndData* pWD,
TLTreeItem* pFirst,
TLTreeItem* pSel,
TLTreeItem* pLast)
{
TLTreeItem* p;
/// TLTreeItem* pFirstSelectParent;
BOOL bSel;
p = pFirst;
bSel = (pLast != NULL);
/// pFirstSelectParent = pWD->firstSelectItem->parentItem;
if (pSel == pWD->firstSelectItem)
{
pSel->state |= TLIS_SELECTED;
pWD->iNumberSelected = 1;
TLInvalidateItem (pWD, pSel);
return pSel;
}
while (p && !bSel)
{
if (p == pSel)
{
bSel = TRUE;
pLast = pWD->firstSelectItem;
}
else if (p == pWD->firstSelectItem)
{
bSel = TRUE;
pLast = pSel;
}
if (!bSel)
{
if ((p->childItem) && (p->state & TLIS_EXPANDED))
{
pLast = TLSelectRange (pWD, p->childItem, pSel, pLast);
if (pLast)
{
bSel = TRUE;
p = p->nextItem;
}
}
}
if (!bSel)
p = p->nextItem;
}
if (bSel)
{
while (p && bSel)
{
if (p == pLast)
bSel = FALSE;
/// if (p->parentItem == pFirstSelectParent)
{
p->state |= TLIS_SELECTED;
(pWD->iNumberSelected)++;
TLInvalidateItem (pWD, p);
}
if ((p->childItem) && (p->state & TLIS_EXPANDED))
{
pLast = TLSelectRange (pWD, p->childItem, pSel, pLast);
if (!pLast)
bSel = FALSE;
}
p = p->nextItem;
}
if (!bSel)
return NULL;
}
return pLast;
}
// _______________________________________________
//
// De-dragover Tree
BOOL
TLDeDragOverTree (
TLWndData* pWD,
TLTreeItem* p,
TLTreeItem* pExcept)
{
BOOL bDedragged = FALSE;
while (p)
{
if (p->childItem)
bDedragged = TLDeDragOverTree (pWD, p->childItem, pExcept);
if (p != pExcept)
{
if (p->state & (TLIS_DRAGGEDOVER|
TLIS_DRAGGEDBEFORE|
TLIS_DRAGGEDAFTER))
{
p->state &= ~(TLIS_DRAGGEDOVER|
TLIS_DRAGGEDBEFORE|
TLIS_DRAGGEDAFTER);
TLInvalidateItem (pWD, p);
bDedragged = TRUE;
}
}
p = p->nextItem;
}
return bDedragged;
}
// _______________________________________________
//
// cursor is moving during internal drag operation
static BOOL
sDragOverInternal (
TLWndData* pWD,
LPARAM lParam)
{
INT irow, iHitType;
TLTreeItem* pHit;
POINT mpt;
BOOL bRet;
BOOL bShift = FALSE;
mpt.x = LOWORD (lParam);
mpt.y = HIWORD (lParam);
pWD->nmTreeList.hdr.code = 0;
pWD->nmTreeList.itemNew.hItem = NULL;
pWD->nmTreeList.itemNew.state = 0;
pWD->nmTreeList.itemOld.hItem = NULL;
pHit = sPointSearch (pWD->rootItem, mpt, &iHitType);
switch (iHitType) {
case TLK_NONE :
TLDeDragOverTree (pWD, pWD->rootItem, NULL);
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -