📄 tlmouse.c
字号:
//:TLMouse.c - handle tree list mouse events
//
// $Id: TLMouse.c,v 1.35 1999/03/26 15:08:30 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
//----------------------------------------------------|
// Determine if mouse is over item element
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
INT PointInItemArea (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
TLTreeItem* TextItemSearch (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 = PointInItemArea (p, pci, ix, mpt);
return p;
}
}
if (p->state & TLIS_EXPANDED) {
pp = TextItemSearch (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
INT PointInActiveArea (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
TLTreeItem* PointSearchEx (TLTreeItem* pStart, TLColumnItem* pci,
int ix, POINT mpt, int* iType, int* iSubItem) {
TLTreeItem* p;
TLTreeItem* pp;
p = pStart;
while (p) {
*iSubItem = PointInActiveArea (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)) {
*iType = TLK_SELECT;
return p;
}
if (p->state & TLIS_EXPANDED) {
pp = PointSearchEx (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
TLTreeItem* PointSearch (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)) {
*iType = TLK_SELECT;
return p;
}
if (p->state & TLIS_EXPANDED) {
pp = PointSearch (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;
}
//----------------------------------------------------|
// Select range of lines
BOOL TLSelectRange (TLWndData* pWD, TLTreeItem* pFirst, TLTreeItem* pSel) {
TLTreeItem* p;
TLTreeItem* pLast;
BOOL bSel;
p = pFirst;
bSel = FALSE;
if (pSel == pWD->firstSelectItem) {
pSel->state |= TLIS_SELECTED;
pWD->iNumberSelected = 1;
TLInvalidateItem (pWD, pSel);
return TRUE;
}
while (p && !bSel) {
if ((p->childItem) && (p->state & TLIS_EXPANDED)) {
if (TLSelectRange (pWD, p->childItem, pSel)) return TRUE;
}
if (p == pSel) {
bSel = TRUE;
pLast = pWD->firstSelectItem;
p->state |= TLIS_SELECTED;
(pWD->iNumberSelected)++;
TLInvalidateItem (pWD, p);
}
else if (p == pWD->firstSelectItem) {
bSel = TRUE;
pLast = pSel;
p->state |= TLIS_SELECTED;
(pWD->iNumberSelected)++;
TLInvalidateItem (pWD, p);
}
p = p->nextItem;
}
if (bSel) {
while (p && bSel) {
if (p == pLast) {
bSel = FALSE;
}
p->state |= TLIS_SELECTED;
(pWD->iNumberSelected)++;
TLInvalidateItem (pWD, p);
p = p->nextItem;
}
return TRUE;
}
return FALSE;
}
//----------------------------------------------------|
// 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) {
p->state &= ~TLIS_DRAGGEDOVER;
TLInvalidateItem (pWD, p);
bDedragged = TRUE;
}
}
p = p->nextItem;
}
return bDedragged;
}
//----------------------------------------------------|
// cursor is moving during internal drag operation
BOOL DragOverInternal (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 = PointSearch (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);
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;
}
//----------------------------------------------------|
// Show tooltip text if text is truncated
void ShowTooltipText (TLWndData* pWD, TLTreeItem* pHit, int iHitSubItem) {
TLListItem* pli;
TLColumnItem* pci;
POINT pt;
int i;
LPSTR psz;
UINT state;
BOOL bActivate = FALSE;
if (pHit && pWD->bTreeFocused) {
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 (bActivate) {
TOOLINFO ti;
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = 0;
ti.hwnd = pWD->hWndParent;
ti.uId = (LPARAM)pWD->hWnd;
ti.lpszText = psz;
SendMessage (pWD->hWndToolTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);
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);
SetTimer (pWD->hWnd, TOOLTIPTIMERID, TOOLTIPTIME, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -