📄 clv_listview.c
字号:
unsigned int iColumnIDX = pListData->m_piColumnOrder[_iColIDX];
if(pListData->m_pColumns[iColumnIDX].m_dwFlags & CPLV_COLFLAG_HIDDEN)
continue;
iLastCursorX = iCursorX;
iCursorX += pListData->m_pColumns[iColumnIDX].m_iColumnWidth;
if(iCursorX > (pListData->m_rHeader.right - CPC_HEADERCOLLAPSETHRESHOLD))
iCursorX = pListData->m_rHeader.right;
if(iTestX >= iLastCursorX && iTestX < iCursorX)
return iColumnIDX;
}
return CPC_INVALIDCOLUMN;
}
//
//
//
int CLV_HitTest_HeaderSizer_X(CIs_ListViewData* pListData, const int iTestX)
{
// We are in the header - are we near a drag boundry?
int iCursorX;
unsigned int _iColIDX;
iCursorX = -pListData->m_iXOrigin;
for(_iColIDX = 0; _iColIDX < pListData->m_iNumColumns; _iColIDX++)
{
unsigned int iColumnIDX = pListData->m_piColumnOrder[_iColIDX];
int iColSizer;
if(pListData->m_pColumns[iColumnIDX].m_dwFlags & CPLV_COLFLAG_HIDDEN)
continue;
iColSizer = iCursorX + pListData->m_pColumns[iColumnIDX].m_iColumnWidth;
if(iColSizer > (pListData->m_rHeader.right - CPC_HEADERCOLLAPSETHRESHOLD))
iColSizer = pListData->m_rHeader.right - CPC_HEADERCOLLAPSETHRESHOLD;
if(iTestX >= (iColSizer-CPC_HEADERDRAG_HTWIDTH) && iTestX <= (iColSizer+CPC_HEADERDRAG_HTWIDTH))
{
// If we cannot resize - return an invalid column
if(pListData->m_pColumns[iColumnIDX].m_dwFlags & CPLV_COLFLAG_LOCKRESIZE)
return CPC_INVALIDCOLUMN;
return iColumnIDX;
}
iCursorX = iColSizer;
}
return CPC_INVALIDCOLUMN;
}
//
//
//
void CLV_Handle_WM_MOUSEMOVE(CIs_ListViewData* pListData, const POINTS _ptCursor)
{
POINT ptCursor;
// Init
ptCursor.x = _ptCursor.x;
ptCursor.y = _ptCursor.y;
if(pListData->m_enWindowMode == wmQuiescent)
{
// Set cursor according to where it is
if(PtInRect(&pListData->m_rHeader, ptCursor) == TRUE)
{
if(CLV_HitTest_HeaderSizer_X(pListData, ptCursor.x) == CPC_INVALIDCOLUMN)
SetCursor(LoadCursor(NULL, IDC_ARROW)); // In a header
else
SetCursor(LoadCursor(NULL, IDC_SIZEWE)); // Sizing
}
else
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
else if(pListData->m_enWindowMode == wmHeader_Click)
{
// If the mouse has moved beyond our drag threshold then enter into header_orderchange mode
if(abs(ptCursor.x - pListData->m_ptMouseDown.x) > CPC_HEADERDRAGDISTANCE
|| abs(ptCursor.y - pListData->m_ptMouseDown.y) > CPC_HEADERDRAGDISTANCE)
{
pListData->m_enWindowMode = wmHeader_ChangeOrder;
InvalidateRect(pListData->m_hWnd, &pListData->m_rHeader, FALSE);
}
}
else if(pListData->m_enWindowMode == wmHeader_ChangeWidth)
{
// Update the new column width
// - get the start of this colunm
unsigned int _iColIDX;
int iCursorX;
RECT rInvalid;
DWORD dwNewFlags;
int iNewWidth;
// Find the start point of the active column
iCursorX = -pListData->m_iXOrigin;
for(_iColIDX = 0; _iColIDX < pListData->m_iNumColumns; _iColIDX++)
{
unsigned int iColumnIDX = pListData->m_piColumnOrder[_iColIDX];
if((int)iColumnIDX == pListData->m_iActiveHeaderCol)
break;
if(pListData->m_pColumns[iColumnIDX].m_dwFlags & CPLV_COLFLAG_HIDDEN)
continue;
iCursorX += pListData->m_pColumns[iColumnIDX].m_iColumnWidth;
}
// Invalidate only the area that needs it
rInvalid.top = 0;
rInvalid.bottom = pListData->m_rClient.bottom;
rInvalid.right = pListData->m_rClient.right;
rInvalid.left = iCursorX;
// Perform resize
dwNewFlags = pListData->m_pColumns[pListData->m_iActiveHeaderCol].m_dwFlags;
iNewWidth = pListData->m_pColumns[pListData->m_iActiveHeaderCol].m_iColumnWidth;
if(ptCursor.x > (iCursorX + CPC_HEADERDRAG_HTWIDTH) )
{
dwNewFlags &= (~CPLV_COLFLAG_HIDDEN);
iNewWidth = ptCursor.x - iCursorX;
}
else
{
if(dwNewFlags & CPLV_COLFLAG_NOHIDE)
{
iNewWidth = CPC_HEADERDRAG_HTWIDTH;
}
else
{
dwNewFlags |= CPLV_COLFLAG_HIDDEN;
iNewWidth = CPC_HEADERDRAG_DEFAULTWIDTH;
}
}
// Update dispaly only if the width (or visible state) has changed
if(iNewWidth != pListData->m_pColumns[pListData->m_iActiveHeaderCol].m_iColumnWidth
|| dwNewFlags != pListData->m_pColumns[pListData->m_iActiveHeaderCol].m_dwFlags)
{
pListData->m_pColumns[pListData->m_iActiveHeaderCol].m_dwFlags = dwNewFlags;
pListData->m_pColumns[pListData->m_iActiveHeaderCol].m_iColumnWidth = iNewWidth;
InvalidateRect(pListData->m_hWnd, &rInvalid, FALSE);
CLV_UpdateScrollBars(pListData);
}
}
else if(pListData->m_enWindowMode == wmHeader_ChangeOrder)
{
// Search for our drag rect - keep track of the threshold of the prev and next colunms
unsigned int _iColIDX;
int iXColStart_Prev = 0;
int iXColEnd_Prev = 0;
int iXColStart_Next = 0;
int iXColEnd_Next = 0;
int iPrevColIDX = CPC_INVALIDCOLUMN;
int iNextColIDX = CPC_INVALIDCOLUMN;
unsigned int iCurrentOrderIDX;
int iActiveColumnWidth;
int iCursorX;
BOOL bFoundColumn;
// Find prev and next colunms
bFoundColumn = FALSE;
iCursorX = -pListData->m_iXOrigin;
iCurrentOrderIDX = 0;
iActiveColumnWidth = 0;
for(_iColIDX = 0; _iColIDX < pListData->m_iNumColumns; _iColIDX++)
{
int iColumnIDX = pListData->m_piColumnOrder[_iColIDX];
if(pListData->m_pColumns[iColumnIDX].m_dwFlags & CPLV_COLFLAG_HIDDEN)
continue;
// Update prev and next
if(bFoundColumn == TRUE && iNextColIDX == CPC_INVALIDCOLUMN)
{
iXColStart_Next = iCursorX;
iXColEnd_Next = iCursorX + pListData->m_pColumns[iColumnIDX].m_iColumnWidth;
iNextColIDX = iColumnIDX;
}
if(iColumnIDX == pListData->m_iActiveHeaderCol)
{
iCurrentOrderIDX = _iColIDX;
iActiveColumnWidth = pListData->m_pColumns[iColumnIDX].m_iColumnWidth;
bFoundColumn = TRUE;
}
else if(bFoundColumn == FALSE)
{
iPrevColIDX = iColumnIDX;
iXColStart_Prev = iCursorX;
iXColEnd_Prev = iCursorX + pListData->m_pColumns[iColumnIDX].m_iColumnWidth;
}
iCursorX += pListData->m_pColumns[iColumnIDX].m_iColumnWidth;
}
// If we have dragged our mouse beyond the prev threshold - swap the order of that with the current col
// - Only swap if the mouse will remain on top of the active column
if(iPrevColIDX != CPC_INVALIDCOLUMN
&& ptCursor.x < iXColEnd_Prev
&& ptCursor.x < (iXColStart_Prev+iActiveColumnWidth))
{
int iTemp;
RECT rInvalid;
iTemp = pListData->m_piColumnOrder[iCurrentOrderIDX];
pListData->m_piColumnOrder[iCurrentOrderIDX] = pListData->m_piColumnOrder[iCurrentOrderIDX-1];
pListData->m_piColumnOrder[iCurrentOrderIDX-1] = iTemp;
// Invalidate only the area that needs it
rInvalid.top = 0;
rInvalid.bottom = pListData->m_rClient.bottom;
rInvalid.left = iXColStart_Prev;
rInvalid.right = iXColEnd_Prev + iActiveColumnWidth;
InvalidateRect(pListData->m_hWnd, &rInvalid, FALSE);
// Send notify
if(pListData->m_hndlr_HeaderChanged)
pListData->m_hndlr_HeaderChanged(pListData);
}
// If we have dragged our mouse beyond the next threshold - swap the order of that with the current col
// - Only swap if the mouse will remain on top of the active column
else if(iNextColIDX != CPC_INVALIDCOLUMN
&& ptCursor.x > iXColStart_Next
&& ptCursor.x > (iXColEnd_Next-iActiveColumnWidth))
{
int iTemp;
RECT rInvalid;
iTemp = pListData->m_piColumnOrder[iCurrentOrderIDX];
pListData->m_piColumnOrder[iCurrentOrderIDX] = pListData->m_piColumnOrder[iCurrentOrderIDX+1];
pListData->m_piColumnOrder[iCurrentOrderIDX+1] = iTemp;
// Invalidate only the area that needs it
rInvalid.top = 0;
rInvalid.bottom = pListData->m_rClient.bottom;
rInvalid.left = iXColStart_Next - iActiveColumnWidth;
rInvalid.right = iXColEnd_Next;
InvalidateRect(pListData->m_hWnd, &rInvalid, FALSE);
// Send notify
if(pListData->m_hndlr_HeaderChanged)
pListData->m_hndlr_HeaderChanged(pListData);
}
}
else if(pListData->m_enWindowMode == wmHScrollbar_DragThumb)
{
if(pListData->m_ptMouseDown.x != ptCursor.x)
{
const int iTrackWidth = (pListData->m_rScrollbar_Horiz.right - pListData->m_rScrollbar_Horiz.left)
- (glb_pSkin->mpl_pHScrollBar_Left->m_pImage->m_szSize.cx
+ glb_pSkin->mpl_pHScrollBar_Right->m_pImage->m_szSize.cx);
const int iTrackThumbWidth = pListData->m_rScrollbar_Horiz_Thumb.right - pListData->m_rScrollbar_Horiz_Thumb.left;
const int iListRectWidth = pListData->m_rList.right - pListData->m_rList.left;
int iNewTrackPos;
int iNewXOrigin;
// Work out new origin based on the track drag distance
iNewTrackPos = ptCursor.x - pListData->m_ptMouseDown_OnHitItem.x - glb_pSkin->mpl_pHScrollBar_Left->m_pImage->m_szSize.cx;
iNewXOrigin = (int)( ( ((float)iNewTrackPos * (float)(pListData->m_iXScrollExtent - iListRectWidth)) / (float)(iTrackWidth-iTrackThumbWidth)));
if(iNewXOrigin < 0)
iNewXOrigin = 0;
else if(iNewXOrigin > (pListData->m_iXScrollExtent-iListRectWidth))
iNewXOrigin = pListData->m_iXScrollExtent-iListRectWidth;
// Update only if the origin has changed
if(iNewXOrigin != pListData->m_iXOrigin)
{
pListData->m_iXOrigin = iNewXOrigin;
CLV_UpdateScrollBars(pListData);
CLV_InvalidateWindow(pListData);
}
}
}
else if(pListData->m_enWindowMode == wmHScrollbar_Scroll_Left)
{
// We will draw the button up if the mouse isn't over it
BOOL bNewButtonState;
if(PtInRect(&pListData->m_rScrollbar_Horiz, ptCursor) == TRUE
&& ptCursor.x < (pListData->m_rScrollbar_Horiz.left + glb_pSkin->mpl_pHScrollBar_Left->m_pImage->m_szSize.cx) )
{
bNewButtonState = TRUE;
}
else
bNewButtonState = FALSE;
// State changed?
if(bNewButtonState != pListData->m_bMouseOverScrollbutton)
{
pListData->m_bMouseOverScrollbutton = bNewButtonState;
InvalidateRect(pListData->m_hWnd, &pListData->m_rScrollbar_Horiz, FALSE);
}
}
else if(pListData->m_enWindowMode == wmHScrollbar_Scroll_Right)
{
// We draw the button up if the mouse isn't over it
BOOL bNewButtonState;
if(PtInRect(&pListData->m_rScrollbar_Horiz, ptCursor) == TRUE
&& ptCursor.x > (pListData->m_rScrollbar_Horiz.right - glb_pSkin->mpl_pHScrollBar_Right->m_pImage->m_szSize.cx) )
{
bNewButtonState = TRUE;
}
else
bNewButtonState = FALSE;
// State changed?
if(bNewButtonState != pListData->m_bMouseOverScrollbutton)
{
pListData->m_bMouseOverScrollbutton = bNewButtonState;
InvalidateRect(pListData->m_hWnd, &pListData->m_rScrollbar_Horiz, FALSE);
}
}
else if(pListData->m_enWindowMode == wmVScrollbar_DragThumb)
{
if(pListData->m_ptMouseDown.y != ptCursor.y)
{
const int iListRectHeight = pListData->m_rList.bottom - pListData->m_rList.top;
const int iTrackHeight = iListRectHeight - (glb_pSkin->mpl_pVScrollBar_Up->m_iStateHeight
+ glb_pSkin->mpl_pVScrollBar_Down->m_iStateHeight);
const int iTrackThumbHeight = pListData->m_rScrollbar_Vert_Thumb.bottom - pListData->m_rScrollbar_Vert_Thumb.top;
const int iListRectHeight_Lines = CLV_GetListRect_Lines(pListData);
int iNewTrackPos;
int iNewFirstVisibleItem;
// Work out new origin based on the track drag distance
iNewTrackPos = ptCursor.y - pListData->m_ptMouseDown_OnHitItem.y - (pListData->m_rScrollbar_Vert.top+glb_pSkin->mpl_pVScrollBar_Up->m_iStateHeight);
iNewFirstVisibleItem = (int)( ( ((float)iNewTrackPos * (float)(pListData->m_iNumItems - iListRectHeight_Lines)) / (float)(iTrackHeight-iTrackThumbHeight)) );
if(iNewFirstVisibleItem < 0)
iNewFirstVisibleItem = 0;
if( (iNewFirstVisibleItem + iListRectHeight_Lines) > pListData->m_iNumItems)
iNewFirstVisibleItem = pListData->m_iNumItems - iListRectHeight_Lines;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -