Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium


CScrollView not clear when using non-TWIPS Map Modes

Posted on 1998-08-13
Medium Priority
Last Modified: 2013-11-20
I'm using Visual C++ 5.0 and am working with an SDI project.  

I had programed a long CScrollView output in the MM_TWIPS map mode.  My output to the screen was crisp and looked very good no matter how many times I scrolled it up or down.  I ran into a problem using the MM_TWIPS mapmode when I tried to set the vertical size of the view to larger than a value of 32K - I assume because the variable which sets the scrollsizes (the SetScrollSize function in CScrollView) takes int values which are limited to around that size.  There are 1440 TWIPS/Inch so this limits you to a vertical size of the view of about 22 inches or so. (which would be the value of the size of the int variable 32K / 1440)  I want to have my outputs be longer in vertical size than this so I decided to switch to a map mode which would allow me to address larger vertical sizes (i.e., a map mode which was lower in resolution.  I tried MM_HIENGLISH and MM_LOENGLISH and both worked well to solve the problem - however a new problem appeared which was not present with MM_TWIPS.  

The quality of the screen outputs which were so clean despite scrolling up and down in TWIPS mode got screwy in any of the other modes (HIENGLISH, LOENGLISH, HIMETRIC, LOMETRIC).  What happens is that the text output to the screen seems to compress some lines and expand others.  Worse still - when you scroll up and down in the outpute created in these non-TWIPS modes, the act of scrolling corrupts the image so that what was reasonably drawn before is now all jumbled.  Forcing the window to Invalidate (and thus redraw) each time the scroll is moved does make the output look pristine - however this is not a good solution as the 10,000 invalidations make the use of the scrollbars difficult (scrolling looses all of its smoothness when you do this).

Can someone tell me 1) why the screen output is breaking up upon scrolling in non-TWIPS mapmodes AND 2) can you tell me a way to keep this from happening which doesn't involve constant forced invalidation of the view?

Thank you
Question by:dombmark
  • 3
  • 3

Author Comment

ID: 1320764
Edited text of question

Accepted Solution

jstolan earned 450 total points
ID: 1320765
Here is a way to go back to the MM_TWIPS mode with a long display.  I ran into this earlier, and wrote a routine that works around the 16 bit limit in the thumbtrack.  Basicly you use a new member variable m_iLastThumb to keep track of the 32 bit position.  You must initialize this variable to zero in your CScrollView derived constructor.  You then override the OnScroll function.  Copy the OnScroll function from the MFC source code and replace the vertical scroll handler with the following:

    switch (HIBYTE(nScrollCode))
    case SB_TOP:
        y = 0;
        m_iLastThumb = y;
    case SB_BOTTOM:
        y = INT_MAX;
        m_iLastThumb = y;
    case SB_LINEUP:
        y -= m_szLineScroll.cy;
        m_iLastThumb = y;
    case SB_LINEDOWN:
        y += m_szLineScroll.cy;
        m_iLastThumb = y;
    case SB_PAGEUP:
        y -= m_szPageScroll.cy;
        m_iLastThumb = y;
    case SB_PAGEDOWN:
        y += m_szPageScroll.cy;
        m_iLastThumb = y;
        // This is an unreal Kluge but it appears to be necessary
        y = nPos;
        // nPos value has FFFF in msb if bit 15 is set, 0000 if bit 15 is clear
        // It is not (as one would expect) a 32 bit value! so we strip off MSW
        if( y < 0 ) y &= 0x0000FFFF;
        // We retrieve the last thumb position (which we own), and make it 16 bit like nPos
        int iYTest = m_iLastThumb & 0x0000FFFF;
        // If we scrolled past 16 bit boundary forward, increment last scroll position MSW
        if( ( iYTest > 0xC000 ) && ( y < 0x04000 ) )
            m_iLastThumb += 0x00010000;
        // If we scrolled past 16 bit boundary backward, decrement last scroll position MSW
        if( ( iYTest < 0x4000 ) && ( y > 0x0C000 ) )
            m_iLastThumb -= 0x00010000;
        // Now m_iLastThumb MSW is correct and y has correct LSW
        m_iLastThumb &= 0xFFFF0000;
        // Combine them
        y = y + m_iLastThumb;
        // and remember it for next time
        m_iLastThumb = y;


Author Comment

ID: 1320766
I've tried your solution and so far have not been able to get it to work (although it seems like it should).  

I defined a _int32 var m_iLastThumb as you suggested in the View.h

I initialized this var  to 0 in the constructor for the view

I overwrote OnScroll and inserted the code as you suggested.  When I did this I could not get it to compile as the variables your code suggested (m_szLineScroll.cy and m_szPageScroll.cy) were not recognized by the compiler.  I substituted the variables m_lineDev.cy and m_pageDev.cy which were used in the source and it then compiled.  

I'm still not able to address the view to a y value larger than the 16 bit integer.  When I try to do this  using the following code

OnDraw ()
// ypos = (code which outputs stuff to the view using textouts and similar functions at the current // ypos and then returns the last y-value)

sizeTotal.cy = abs(pText.y);
sizeTotal.cx = 10080;
CSize sizePage(sizeTotal.cx / 2, sizeTotal.cy /7); // page scroll
CSize sizeLine(sizeTotal.cx / 200, sizeTotal.cy / 500); // line scroll
SetScrollSizes(MM_TWIPS, sizeTotal, sizePage, sizeLine);

I end up with screwy graphs which (since their rectagles have bottoms which terminate below the 16bit value draw up instead of down and mask all output above them - and whatever text output which is drawn below the 16bit limit of the ypos may or may be there but you can't scroll down to view it - the view is cut at the 16bit limit.  

I'm thinking that the SetScrollSizes code needs to be overwritten in a manner not unlike you've done with OnScroll.  (but I'm a bit out of my league here).  Either that or my code which directly outputs to the view at the current ypos just can't be doing that below the limit and I need to figure out some other way to address text and rectangles below that limit.

Do you have any suggestions on how to get this working the way you say it should?  
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Expert Comment

ID: 1320767
I apologize for the m_szLineScroll and m_szPageScroll problem.  I had forgotten that I converted this from a CScrollView to a CView derived class.  I did this because I wanted to exclude a portion of the window from scrolling, not because of smoothness.  Your conversion to m_lineDev and m_pageDev were exactly right.

The SetScrollSizes should be set outside of the OnDraw function.  I usually do this in the OnInitialUpdate function.  Unless you change the size, you only need to do it once.

I'm not sure I understand your drawing code perfectly.  Here are two things to remember

1.  You need to do a call to GetScrollPosition somewhere in the OnDraw function to get the position value.  This will give you a clue as to which area needs to be redrawn.  No since in redrawing everything unless it's REAL fast.

2.  The 16 bit error only occurs in the SB_THUMBTRACK procedure.  You should be able to scroll with the SB_PAGEUP SB_PAGEDOWN SB_LINEUP or SB_LINEDOWN functions without a problem.  If you're having a problem in that area, you're OnDraw function is not working correctly.

This code worked well for me.  If you post a larger snippet, I'll be happy to take another look.

Good luck


Author Comment

ID: 1320768
Thanks for the reply.  I've not fully soved the problem I was having yet (lack of time!) but I'll work on it some more  later - no sense in  holding up your points indefinately.  I have learned more anyway at this point.  

Regarding not calling setscrollsizes from OnDraw.  the way my present ondraw function is working it is calling functions that draw to the screen and that do not check before hand to see if there is enough room on the screen.  Each of these functions takes a logical units (TWIPS for instance) y position to tell it where on the screen to start drawing and returns the last yposition it drew to.  The problem I was having was occuring when I several of these functions one on top of each other so that the final yposition returned exceeded the limit.  I 'solved' the problem by making the screen output functions be mutually exclusive with only one showing at a time and using a toolbar set up as a bunch of radio buttons to allow easy access from one output type to another.  This is more like a dodge of the problem but - it actually seems to  improve navigation as having the user scroll through a single massive view is clunckly anyway

Note that the program in its present does not know before entering ondraw how long the size of the output screen will be (as the size of the output depends on the size of the user's file which is being processed).  For this reason I had put the setscrollsizes function at the end of the ondraw function.  Now that I think about it - it might be a good idea to locate a function called just before  ondraw is called (I'll use the functions I've attached to each of the radio buttons in my toolbar so they each execute only once and do not interfere with the ondraw loop that seems to function continuously in the background) and from this pre-ondraw file call a routine to determine the size of each screen before calling ondraw.  In that way I can call setscrollsizes before entering ondraw and not have to call it repeatedly.  

Thank you very much for your help.

If you have any further suggestions I would sure like to hear them.  

Expert Comment

ID: 1320769
Your idea of a separate SetScrollSizes routine is good.

About the only other thing I could suggest would involve a fairly significant restructuring of the draw routine.  Drawing is typically quite slow, and it is going to be very time consuming to have to draw everything whenever the user scrolls.  This will result in poor scrolling performance, defeating the purpose of what you were trying to accomplish.  If the performance is not what you would like, you might try this.

1.  In the OnDraw function, call a new function which doesn't draw, but simply determines it's location.  It can be just like the draw routine, accepting a y position to start and returning a yposition for the last point it needs.

2.  Using this information and the scroll value, determine which objects need to be drawn at all.  You might include a region 1/2 a screen above and 1/2 a screen below to minimize flickering.

3.  Then draw only those objects that really need it.

Have fun

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

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

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
With just a little bit of  SQL and VBA, many doors open to cool things like synchronize a list box to display data relevant to other information on a form.  If you have never written code or looked at an SQL statement before, no problem! ...  give i…
Suggested Courses

569 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