⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clv_listview.c

📁 VC++视频开发实例集锦(包括“远程视频监控”"语音识别系统"等13个经典例子)
💻 C
📖 第 1 页 / 共 5 页
字号:
        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 + -