📄 clv_listview.c
字号:
// Update only if the origin has changed
if(iNewFirstVisibleItem != pListData->m_iFirstVisibleItem)
{
pListData->m_iFirstVisibleItem = iNewFirstVisibleItem;
CLV_UpdateScrollBars(pListData);
CLV_InvalidateWindow(pListData);
}
}
}
else if(pListData->m_enWindowMode == wmVScrollbar_Scroll_Up)
{
// We will draw the button up if the mouse isn't over it
BOOL bNewButtonState;
if(PtInRect(&pListData->m_rScrollbar_Vert, ptCursor) == TRUE
&& ptCursor.y < (pListData->m_rScrollbar_Vert.top + glb_pSkin->mpl_pVScrollBar_Up->m_iStateHeight) )
{
bNewButtonState = TRUE;
}
else
bNewButtonState = FALSE;
// State changed?
if(bNewButtonState != pListData->m_bMouseOverScrollbutton)
{
pListData->m_bMouseOverScrollbutton = bNewButtonState;
InvalidateRect(pListData->m_hWnd, &pListData->m_rScrollbar_Vert, FALSE);
}
}
else if(pListData->m_enWindowMode == wmVScrollbar_Scroll_Down)
{
// We draw the button up if the mouse isn't over it
BOOL bNewButtonState;
if(PtInRect(&pListData->m_rScrollbar_Vert, ptCursor) == TRUE
&& ptCursor.y > (pListData->m_rScrollbar_Vert.bottom - glb_pSkin->mpl_pVScrollBar_Down->m_iStateHeight) )
{
bNewButtonState = TRUE;
}
else
bNewButtonState = FALSE;
// State changed?
if(bNewButtonState != pListData->m_bMouseOverScrollbutton)
{
pListData->m_bMouseOverScrollbutton = bNewButtonState;
InvalidateRect(pListData->m_hWnd, &pListData->m_rScrollbar_Vert, FALSE);
}
}
else if(pListData->m_enWindowMode == wmList_Click)
{
// If the mouse has moved beyond our drag threshold then enter into header_orderchange mode
if( pListData->m_iFocusItem != CPC_INVALIDITEM
&& ((abs(ptCursor.x - pListData->m_ptMouseDown.x) > CPC_LISTDRAGDISTANCE
|| abs(ptCursor.y - pListData->m_ptMouseDown.y) > CPC_LISTDRAGDISTANCE) )
&& (pListData->m_pItems[pListData->m_iFocusItem].m_dwFlags & CPLV_ITEMFLAG_SELECTED))
{
pListData->m_enWindowMode = wmList_Drag;
if(pListData->m_hndlr_ItemDrag && pListData->m_iFocusItem != CPC_INVALIDITEM)
pListData->m_hndlr_ItemDrag(pListData, pListData->m_iFocusItem, pListData->m_pItems[pListData->m_iFocusItem].m_pItemData);
}
}
else
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
//
//
//
void CLV_StartAutoRepeat(CIs_ListViewData* pListData)
{
DWORD dwRepeatDelay;
SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &dwRepeatDelay, 0L);
dwRepeatDelay = 250 + (dwRepeatDelay*250);
pListData->m_bAutoRepeatFirst = TRUE;
pListData->m_uiAutorepeatTimer = SetTimer(pListData->m_hWnd, CPC_TIMERID_AUTOREPEAT, dwRepeatDelay, NULL);
}
//
//
//
void CLV_Handle_WM_TIMER_AUTOREPEAT(CIs_ListViewData* pListData)
{
POINT ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(pListData->m_hWnd, &ptCursor);
// Are we autorepeating in the horizontal scrollbar?
if(PtInRect(&pListData->m_rScrollbar_Horiz, ptCursor) == TRUE)
{
// In left button
if(ptCursor.x < (pListData->m_rScrollbar_Horiz.left + glb_pSkin->mpl_pHScrollBar_Left->m_pImage->m_szSize.cx)
&& pListData->m_enWindowMode == wmHScrollbar_Scroll_Left)
{
CLV_Scroll_Horiz(pListData, -CPC_SCROLLBAR_HORIZ_LINESIZE);
}
// In right button
else if(ptCursor.x > (pListData->m_rScrollbar_Horiz.right - glb_pSkin->mpl_pHScrollBar_Right->m_pImage->m_szSize.cx)
&& pListData->m_enWindowMode == wmHScrollbar_Scroll_Right)
{
CLV_Scroll_Horiz(pListData, CPC_SCROLLBAR_HORIZ_LINESIZE);
}
// In left page area
else if(ptCursor.x < pListData->m_rScrollbar_Horiz_Thumb.left
&& pListData->m_enWindowMode == wmHScrollbar_Page_Left)
{
CLV_Scroll_Horiz(pListData, -CPC_SCROLLBAR_HORIZ_PAGESIZE);
}
// In right page area
else if(ptCursor.x > pListData->m_rScrollbar_Horiz_Thumb.right
&& pListData->m_enWindowMode == wmHScrollbar_Page_Right)
{
CLV_Scroll_Horiz(pListData, CPC_SCROLLBAR_HORIZ_PAGESIZE);
}
}
// Are we autorepeating in the vertical scrollbar?
else if(PtInRect(&pListData->m_rScrollbar_Vert, ptCursor) == TRUE)
{
if(ptCursor.y < (pListData->m_rScrollbar_Vert.top + glb_pSkin->mpl_pVScrollBar_Up->m_iStateHeight)
&& pListData->m_enWindowMode == wmVScrollbar_Scroll_Up)
{
CLV_Scroll_Vert(pListData, -1);
}
// In down button
else if(ptCursor.y > (pListData->m_rScrollbar_Vert.bottom - glb_pSkin->mpl_pVScrollBar_Down->m_iStateHeight)
&& pListData->m_enWindowMode == wmVScrollbar_Scroll_Down)
{
CLV_Scroll_Vert(pListData, 1);
}
// In top page area
else if(ptCursor.y < pListData->m_rScrollbar_Vert_Thumb.top
&& pListData->m_enWindowMode == wmVScrollbar_Page_Up)
{
CLV_Scroll_Vert(pListData, -pListData->m_iNumItemsOnPage);
}
// In bottom page area
else if(ptCursor.y > pListData->m_rScrollbar_Vert_Thumb.bottom
&& pListData->m_enWindowMode == wmVScrollbar_Page_Down)
{
CLV_Scroll_Vert(pListData, pListData->m_iNumItemsOnPage);
}
}
// Do we need to update the timer (after the first autorepeat delay)
if(pListData->m_bAutoRepeatFirst)
{
int iRepeatDelay;
// Make the autorepeat the same as the keyboard autorepeat
pListData->m_bAutoRepeatFirst = FALSE;
SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &iRepeatDelay, 0L);
iRepeatDelay = 400 - (iRepeatDelay*12);
if(iRepeatDelay < 0)
iRepeatDelay = 10;
pListData->m_uiAutorepeatTimer = SetTimer(pListData->m_hWnd, CPC_TIMERID_AUTOREPEAT, iRepeatDelay, NULL);
}
}
//
//
//
void CLV_InvalidateItem(CP_HLISTVIEW _hListData, const int iItemIDX)
{
CIs_ListViewData* pListData;
RECT rItemRect;
pListData = (CIs_ListViewData*)_hListData;
CP_CHECKOBJECT(pListData);
if(iItemIDX == CPC_INVALIDITEM)
return;
CP_ASSERT(iItemIDX >= 0);
CP_ASSERT(iItemIDX < pListData->m_iNumItems);
rItemRect.left = pListData->m_rList.left;
rItemRect.right = pListData->m_rList.right;
rItemRect.top = pListData->m_rList.top + ( (iItemIDX - pListData->m_iFirstVisibleItem) * pListData->m_iItemHeight);
rItemRect.bottom = rItemRect.top + pListData->m_iItemHeight;
// Handle the possiblity that the previous/next item may be selected
rItemRect.top -= glb_pSkin->mpl_pSelection->m_szSize.cy - glb_pSkin->mpl_rSelection_Tile.bottom;
rItemRect.bottom += glb_pSkin->mpl_rSelection_Tile.top;
InvalidateRect(pListData->m_hWnd, &rItemRect, FALSE);
}
//
//
//
void CLV_ItemSelChange(CIs_ListViewData* pListData, int iItemIDX)
{
if(iItemIDX == CPC_INVALIDITEM)
return;
CP_ASSERT(iItemIDX >= 0);
CP_ASSERT(iItemIDX < pListData->m_iNumItems);
if(pListData->m_hndlr_ItemSelected
&& pListData->m_pItems[iItemIDX].m_dwFlags & CPLV_ITEMFLAG_SELECTED)
{
pListData->m_hndlr_ItemSelected(pListData, iItemIDX, pListData->m_pItems[iItemIDX].m_pItemData);
}
}
//
//
//
void CLV_ActionFocusedItem(CIs_ListViewData* pListData)
{
if(pListData->m_iFocusItem == CPC_INVALIDITEM)
return;
CP_ASSERT(pListData->m_iFocusItem >= 0);
CP_ASSERT(pListData->m_iFocusItem < pListData->m_iNumItems);
CLV_ClearSelection(pListData);
pListData->m_pItems[pListData->m_iFocusItem].m_dwFlags |= CPLV_ITEMFLAG_SELECTED;
CLV_ItemSelChange(pListData, pListData->m_iFocusItem);
CLV_InvalidateItem(pListData, pListData->m_iFocusItem);
pListData->m_iFocusItem = pListData->m_iFocusItem;
pListData->m_iKeyboardAnchor = pListData->m_iFocusItem;
if(pListData->m_hndlr_ItemAction)
pListData->m_hndlr_ItemAction(pListData, pListData->m_iFocusItem, pListData->m_pItems[pListData->m_iFocusItem].m_pItemData);
}
//
//
//
void CLV_SelectRange(CIs_ListViewData* pListData, const int _iFirst, const int _iLast)
{
int iStartRange;
int iEndRange;
int iItemIDX;
if(_iFirst > _iLast)
{
iStartRange = _iLast;
iEndRange = _iFirst;
}
else
{
iStartRange = _iFirst;
iEndRange = _iLast;
}
CP_ASSERT(iStartRange >= 0);
CP_ASSERT(iStartRange < pListData->m_iNumItems);
CP_ASSERT(iEndRange >= 0);
CP_ASSERT(iEndRange < pListData->m_iNumItems);
for(iItemIDX = iStartRange; iItemIDX <= iEndRange; iItemIDX++)
{
pListData->m_pItems[iItemIDX].m_dwFlags |= CPLV_ITEMFLAG_SELECTED;
CLV_ItemSelChange(pListData, iItemIDX);
CLV_InvalidateItem(pListData, iItemIDX);
}
}
//
//
//
void CLV_Handle_WM_LBUTTONDOWN(CIs_ListViewData* pListData, const POINTS _ptCursor, const DWORD dwKeys)
{
POINT ptCursor;
// Init
ptCursor.x = _ptCursor.x;
ptCursor.y = _ptCursor.y;
pListData->m_ptMouseDown = ptCursor;
pListData->m_dwMouseDown_Keys = dwKeys;
// Hit test cursor
// - in header?
if(PtInRect(&pListData->m_rHeader, ptCursor) == TRUE)
{
pListData->m_iActiveHeaderCol = CLV_HitTest_HeaderSizer_X(pListData, ptCursor.x);
if(pListData->m_iActiveHeaderCol != CPC_INVALIDCOLUMN)
{
// Resizing header
SetCapture(pListData->m_hWnd);
pListData->m_enWindowMode = wmHeader_ChangeWidth;
}
else
{
pListData->m_iActiveHeaderCol = CLV_HitTest_Header_X(pListData, ptCursor.x);
if(pListData->m_iActiveHeaderCol != CPC_INVALIDCOLUMN)
{
// Resizing header
SetCapture(pListData->m_hWnd);
pListData->m_enWindowMode = wmHeader_Click;
InvalidateRect(pListData->m_hWnd, &pListData->m_rHeader, FALSE);
}
}
}
// - In HScrollbar?
else if(PtInRect(&pListData->m_rScrollbar_Horiz, ptCursor) == TRUE)
{
// In Thumb?
if(PtInRect(&pListData->m_rScrollbar_Horiz_Thumb, ptCursor) == TRUE)
{
// Dragging thumb
SetCapture(pListData->m_hWnd);
pListData->m_enWindowMode = wmHScrollbar_DragThumb;
pListData->m_ptMouseDown_OnHitItem.x = ptCursor.x - pListData->m_rScrollbar_Horiz_Thumb.left;
pListData->m_ptMouseDown_OnHitItem.y = ptCursor.y - pListData->m_rScrollbar_Horiz_Thumb.top;
InvalidateRect(pListData->m_hWnd, &pListData->m_rScrollbar_Horiz_Thumb, FALSE);
}
// In left button
else if(ptCursor.x < (pListData->m_rScrollbar_Horiz.left + glb_pSkin->mpl_pHScrollBar_Left->m_pImage->m_szSize.cx) )
{
SetCapture(pListData->m_hWnd);
pListData->m_enWindowMode = wmHScrollbar_Scroll_Left;
CLV_Scroll_Horiz(pListData, -CPC_SCROLLBAR_HORIZ_LINESIZE);
InvalidateRect(pListData->m_hWnd, &pListData->m_rScrollbar_Horiz, FALSE);
pListData->m_bMouseOverScrollbutton = TRUE;
CLV_StartAutoRepeat(pListData);
}
// In right button
else if(ptCursor.x > (pListData->m_rScrollbar_Horiz.right - glb_pSkin->mpl_pHScrollBar_Right->m_pImage->m_szSize.cx) )
{
SetCapture(pListData->m_hWnd);
pListData->m_enWindowMode = wmHScrollbar_Scroll_Right;
CLV_Scroll_Horiz(pListData, CPC_SCROLLBAR_HORIZ_LINESIZE);
InvalidateRect(pListData->m_hWnd, &pListData->m_rScrollbar_Horiz, FALSE);
pListData->m_bMouseOverScrollbutton = TRUE;
CLV_StartAutoRepeat(pListData);
}
// In left page area
else if(ptCursor.x < pListData->m_rScrollbar_Horiz_Thumb.left)
{
SetCapture(pListData->m_hWnd);
pListData->m_enWindowMode = wmHScrollbar_Page_Left;
CLV_Scroll_Horiz(pListData, -CPC_SCROLLBAR_HORIZ_PAGESIZE);
InvalidateRect(pListData->m_hWnd, &pListData->m_rScrollbar_Horiz, FALSE);
CLV_StartAutoRepeat(pListData);
}
// In right page area
else if(ptCursor.x > pListData->m_rScrollbar_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -