Solved

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

Posted on 2004-09-20
20
970 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:madanponna
Comment Utility
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
Comment Utility
If it is based on CListView try replacing CScrollView with CListView.
Does that sort it out?
0
 

Author Comment

by:madanponna
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:madanponna
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Do you invalidate the view after the SetScrollPos ?  (We are getting closer - the scroll bar does show an effect ! )
0
 

Author Comment

by:madanponna
Comment Utility
Thanks to all for helping to solve my problem.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
sameEnds challenge 3 105
tenRun challenge 28 81
count11 challenge 6 47
mapAB Challlenge 35 84
If you haven’t already, I encourage you to read the first article (http://www.experts-exchange.com/articles/18680/An-Introduction-to-R-Programming-and-R-Studio.html) in my series to gain a basic foundation of R and R Studio.  You will also find the …
This article will show, step by step, how to integrate R code into a R Sweave document
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

762 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now