Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » themed scrollbars (again) Collapse All
Subject Author Date
pere montana May 10, 2007 - 5:21 AM

Dear Support,

MFCs CScrollView is handy and allows different mapping modes besides MM_TEXT. I’d like to use it with a themed scroll bars. in a previous thread you advised a way to replace usual scrollbars with CExtScrollBar. the code you provided does not work. scroll bars do not show up. (DRAWCLI sample has this portions of code commented)
I made scroll bars child of mainframe. ==> m_wndScrollBarV.Create( WS_CHILD | WS_VISIBLE | SBS_VERT | SBS_RIGHTALIGN, CRect(0,0,0,0), /*this*/ GetParent(), 1);
it works fine, but:
* it leaves a small square not painted at bottom right, as noted on previous thread, and this portion of screen does not belong to the view but its mainframe’s
* the scrollbars do not take into account dockable panels (it looks ugly) can it be fixed from mainframe ?
* at least working with MM_LOMETRIC you can actually scroll twice the height of a window. first keepint pushed the top button and a second time dragging the scroller.

Thanks

pere montana May 18, 2007 - 11:41 AM

hello support team,
version 2.70 besides fixing some issues worsen some others. I might think some of you hate CScroolView :) with the new version freshly compiled librarys, somebody is trying to paint the view on its own, before the mfc framework does its job. it craks. I found an easy workaround setting up a flag (s_bImReady) which gets marked as soon as OnInitialUpdate is called and overrided OnPrepareDC:

    if (s_bImReady)
        CScrollView::OnPrepareDC(pDC, pInfo);
// else somebody is tryng to paint before OnInitialUpdate gets called: do nothing

this is a workaround, but I reckon you should fix it

pere montana May 16, 2007 - 9:35 AM

dear Support:
seemingly I do not express myself quite clear, for you are solving a problem nobody has, and not showing a way to fix a problem that CExtScrollBar do has. CScrollView works fine on its own. the class handles scrolling ok. when a replace CScrollBar with CExtScrollBar appears a problem. Only with the arrows: it performs pageup/down and thumbtracking as expected. but pushing one of the buttons generates lineup/down message and BOTH scrolls the window AND moves the bar. but, and this is the problem, not in the same amount. CScrollView has a func ’SetScrollSizes’ which has no effect on CExtScrollBar.
A workaround can take two ways:
1 manually scroll the page the same amount the bar has moved.
2 manually move the bar the same amount the page has been / will be moved.
(it is also possible apply both methods together an arbitray amount)
as I noticed CExtScrollBar does NOT respond to SetScrollPos (it’s a CScrollBar derived is’nt it?)
I adopted method 1: in OnVScroll (the bar it has already been moved -1pixel- and I found no way to move it further) as showed above.

so, if you have a better method it will be wellcome.


Technical Support May 16, 2007 - 10:21 AM

Yes, the problem is exactly described in your messages. Simply saying: it is not always possible to redraw custom painted scroll bar when its position is changed programmatically.



pere montana May 14, 2007 - 11:47 AM

dear Support
I do not understand your advice. OnVScroll gets all scroll related messages; any scroll related message I send from within it will return to the very same place. what I do instead, is call the CScrollView method (OnScroll) that would be invoked if the original message was a THUMBTRACK notification, in order to control the amount of scrolling in the window.
where’s the point ?

Technical Support May 15, 2007 - 8:46 AM

The idea is simple: you have received the line up/down scrolling notification and invoking the OnScroll() method like the thumb position was changed. But the scrollbar windows does not know what you do. You should synchronize state of the scroll bar windows with the scrolling position which you are going to pass to the OnScroll() method. That is why we advise you to emulate the thumb button tracking via changing the scroll bar position value and re-sending appropriate SB_THUMBTRACK notification message.

pere montana May 13, 2007 - 1:37 PM

dear Support
I reckon it most be something related with mapping modes used with CScrollView. I converted line up and line down to exactly one pixel up/down and it works ok (too slow, but at leat synchronized)

void        CMANT2View::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) {
int        delta=0;

    switch (nSBCode)    {
    case SB_LINEUP:
        delta =-1;
        break;
    case SB_LINEDOWN:
        delta =+1;
        break;
    }
    if (delta !=0 && pScrollBar)    {
        OnScroll(MAKEWORD(-1, SB_THUMBTRACK), pScrollBar->GetScrollPos()+delta);
        return;
    }
    CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
}
(ant the same for horizontal scroll)
bye

Technical Support May 14, 2007 - 9:00 AM

Your scroll position changing method is not correct. Please replace the OnScroll( . . . ) method invocation with SendMessage( . . . ) and synchronize the scroll bar positions manually.

pere montana May 11, 2007 - 8:33 AM

thanks, it works fine. I simplified a bit: no need for a CWnd container inside a FrameWnd container, so I put the CExtScrollBar in the mainframe and create them in OnCreate (along with toolbars, etc.), provided a func to pass CExtScrollBar ptrs to the scrollview (needed some cast because of const) and use these ptrs in CScrollView::GetScrollBarCtrl. I put the code you gave for CwndContainer in CMainFrame:OnPaint to take care of the square bottom.right and let MFC to do the rest. allright.
still an issue remaining: CExtScrollBar does not synchronize the bar with the scrolling done thru top and down buttons. is there a way to fix it ? (tha is move the bar in the same amount as line up and line down do scroll)

Technical Support May 13, 2007 - 6:27 AM

It seems the synchronization problem is caused by something in your code that is handling scrolling notification events because the CExtSplitterWnd class used in the DRAWCLI sample does nothing except for redirecting WM_HSCROLL and WM_VSCROLL messages.



Technical Support May 10, 2007 - 11:22 AM

In the DRAWCLI sample, the CExtSplitterWnd control automatically creates the CExtScrollBar windows and retranslates the WM_HSCROLL and WM_VSCROLL messages to view windows correctly. So this is not the same view scrolling as it should be implemented in your application. You need to create the following window structure:

1) Some CWnd-based container window as a child of main frame window.

2) Your CScrollView-based window and two CExtScrollBar windows as children of the container window.

Both container and scroll view should have the AFX_IDW_PANE_FIRST dialog control identifier. The container should invoke CWnd::RepositionBars(0, 0xFFFF, AFX_IDW_PANE_FIRST ); both after creating child windows and when handing the WM_SIZE message. The container window should implement the OnCmdMsg() and PreTranslateMessage() virtual methods and redirect their invocations to the scroll view window inside it. The container window should send the WM_HSCROLL and WM_VSCROLL messages to the scroll view window. The CScrollView-based class should implement the virtual CWnd::GetScrollBarCtrl() virtual method and return pointers to the CExtScrollBar windows created in its parent container window. The container window should eat up the WM_ERASEBKGND message and handle the WM_PAINT message for filling the corner area between scroll bar controls using the following code:

if( ! g_PaintManager->PaintDockerBkgnd( true, dc, this ) )
{
      CRect rcClient;
      GetClientRect( &rcClient );
      COLORREF clrBk = g_PaintManager->GetColor( CExtPaintManager::CLR_3DFACE_OUT, this );
      dc.FillSolidRect( 
            &rcClient, 
            clrBk
            );
}
In this case you should not have any problems with the scroll bar windows and any other windows inside the main frame window.