Auto scroll in CFormView

I have some controls in CFormView, and when I tabbed to those which out of the visible area, I can't see the caret or the active control. How can I make auto scroll depending on the caret's position or the active control position. I would like a global method as posible i.e. avoiding treating each control.
slapakAsked:
Who is Participating?
 
piano_boxerConnect With a Mentor Commented:
Add this WM_COMMAND hander to your CFormView class. It will up and down it the control receiving focus is not visible.

NOTE: and the variable m_nScrollPos to the class header and initialize it to zero in the constructor;

BOOL CXxxxView::OnCommand(WPARAM wParam, LPARAM lParam)
    {
        if( lParam && HIWORD(wParam)==EN_SETFOCUS )
        {
            MessageBeep(-1);

            CWnd* pControl = CWnd::FromHandle((HWND)lParam);
            ASSERT_VALID(pControl);

            CRect rcControl;
            pControl->GetWindowRect(&rcControl);
            ScreenToClient(&rcControl);

            int nScroll = 0;
            if(rcControl.top < 0)
                nScroll = -rcControl.top;
            else
            {
                CRect rc;
                GetClientRect(&rc);
                if(rcControl.bottom > rc.bottom)
                    nScroll = rc.bottom-rcControl.bottom;
            }

            if(nScroll)
            {
                m_nScrollPos = m_nScrollPos-nScroll;
                SCROLLINFO si;
                si.cbSize = sizeof(si);
                si.fMask = SIF_POS;
                si.nPos = m_nScrollPos;
                SetScrollInfo(SB_VERT, &si);
                ScrollWindowEx(0, nScroll, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN|SW_INVALIDATE|SW_ERASE);
            }
        }
0
 
piano_boxerCommented:
A little update to my prev answer:

As a formview is derived from CScrollView, a better way to scroll the view would be to call ScrollToPosition() and GetDeviceScrollPosition() to get the current scroll position instead of using SetScrollInfo() and ScrollWindowEx().
0
 
slapakAuthor Commented:
All right, but it works only if I don't have radio button or other CButton derivatives. What can I do in this case?
0
 
piano_boxerCommented:
To add support for other that edit controls, you need to look for aditional notification values in the WM_COMMAND handler.
NOTE: You need to enable the notify window flag for every control for this to work!

Button:     BN_SETFOCUS
Edit:       EN_SETFOCUS
ListBox:    LBN_SETFOCUS
ComboBox:   CBN_SETFOCUS

The new common controls send WM_NOTIFY messages to its parent, so
we need to handle them a little different.

Insert the decleration of the handler in the views class header:

    void OnSetFocusNotify( NMHDR * pNotifyStruct, LRESULT * result );

Insert this line above END_MESSAGE_MAP for the views class:

    ON_NOTIFY_RANGE(NM_SETFOCUS, 0, 0xffff, OnSetFocusNotify)


Insert the handler code in the views cpp-file:

void CXxxxView::OnSetFocusNotify( NMHDR * pNotifyStruct, LRESULT * result )
{
    CWnd* pControl = CWnd::FromHandle(pNotifyStruct->hwndFrom);
    ASSERT_VALID(pControl);

    CRect rcControl;
    pControl->GetWindowRect(&rcControl);
    ScreenToClient(&rcControl);

    [ insert code to scroll here ]
}
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.