Click here to Skip to main content
15,868,016 members
Articles / Desktop Programming / MFC
Article

Synchronization of scrolling between two list controls

Rate me:
Please Sign up or sign in to vote.
4.88/5 (12 votes)
11 Jun 20022 min read 108.7K   1.2K   29   9
This simple example shows the synchronization of scrolling of two list controls

Sample Image - SynchScroll.gif

Introduction

Developing one of my projects I became interested in the idea of synchronizing of scrolling of two list controls - both lists have always had information that coincides in the first column and differs in others. That is why parallel browsing of lists would be very comfortable.

The Solution

My solution is the following.

  1. Override the class CListCtrl and add three new functions in new class CListCtrlEx.
    void CListCtrlEx::RedirectHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
    {
        // Only for WinNT/2000/XP - the beginning of the code
        if (nSBCode/256==SB_THUMBTRACK || (nSBCode & 0xFF)==SB_THUMBTRACK)
        {
            int iX = ((int)nPos - (int)GetScrollPos(SB_HORZ));
            Scroll(CSize(iX, 0));
        }
        // Only for WinNT/2000/XP - the end of the code
        CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
    }
    
    void CListCtrlEx::RedirectVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
    {
        // Only for WinNT/2000/XP - the beginning of the code
        if (nSBCode/256==SB_THUMBTRACK || (nSBCode & 0xFF)==SB_THUMBTRACK)
        {
            int iY = ((int)nPos - (int)GetScrollPos(SB_VERT)) * m_nItemHeight;
            Scroll(CSize(0, iY));
        }
        // Only for WinNT/2000/XP - the end of the code
        CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
    }
    
    void CListCtrlEx::RedirectKeyScroll(UINT nChar)
    {
        switch (nChar)
        {
            case VK_UP:
                OnVScroll(SB_LINEUP, 0, NULL);
                break;
            case VK_DOWN:
                OnVScroll(SB_LINEDOWN, 0, NULL);
                break;
            case VK_LEFT:
                OnHScroll(SB_LINELEFT, 0, NULL);
                break;
            case VK_RIGHT:
                OnHScroll(SB_LINERIGHT, 0, NULL);
                break;
            case VK_HOME:
                OnHScroll(SB_LEFT, 0, NULL);
                break;
            case VK_END:
                OnHScroll(SB_RIGHT,0,NULL);
                break;
            case VK_PRIOR:
                OnVScroll(SB_PAGEUP, 0, NULL);
                break;
            case VK_NEXT:
                OnVScroll(SB_PAGEDOWN, 0, NULL);
                break;
        }
    }
    These functions will initiate operation of OnHScroll/OnVScroll handler in another list control.

  2. Add to the class CListCtrlEx three variables.
    CSynchScrollView* m_pViewPos;        // pointer to View aplications
    This variable will be used for functions call from View application.
    int m_nNumCtrl;                // number of class copy - number of list control
    By means of this variable we will be able to define what list control has got the message WM_HSCROLL/WM_VSCROLL/WM_KEYDOWN.
    int m_nItemHeight;                // height of an item
    To define an item height we use the following function:
    int CListCtrlEx::GetItemHeight()
    {
        CRect ItemRect;
        GetSubItemRect(1, 1, LVIR_BOUNDS, ItemRect);
        return ItemRect.bottom - ItemRect.top;
    }
  3. Override in the class CListCtrlEx OnHScroll/OnVScroll/OnKeyDown handlers.
    void CListCtrlEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
    {
        if (m_pViewPos->m_boolCheckSynchro)
        {
            CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
            m_pViewPos->HorzSynchro(m_nNumCtrl, nSBCode, nPos, pScrollBar);
        }
        else
            CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
    }
    
    void CListCtrlEx::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
    {
        if (nSBCode/256==SB_THUMBTRACK || (nSBCode & 0xFF)==SB_THUMBTRACK ||
            nSBCode/256==SB_THUMBPOSITION || (nSBCode & 0xFF)==SB_THUMBPOSITION)
        {
            SCROLLINFO sinfo;
            sinfo.cbSize=sizeof(sinfo);
            sinfo.fMask=SIF_TRACKPOS;
            ::GetScrollInfo(m_hWnd, SB_VERT, &sinfo);
            nPos=sinfo.nTrackPos;
        }
    
        if (m_pViewPos->m_boolCheckSynchro)
        {
            CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
            m_pViewPos->VertSynchro(m_nNumCtrl, nSBCode, nPos, pScrollBar);
        }
        else
            CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
    }
    
    void CListCtrlEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
    {
        if (m_pViewPos->m_boolCheckSynchro)
            m_pViewPos->KeySynchro(m_nNumCtrl, nChar);
        else
            CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
    }

    Everything is simple for OnHScroll/OnVScroll functions: if synchronization is on, than we call synchronizer-function from View application after a standard processing. For OnKeyDown function, if synchronization is on, standard WM_KEYDOWN handler is not used at all - for both list controls OnHScroll/OnVScroll functions are performed.

  4. In View application we define three functions, which will initiate synchronization of scrolling of list controls.

    Function for horizontal synchronization.

    void CSynchScrollView::HorzSynchro(int NumCtrl, int SBCode, int Pos, CScrollBar* pSB)
    {
        switch (NumCtrl)
        {
        case 1:
            if (SBCode == SB_THUMBTRACK)
            {
                m_ctrlSecondList.RedirectHScroll(SB_THUMBTRACK, Pos, NULL);
                m_ctrlSecondList.RedirectHScroll(SB_THUMBPOSITION, Pos, NULL);
                m_ctrlSecondList.RedirectHScroll(SB_ENDSCROLL, 0, NULL);
            }
            else
                m_ctrlSecondList.RedirectHScroll(SBCode, Pos, pSB);
            break;
        case 2:
            if (SBCode == SB_THUMBTRACK)
            {
                m_ctrlFirstList.RedirectHScroll(SB_THUMBTRACK, Pos, NULL);
                m_ctrlFirstList.RedirectHScroll(SB_THUMBPOSITION, Pos, NULL);
                m_ctrlFirstList.RedirectHScroll(SB_ENDSCROLL, 0, NULL);
            }
            else
                m_ctrlFirstList.RedirectHScroll(SBCode, Pos, pSB);
            break;
        }
    }

    Function for vertical synchronization.

    void CSynchScrollView::VertSynchro(int NumCtrl, int SBCode, int Pos, CScrollBar* pSB)
    {
        switch (NumCtrl)
        {
        case 1:
            if (SBCode == SB_THUMBTRACK)
            {
                m_ctrlSecondList.RedirectVScroll(SB_THUMBTRACK, Pos, NULL);
                m_ctrlSecondList.RedirectVScroll(SB_THUMBPOSITION, Pos, NULL);
                m_ctrlSecondList.RedirectVScroll(SB_ENDSCROLL, 0, NULL);
            }
            else
                m_ctrlSecondList.RedirectVScroll(SBCode, Pos, pSB);
            break;
        case 2:
            if (SBCode == SB_THUMBTRACK)
            {
                m_ctrlFirstList.RedirectVScroll(SB_THUMBTRACK, Pos, NULL);
                m_ctrlFirstList.RedirectVScroll(SB_THUMBPOSITION, Pos, NULL);
                m_ctrlFirstList.RedirectVScroll(SB_ENDSCROLL, 0, NULL);
            }
            else
                m_ctrlFirstList.RedirectVScroll(SBCode, Pos, pSB);
            break;
        }
    }

    Function for keyboard synchronization.

    void CSynchScrollView::KeySynchro(int NumCtrl, UINT nChar)
    {
        switch (NumCtrl)
        {
        case 1:
            m_ctrlSecondList.RedirectKeyScroll(nChar);
            break;
        case 2:
            m_ctrlFirstList.RedirectKeyScroll(nChar);
            break;
        }
    }

    In these functions the number of list control that received WM_HSCROLL/WM_VSCROLL/WM_KEYDOWN message is defined, then operation of OnHScroll/OnVScroll handler in another list control will be initiated.

Important note - SB_THUMBTRACK processing

When the scroll box is dragged and the mouse button is pressed and not released, a  SB_THUMBTRACK message is generated with each change of a scroll box position. When the mouse button is released, first the SB_THUMBPOSITION message will be generated and then - SB_ENDSCROLL message. Therefore, at each generation of the SB_THUMBTRACK message sequential processing of the SB_THUMBTRACK - SB_THUMBPOSITION - SB_ENDSCROLL messages in appropriate handlers of opposite list controls should be initiated.

Such design correctly works under Win95/98/Me, but does not work under WinNT/2000 and, probably, XP - I have no opportunity to check it up. I don't know how to explain it. May be the reason lies in some peculiarities of realization of some Win32 API functions for different versions of Windows.

The solution of this problem was offered by Jonathan Liu and I am truly grateful to him. While  SB_THUMBTRACK in the RedirectHScroll/RedirectVScroll functions Scroll (CSize (X, Y)) is called for direct scrolling of contents of the list controls. I repeat one more time: there is no need in it if Win95/98/Me is used.

Look for details of realization on enclosed demo project. I believe that this solution will be useful for somebody.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
PraiseRemember to initialize the pointer Pin
lumoru0124-Oct-16 4:43
professionallumoru0124-Oct-16 4:43 
QuestionLicense Terms of "Synchronization of scrolling between two list controls" Pin
Member 466767322-Dec-13 3:37
Member 466767322-Dec-13 3:37 
AnswerRe: License Terms of "Synchronization of scrolling between two list controls" Pin
Alexander Khudyakov24-Dec-13 4:16
Alexander Khudyakov24-Dec-13 4:16 
QuestionScrolling only a part of the dialog ? Pin
mohanrajh13-Jul-02 18:52
mohanrajh13-Jul-02 18:52 
GeneralSimplier code ? :) Pin
8-Mar-02 11:29
suss8-Mar-02 11:29 
GeneralRe: Simplier code ? :) [modified] Pin
Ross Peralta25-Mar-08 7:41
Ross Peralta25-Mar-08 7:41 
GeneralNice but... Pin
3-Jan-02 17:39
suss3-Jan-02 17:39 
GeneralRe: Nice but... Pin
xpbrains14-Sep-04 14:18
xpbrains14-Sep-04 14:18 
Generalvery good.. (altough i haven't tried it out) Pin
Bernhard1-Jan-02 21:45
Bernhard1-Jan-02 21:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.