Solved

How to synchronize Scrollbars in more then one child windows in MFC  MDI applications?

Posted on 2004-09-20
20
1,023 Views
Last Modified: 2012-05-05
Hai Friends,
       hope everybody are enjoying the life.

Friends, I got a problem, please help me out.

 I'm coding in VC++, and using MDI application.
Problem is,
If in one child window if I drag a Scroll bar, then simulataneously the scroll bar in other child window also has to move!!!!

Please help me out as early as possible.

Thanks a lot...

Have a nice day!

0
Comment
Question by:madanponna
  • 10
  • 8
20 Comments
 
LVL 48

Assisted Solution

by:AlexFM
AlexFM earned 200 total points
ID: 12110727
This is a way to create MFC MDI application with CScrollView class, which scrolls all it's views synchronously. If number of child views are opened, scrolling of one view scrolls by the same way all others.

1) Create MFC MDI application (I called it Test). On the last step of MFC Application Wizard select CScrollView class instead of CView.
2) Add WM_VSCROLL and WM_HSCROLL message handlers to CTEstView classes and fill them by the following way:

void CTestView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    AfxGetMainWnd()->PostMessage(WM_APP + 1, (WPARAM)this, 0);
   
    CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CTestView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    AfxGetMainWnd()->PostMessage(WM_APP + 1, (WPARAM)this, 0);
   
    CScrollView::OnHScroll(nSBCode, nPos, pScrollBar);
}

3) Open MainFrm.h file and add this line to message map:

    LRESULT OnMessageScroll(WPARAM wParam, LPARAM lParam);     // add this line
    DECLARE_MESSAGE_MAP()                                                          // before this line

4) Open MainFrm.cpp file and add this include line:

#include <afxcoll.h>

5) Add the following code to the beginning of MainFrm.cpp file (before CMainFrame class functions):

// CDocEnumerator — Enumerates all the documents in an MFC application.
// To use:
//
//    CDocEnumerator it;
//    CDocument* pdoc;
//    while ((pdoc=it.Next())!=NULL) {
//       // do something
//    }
//
// Source: http://msdn.microsoft.com/msdnmag/issues/04/05/CQA/
// Paul DiLascia
// From the May 2004 issue of MSDN Magazine.
//
class CDocEnumerator {
private:
    CPtrArray m_doclist; // array of all docs
    int m_iPos;          // current position in array
public:
    CDocEnumerator();
    CDocument* Next();
    void Reset() { m_iPos=-1; }
};


//
CDocEnumerator::CDocEnumerator() {
    CWinApp* pApp = AfxGetApp();
    POSITION pos = pApp->GetFirstDocTemplatePosition();
    while (pos!=NULL) {
        CDocTemplate* pDocTemplate = pApp->GetNextDocTemplate(pos);
        POSITION pos2 = pDocTemplate->GetFirstDocPosition();
        while (pos2!=NULL) {
            m_doclist.Add(pDocTemplate->GetNextDoc(pos2));
        }
    }
    Reset();
}

//////////////////
// Fetch next document.
//
CDocument* CDocEnumerator::Next() {
    if (++m_iPos < m_doclist.GetSize()) {
        return (CDocument*)m_doclist[m_iPos];
    }
    return NULL;
}

6) Add this line to CMainFrame message map, MainFrm.cpp file:

    ON_MESSAGE(WM_APP + 1, OnMessageScroll)          // add this line
END_MESSAGE_MAP()                                                 // before this line

7) Add the following code to MainFrm.cpp file:

LRESULT CMainFrame::OnMessageScroll(WPARAM wParam, LPARAM lParam)
{
    CScrollView* pSourceView = (CScrollView*)wParam;
    CDocEnumerator it;
    CDocument* pdoc;

    while ((pdoc=it.Next())!=NULL)
    {
        POSITION pos = pdoc->GetFirstViewPosition();
       
        CScrollView* pView = (CScrollView*)pdoc->GetNextView(pos);
       
        if ( pView != pSourceView )
        {
            CPoint pt = pSourceView->GetScrollPosition();
            pView->ScrollToPosition(pt);
        }
    }
   
    return 0;
}
0
 

Author Comment

by:madanponna
ID: 12111940
Hai Alex,
      I'm very very glad to see your answer, thanks a lot.

But Alex, I'm extreamly sorry, as I did not explained my problem clearly.
But your answer is perfectly correct to my question.

Actully my problem is,  as I already said , I'm using MDI application.

And as you wrote in your answer that to inherit from CScrollView, but as per the requirement I inherited from CView class.

what i'm doing is, i'm splitting the child window into TWO panes in CChildFrm.cpp in OnCreateClient() function using CSplitterWnd object.

First Pane(0,0) is a class derived from CListView. And Second Pane(0,1) also derived from CListView.

I created a check box on the MainFrame, so that when I check it, Scrollbar synchronize should occur.

Suppose assume that there are more than one child window.
After checking the check box for scrollbar synchronization,
****whenever I drag a scrollbar in Pane(0,0) in one child window , then Pane(0,0) of other Child window also has to be dragged.

****Similarly whenever I drag a scrollbar in Pane(0,1) in one window , then Pane(0,1) of other Child window also has to be dragged.

Dear Alex, please solve this problem!!!!!!

Thanks a lot for your previous answer.

Waiting.....




0
 
LVL 44

Accepted Solution

by:
AndyAinscow earned 100 total points
ID: 12121872
From the description of a CView
A view handles scroll-bar messages with the CWnd::OnHScroll and CWnd::OnVScroll member functions
Alex has suggested you override those functions.  

What he did was provide a sample of code not specific to your question BUT one that should function as you require.  Ignore the CScrollView base class and try it with your CListView based class.
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:madanponna
ID: 12131271
Thanks Andy!!!!

I changed it to CListView, It is working!!!!!!!

But when I  scroll the pane(0,0) in one of the child window, all other scrollbars of pane(0,0) are scrolled but LIST ITEMS are NOT repainting!!!!

I mean the data in other  panes(0,0) are not repainted and even the List Control HEADER is moving !!!!!!
But this is not happening with the pane(0,0) in which i'm dragging the scrollbar!!!

Please tell me how to solve this problem!!! I used Invalidate() but no use!!!

One more doubt is , in the below code which Alex sent for my question ,
/////////////////////////////////////////////////////////////////////////////////////
7) Add the following code to MainFrm.cpp file:
LRESULT CMainFrame::OnMessageScroll(WPARAM wParam, LPARAM lParam)
{
    CScrollView* pSourceView = (CScrollView*)wParam;
    CDocEnumerator it;
    CDocument* pdoc;

    while ((pdoc=it.Next())!=NULL)
    {
        POSITION pos = pdoc->GetFirstViewPosition();
       
        CScrollView* pView = (CScrollView*)pdoc->GetNextView(pos);
       
        if ( pView != pSourceView )
        {
            CPoint pt = pSourceView->GetScrollPosition();
            pView->ScrollToPosition(pt);
        }
    }
   
    return 0;
}
/////////////////////////////////////////////////////////////////////////


In place of "CScrollView" what I have to use? at present scroll bars are moving with the same above code.

But is it correct?

Because , the left pane(0,0) , say class name CLeftPane ,is derived from CListView.
And the right pane(0,1) , say class name CRightPane , is also derived from CListView.

Now in place of "CScrollView", what I have to use? still "CScrollView" is ok?

________________________

Also please see my other question at :
           http://www.experts-exchange.com/Programming/Programming_Languages/Q_21131575.html

Thanks!!!!


Waiting....






0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 12131528
If it is based on CListView try replacing CScrollView with CListView.
Does that sort it out?
0
 

Author Comment

by:madanponna
ID: 12132403
Hai,
  I pasted CListView in place of CScrollView but I get error as below:

error C2039: 'GetScrollPosition' : is not a member of 'CListView'

????
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 12132687
OK.  Get a pointer to the CListView and then get the underlying list control

pListView->GetListCtrl().GetScrollPosition()

I think the above line is what you would require.
0
 

Author Comment

by:madanponna
ID: 12133114
But Andy, CListView does not have GetScrollPosition() function but it has, GetScrollPos(int nBar), this function returns postion of the scrollbar. I dont find use of GetScrollPos()!!!

What to do now? and more over how to :

/////////////////////////////
But when I  scroll the pane(0,0) in one of the child window, all other scrollbars of pane(0,0) are scrolled but LIST ITEMS are NOT repainting!!!!

I mean the data in other  panes(0,0) are not repainted and even the List Control HEADER is moving !!!!!!
But this is not happening with the pane(0,0) in which i'm dragging the scrollbar!!!

Please tell me how to solve this problem!!! I used Invalidate() but no use!!!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

Waiting...
And thanks a lot for quick responses!
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 12133184
GetScrollPos(SB_HORZ) or SB_VERT

To repaint after you have scrolled you can use Invalidate() then  UpdateWindow().

Could you zip and e-mail your project to me, I would have a quick look tonight.  info@ainscow.ch
0
 

Author Comment

by:madanponna
ID: 12133334
Andy, actually i'm in office now, and I cant send code due to security reasons.

I try with you tips.
But really i'm very much confused!!!!
0
 

Author Comment

by:madanponna
ID: 12133618
I did as  you told :

LRESULT CMainFrame::OnMessageScroll(WPARAM wParam, LPARAM lParam)
{
    CScrollView* pSourceView = (CScrollView*)wParam;
    CDocEnumerator it;
    CDocument* pdoc;

    while ((pdoc=it.Next())!=NULL)
    {
        POSITION pos = pdoc->GetFirstViewPosition();
       
        CScrollView* pView = (CScrollView*)pdoc->GetNextView(pos);
       
        if ( pView != pSourceView )
        {
            CPoint pt = pSourceView->GetScrollPosition();
            pView->ScrollToPosition(pt);
->           Invalidate();
->          UpdateWindow();
        }
    }
   
    return 0;
}

Arrows indicate where I'm calling Invalidate and UpdateWindow functions.

But no use !!!!!

Same problem, unable to repaint after scrolling !!!!!

0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 12134071
No no no, Don't scroll the view itself, scroll the list control that is in the view.
Also you have a CListView -DO NOT CAST IT TO CScrollView, cast it to a CListView and use GetListCtrl() to get the underlying list control.  It is that that you want to scroll the contents of.
 
0
 

Author Comment

by:madanponna
ID: 12135038
Andy, in MDI Applications , we wont find Scroll bars, only to the child windows scroll bars will be there, am I right?

And i'm scrolling only the List view's scroll bar.
Andy , here in India, it is night 10pm. I'm leaving now. I catch you tommarrow.

But a milliion  thanks  for your continous replies!!!!!

Waiting for the right answer!!!!!
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 12136208
in MDI Applications , we wont find Scroll bars, only to the child windows scroll bars will be there, am I right?

Not really - any window COULD have a scrollbar, just does it make sense for it to have one?



And i'm scrolling only the List view's scroll bar

The code you posted you are casting to a CScrollView, not to a CListView AND you need to get the scrollbar of the CListCtrl which is the functional bit inside the CListView.  Just scrolling the view itself should scroll the control (header moving), not the contents of the list.
0
 

Author Comment

by:madanponna
ID: 12141011
Hai Andy,
             I'm doing as you said, but once I cast CScrollView to CListView,
then I cant use GetScrollPostion() function.
But I can use GetScrollPos(int nBar) function, this function return back scroll position,
But  problem is, to which function I have to pass the scroll position which I got from GetScrollPos() function???

Waiting....
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 12141056
You want to scroll the ListControl.  So you need a pointerto the list control you want to use SetScrollPos with.
0
 

Author Comment

by:madanponna
ID: 12142566
Andy,   I did as you said, as below:  

while ((pdoc=it.Next())!=NULL)
{
        POSITION pos = pdoc->GetFirstViewPosition();
       
        CListCtrl* pView = (CListCtrl*)pdoc->GetNextView(pos);
       
        if ( pView != pSourceView )
        {
            int pScrollPos = pSourceView->GetScrollPos(SB_VERT);
            pView->SetScrollPos(SB_VERT,pScrollPos,TRUE);

        }
}

but when I drag the vertical scroll bar, only in one view that is in which i'm dragging the scrollbar , all the  columns are moving. but in remaining views only vertical scrollbar is moving , columns data is not moving!!!

Waiting...
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 12143058
Do you invalidate the view after the SetScrollPos ?  (We are getting closer - the scroll bar does show an effect ! )
0
 

Author Comment

by:madanponna
ID: 12407667
Thanks to all for helping to solve my problem.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

How to remove superseded packages in windows w60 or w61 installation media (.wim) or online system to prevent unnecessary space. w60 means Windows Vista or Windows Server 2008. w61 means Windows 7 or Windows Server 2008 R2. There are various …
Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question