Zoom | Scroll

Could anyone show me how to zoom ->and<- scroll a bitmap within a CDialog?

First off...
I load a bitmap from file.
I then draw it on the background of the dialog in the OnEraseBkgnd function.

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

How are you displaying the bitmap?  An CBitmapButton? and owner drawn button? a window?

We need to know how you display it before we can tell you how to scroll it.

matzonAuthor Commented:
Edited text of question
matzonAuthor Commented:
Edited text of question
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

Do you want it to scroll automtically (like scrolling credits at the end of a movie) or what?

In any case, if you use BitBlt to draw it, change to StretchBlt instead, as this will allow you to zoom and scroll

Perhaps if you post your code for your OnEraseBkgnd I can give you more help


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
matzonAuthor Commented:
I'll start from the beginning.
Basically, what I am trying to create, is a dialog which can show a bitmap (loaded
from a file). The bitmap should be able to be of any size(256 colors though).

I use a function from Codeguru (LoadBMPImage) to load the image and create the palette.
The following is member variables on my CDialog

      BITMAP bm;
      CBitmap bmp;
      CRect rect;
      CPalette* pPal;

I then override OnEraseBkgnd(CDC* pDC)
and draw the bitmap:

BOOL CElDlg::OnEraseBkgnd(CDC* pDC)
      CDC memDC;
      bmp.GetBitmap( &bm );
      return 1;

My first problem, is that i need to be able to scroll the dialog in order to see
the entire bitmap.
For this i need to attach 2 scrollbars:

      //Get dialog size
      RECT Coords;

      //Set bottom Scroll
      //Get and position scrollbar on bottom ...
      CRect PosBot(0, (Coords.top), (Coords.right-15),        Coords.bottom);
      BotScroll.Create(WS_VISIBLE | SBS_HORZ | SBS_BOTTOMALIGN , PosBot, this, 65000);
      BotScroll.SetScrollPos(0, false);

      //Set Right Scroll
      //Get and position scrollbar at right boder ...
      CRect PosRig(Coords.right, 0, Coords.right, (Coords.bottom-15));
      RigScroll.Create(WS_VISIBLE | SBS_VERT | SBS_RIGHTALIGN , PosRig, this, 65001);
      RigScroll.SetScrollPos(0, false);

But this doesn't work?
The bottom scrollbar blinks???
The scrollbars doesn't increase in position?

At the same time I need to be able to zoom?
I need to create all this within a CDialog, since I can't instanciate a CScrollView from
my main SDi app. Or can I?

I can mail you the program if you wish?
hope this helps you (and in the end me :·))

btw: just out of curiosity are you ->Roger<- Onslow?

Yes .. I am indeed ->Roger<- Onslow .. do you know of me?

In you draw code you use BitBlt .. change this to a StrtchBlt instead.  Then you can specify the part of the bitmap you want to display and can scale it (by making the source and destination rectangles of different size.

After attaching the scrollbars, you need to respond to the scrolling messages.  These should change the parameters to the StretchBlt so that the approriate part of the bitmap is displayed.  Note that you'll also need to force the dialog to repaint itself or the erase backgroun won't be called again.

Perhaps you'd be better putting the bitmap in an owner-drawn button (say) and have that button along with the scroll bars (and maybe some zoom control) on a dialog.

matzonAuthor Commented:
Ill be giving you a B, since the answer is good, but doesn't help a newbie (like me!) that much.
Since the initial question, i have come so far that i am able to zoom and scale a (background drawn)bitmap picture, in a CScrollView.
But this doesn't really help me, since I can't initiate a CScrollView from within my CFormView derived SDI app.
The problem with using a dialog, is that after I create the scrollbars they don't seem to react to a scroll??
I've posted the question on the discussion board at Codeguru, which is were I've heard of you.

Do you disagree with my grading?

I disagree a little... I never suggested you use a scroll view (did I?) .. And I've told you why your scroll bars aren't working .. and suggested a better (or at least different) was to do what you want.

Surely if the information is not clear enough, then you can just ask me for further info and clarification before grading me.

matzonAuthor Commented:
No you never suggested the use of CScrollView.
and yes you've told me how to use the scrollbars but they don't work anyway? I override OnVScroll and OnHScroll and set the scrollbars position, but for some strange reason the scrollbars never change position?

About the button solution, I find that to be an strange solution, since that only complicates the process(i.e I now have to scroll and soom a button instead of the initial dialog?)

You aren't really scrolling the dialog .. but rather the background of it.  A background doesn't scroll when you use scroll bars.

You haven't shown me what your OnVScroll etc code does so that I may be able to help with finding out why it doesn't work.

Having the bitmap in a control in the dialog so that you can add scroll and zoom controls around it seems fairly sensible.  If you prefer the other way, I do have xode that displays a bitmap in a dialog.  It doesn't support scrollbars, but I can see if I can add them for you.  How the user would perform a zoom I don't know .. perhaps clicking on the dislog somewhere?

matzonAuthor Commented:
Well... My code for OnVscroll looks like this:

void OnVScroll( UINT nSBCode, UINT nPos,
CScrollBar* pScrollBar )
   //Bottom scrollctrl
   BotScroll.SetScrollPos(nPos, true);

If you have the time, I would love to get hands on that code for displaying bitmap in a dialog, preferably with scrollbars..
The zoom capabilities(or ZoomFactor) could be placed on a menu(right click)
But I still need the window to redraw itself?

How would I give you some more points?

So the handler for when the scroll bar changes simple changes the scroll bar.  Instead, the handler should change the variables that say what part of the image to show.

I'll try changing that sample code I mentioned so that scrollbars will be present (and working, I hope).

Then I can send you the project (or at least the differences).

If this is really helpful for you, you'll either have to post another (dummy) question for me to answer, or get in touch with Linda@experts-exchange.com and/or post a message in the EE Customer Support topics area saying (for example) that you prematurely graded this question with a B and would like to re-grade after receiveing extra help).

All that is, of course, on the condition that I can actually get this working for you ... I wouldn't like you to arrange for a better grade or use up extra points without getting a good result.

OK .. I started with the MSJ March 1997 C++ article sample code.

This sample displays a window (with menu) and shows a bitmap.  It uses a tooltip to describe the part of the image the mouse is hovering over.  (NOTE: doesn't use a dialog .. but you may find the classes and techniques in this sample useful).

I've changed the sample so that the main window is only half the required height and width, and added the scroll bars.  Now you can scroll around the image using the bars .. and the tooltips still work

I'll post you the sample .. my code is indicated with // RKO comments.

Basically (except for changes to window size and tooltips) I added these to the class definition...

  // RKO added these to keep track of scoll pos and max pos
  int m_nVscrollPos;
  int m_nHscrollPos;
  int m_nVscrollMax;
  int m_nHscrollMax;
  // RKO added this to set scroll bar style
  virtual BOOL PreCreateWindow( CREATESTRUCT& cs );
  // RKO added these to respond to scroll messages
  afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );
  afx_msg void OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );

Then made these changes to the class implementation...

// RKO added these handlers to the message map

in the constructor...

  // RKO initial scroll bar pos (top left)
  m_nVscrollPos = 0;
  m_nHscrollPos = 0;

and added ...

// RKO ensure we have scroll bar style
BOOL CMainFrame::PreCreateWindow( CREATESTRUCT& cs ) {
  BOOL ret = CFrameWnd::PreCreateWindow(cs);
  cs.style |= WS_HSCROLL | WS_VSCROLL;
  return ret;

in the OnCreate (for a dialog, OnInitDialog) ...

  // RKO added this to set up scroll bars
  CSize sz = m_dibImage.GetSize(); // size of bitmap
  m_nVscrollMax = sz.cy - mmi.ptMaxSize.y;
  m_nHscrollMax = sz.cx - mmi.ptMaxSize.x;
  SetScrollRange(SB_VERT, 0, m_nVscrollMax, FALSE);
  SetScrollPos(SB_VERT, 0, TRUE);
  SetScrollRange(SB_HORZ, 0, m_nHscrollMax, FALSE);
  SetScrollPos(SB_HORZ, 0, TRUE);

in the OnPaint...

  // RKO setup dest rect based on scroll pos
  CRect rcDst(-m_nHscrollPos,-m_nVscrollPos,-m_nHscrollPos-1,-m_nVscrollPos-1);

And finally...

// RKO handle scroll messages

void CMainFrame::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) {
  m_nVscrollPos = GetScrollPos(SB_VERT);
  int nVscrollInc;
  switch (nSBCode) {
  case SB_TOP:
    nVscrollInc = 0 - m_nVscrollPos;
  case SB_BOTTOM:
    nVscrollInc = m_nVscrollMax - m_nVscrollPos;
  case SB_LINEUP:
    nVscrollInc = -1;
    nVscrollInc = 1;
  case SB_PAGEUP:
    nVscrollInc = -8;
    nVscrollInc = 8;
    nVscrollInc = nPos - m_nVscrollPos;
    nVscrollInc = 0;
  if (nVscrollInc) {
    m_nVscrollPos += nVscrollInc;
    ScrollWindow(0, -nVscrollInc, NULL, NULL);
    SetScrollPos(SB_VERT, m_nVscrollPos, TRUE);

void CMainFrame::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) {
  m_nHscrollPos = GetScrollPos(SB_HORZ);
  int nHscrollInc;
  switch (nSBCode) {
  case SB_LEFT:
    nHscrollInc = 0 - m_nHscrollPos;
  case SB_RIGHT:
    nHscrollInc = m_nHscrollMax - m_nHscrollPos;
  case SB_LINEUP:
    nHscrollInc = -1;
    nHscrollInc = 1;
  case SB_PAGEUP:
    nHscrollInc = -8;
    nHscrollInc = 8;
    nHscrollInc = nPos - m_nHscrollPos;
    nHscrollInc = 0;
  if (nHscrollInc) {
    m_nHscrollPos += nHscrollInc;
    ScrollWindow(-nHscrollInc, 0, NULL, NULL);
    SetScrollPos(SB_HORZ, m_nHscrollPos, TRUE);

matzonAuthor Commented:
Hi... Thnx very much...

I've now got a running dialog.
Ofcourse I still need to be able to zoom. But that should be simple (StretchBlt?).

I'll be posting a new question for you!
The interesting thing is how will the USER tell the program to zoom.  Perhaps a left click to zoom in and right click to zoom out?

matzonAuthor Commented:
hmm I thought of a popop menu to set the zoom factor.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.