|
I've found this code searching for a solution simply to use and not so complex as CRollupCtrl (also in CodeProject).
I need to add some other fields (rarely used and loaded automatically) to a CDialog that is already dimensioned at maximum screeb size for our specification.
This code is very simple and can inserted in few cut and paste, but:
1) I need to scroll automatically when users move with TAB os Shift+TAB
2) My control is a part of a more complex dialog and I need to maintain TAB sequence between scrolling dialog and main dialog
Ok, these doenst requires long work, but I want to share this enhancements, maybe some find it usefull...
1) Set "Control" property in dialog design to TRUE and after child creation insert a
::SetWindowPos( m_pdlgScroll->GetSafeHwnd(), GetDlgItem( ID_PREVIUOUS_CONTROL)->GetSafeHwnd(),
0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
where ID_PREVIOUS_CONTROL is the ID of any control already present in parend dialog (in the sample you can try with IDCANCEL)
2) This is a little more tricky, and can depend on controls present in child window, in my case EDITs and BUTTONs.
I've added two notification handler
ON_CONTROL_RANGE(EN_SETFOCUS, 0, 0xFFFFFFFF, OnSetFocus)
ON_CONTROL_RANGE(BN_SETFOCUS, 0, 0xFFFFFFFF, OnSetFocus)
(remember that buttons have notification disabled by default so you need to activate in dialog design mode)
void CDlgScrollable::OnSetFocus( UINT nID)
{
CWnd * pWnd = GetDlgItem( nID);
if ( pWnd == NULL)
return;
CRect rc;
pWnd->GetWindowRect( rc);
ScreenToClient( &rc);
// We don't need to scroll...
if ( rc.top >= 0 && rc.bottom <= m_nCurHeight)
return;
// This is a check since I have edit that can be longer than the child window
if ( rc.Height() > m_nCurHeight && ( rc.top >= 0 || rc.bottom <= m_nCurHeight))
return;
// The first 2 cases just to have a smooth scroll, maybe you want less scrolls and use directy 3rd option
int nTop;
if ( rc.bottom > m_nCurHeight && ( rc.bottom - m_nCurHeight) < m_nCurHeight / 4) {
nTop = max( 0, m_nScrollPos +( rc.bottom - m_nCurHeight) +3);
TRACE( "Scoll in basso - top a %d\n", nTop);
} else if ( rc.top < 0 && abs( rc.top) < m_nCurHeight / 4) {
nTop = max( 0, m_nScrollPos +rc.top -3);
TRACE( "Scoll in alto - top a %d\n", nTop);
} else {
nTop = max( 0, rc.top +m_nScrollPos -3);
TRACE( "Riposiziona top a %d\n", nTop);
}
// Sure not to scroll to much (ie in last line) and leave at least one page
if ( nTop +m_nCurHeight > m_rcOriginalRect.Height())
nTop = m_rcOriginalRect.Height() -m_nCurHeight;
// Just scroll
int nDelta = nTop - m_nScrollPos;
m_nScrollPos += nDelta;
SetScrollPos( SB_VERT, m_nScrollPos, TRUE);
ScrollWindow( 0, -nDelta);
}
Hope this help.. and thanxs to the author.
|
|
|
|
|
Have you ever tried this class in a MDI environment?
It seems all working in debug mode, but in release mode when you try to communicate to the parent, it result in a CRASH of the application...
I have a MDI form that call a dialog in which I putted this class... I'm not able to communicate to any of the MDI window, nor the main wnd. I tried with SendMessage(), PostMessage(), RegisterWindowMessage()... NO WAY TO COMMUNICATE WITHOUT A CRASH.
I'm very surprised, in particular 'cause there is no problem in debug mode..
|
|
|
|
|
Hi,
Great class, thanks, saved us a lot of work!
What we would like to do is change the size of the original dialog programatically. We have currently done this by:
1. Moving the scroll to the top
2. Setting m_rcOriginalRect.bottom to reflect the new height
3. Calling SetScrollInfo with the appropriate info
i.e.
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
si.nMin = 0;
si.nMax = m_rcOriginalRect.Height();
si.nPage = m_nCurHeight;
si.nPos = 0;
SetScrollInfo(SB_VERT, &si, TRUE);
This appears to work fine, but is very "hacky" is there a better way?
Also you missed the SB_TOP and SB_BOTTOM cases from OnVScroll(). They can be implemented by:
case SB_TOP:
nDelta = 0 - m_nScrollPos;
break;
case SB_BOTTOM:
nDelta = nMaxPos - m_nScrollPos;
break;
And tested by right clicking the scroll bar.
Thanks
|
|
|
|
|
Many thanks for your excellent work!
This class is very usefull if you write software for Win CE!
I had the same problem mentioned in another post:
I couldn't scroll the content of the window. The sample application worked with Win XP but didn't work with Win CE. After a few trial and errors I figured out that I could move the content using ScrollWindow() in OnInitDialog(). Nothing happens if you call this function after when dialog is displayed.
I tried some Invalidate() / UpdateWindow() commands in OnVScroll() without any luck.
So my first fix was this:
ShowWindow(SW_HIDE);
ScrollWindow(...);
ShowWindow(SW_SHOW);
This really worked but looked quite ugly.
A better way is replacing ScrollWindow() with ScrollWindowEx() and passing SW_SCROLLCHILDREN:
ScrollWindowEx(..., NULL, NULL, NULL, NULL, SW_ERASE|SW_INVALIDATE|SW_SCROLLCHILDREN);
It's not a bug it's a feature...
|
|
|
|
|
???
It works great for a child of a dialog. How can I get
it to work for the Dialog itself?
Please any response any one can give me will be greatly
appreciated.
Sincerely,
Danielle (an overworked graduate student)
|
|
|
|
|
Thanx for your comments.
The fastest way to use this code in a formview is to add a child-dialog to the formview. I'll try to write down some snippet as soon as possible, but i really can't tell if i will do it within one, two or three weeks (or months!!!)
Try to move all the controls in the formview into the child dialog, and then add some code to resize the child dialog to fit the formview client area.
Hope this helps
Ciao
|
|
|
|
|
Cool project. Can you show me how to implement this for a CFormView?
Please any response you can give me will be greatly appreciated.
Sincerely,
Danielle (an overworked graduate student)
|
|
|
|
|
Vertical Scroll dialog when tab key is pressed to move to next control and next control is not visible at the bottom of dialog box. After pressing Tab key focus moves to next control but it doesn't scroll he dialog in case the next control is not visible. Pls urgently reply.
|
|
|
|
|
I think I am silly
what must I do to initialize the dialog with the horizontal scrollbar at the right end?
scrollwindow and/or setscrollpos don´t do what I want them to do.
Is there a mistake in my code, or another function I overlooked?
By the hand:
Great job!
Old europ strikes back: Arnie is coming
|
|
|
|
|
Thanks,
It made it easier to solve a difficult problem,
which I was facing for quite a few days.
Sansky
John 3:16
For God so loved the world,
that he gave his only begotten Son ( Jesus Christ ) ,
that whosoever believeth in him should not perish, but have everlasting life.
|
|
|
|
|
Thanks too, I know it already exists in Trolltech Qt, and I didn't know how to do it with MFC.
Nice and simple, great job !
|
|
|
|
|
Does anyone know how to insert scrollbar in a embedded child dialog (for a dialog-based application)? I am using embedded Visual C++ 3.0 too. Thx
|
|
|
|
|
I have found the solution from www.pocketpcdn.com:
Instead of using the ScrollWindow(...), you need to use wce_ScrollChildren(m_hWnd, 0, iMove) in Windows CE application.
|
|
|
|
|
Hi John,
I really think this class is valuable, however I failed to port this code to embedded visual c++ 3.0. First of all, it give me error when compiling, saying there is no OnMouseWheel command, so I comment out this definition and implementation. Then, when I start my sample app in PocketPC 2002 emulator, i can see my child dialog in place, but it doesn't respond to the scrollbar.
Can you help?
Best Regards,
Keith
|
|
|
|
|
Hi,
I have a similar problem.
First it doesn't work with:
GetDlgItem(IDC_PLACEHOLDER)->GetWindowRect(rc);
ScreenToClient(&rc);
m_ScrollDlg->MoveWindow(rc);
So I tried following and it worked:
this->GetWindowRect(rc);
m_ScrollDlg->SetWindowPos(
this,
0,
0,
rc.Width()-4,
rc.Height()-75,
SWP_SHOWWINDOW);
But now the problem. The content of the Dialog is shown but doesn't respond to the scrollbar. The thumb is moving, but the content of the scrollbar is not moving.
Nobody a solution??
|
|
|
|
|
I tested your demo on windows 2000, but I cannot get the mousewheel to work (I can drag it by pressing the left mouse button).
|
|
|
|
|
Click on any control inside the child dialog and then try to scroll using the mouse wheel. In your app you could give focus to one of the child controls during initialization of the parent dialog (you can do it in the OnInitDialog).
This should work
|
|
|
|
|
But if i add a combobox control on dialog and click inside it than also mouse wheel does not work.
sankalp
|
|
|
|
|
Make sure the child dialog has the DS_CONTROL style and the parent has WS_EX_CONTROLPARENT.
|
|
|
|
|
Nice work.
For smoother scrolling add just one more line:
case SB_THUMBTRACK:
immediately after the
case SB_THUMBPOSITION: line.
Again, good work.
|
|
|
|
|
thanx for suggestion, code is now updated!
|
|
|
|
|
You could also put your inner controls in a sysPager custom control and move them a page at a time. Up to you which look you prefer though.
'--8<------------------------
Ex Datis:
Duncan Jones
Merrion Computing Ltd
|
|
|
|
|
...that you won't find any code for this in CodeProject/CodeGuru. I have had this need no more than a few days ago, to help me contain an xml-based UI.
Thanks for the article.
|
|
|
|
|
Not really, it's usually a very bad design. If you have so many controls that you have to hide some of them, tabs are most likely a better idea.
Still, sometimes it's useful, for example if you have to duplicate the layout of a paper form.
|
|
|
|
|
My point was about xml-based UIs, ie UIs that are really built from scratch at run-time and you have no idea of what it might look like, and what can be the extent in width and height.
|
|
|
|