Click to See Complete Forum and Search --> : How to add a ScrollView to Dialog??


Yusheng Dong
March 31st, 1999, 11:02 AM
Hi,


Does any one know how to add a scroll view to a dialog box? Can we add any view to dialog?


Yusheng

David Giovannini
June 7th, 1999, 11:17 AM
Views and dialogs do not get along. I tried many, many combinations. If you want a dialog like interface in a view then use CFormView.

If you want a smart scrolling control in a dialog then you need to write much of the scrolling yourself.

These were written for some QuickTime controls- you'll see some Mac-Like code.

Here is a class ( a hack more like ;->) to activate scrollbars for controls in dialogs and views.



// class to be used in a control that belongs in a dialog
class CWndScroller
{
public:
CWndScroller(CWnd &inWnd);

virtual ~CWndScroller()
{
}
virtual void SetScrollSizes(
const SIZE& sizeImage,
const SIZE& sizePage = CScrollView::sizeDefault,
const SIZE& sizeLine = CScrollView::sizeDefault);
virtual void AdjustFrame();
virtual void ResizeImage(const SIZE& sizeImage);
virtual bool OnScroll(int inBar, UInt sbCode, UInt pos, CScrollBar *bar);
virtual void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

virtual CSize GetImageSize()
{
return mImageSize;
}
virtual void ScrollTo(UInt32 x, UInt32 y)
{
mCurrentPos.x = x;
mCurrentPos.y = y;
mSubject.SetScrollPos(x, y);
}
virtual CPoint GetPosition()
{
mSubject.GetScrollInfo(SB_HORZ, &mInfo);
mCurrentPos.x = mInfo.nPos;
mSubject.GetScrollInfo(SB_VERT, &mInfo);
mCurrentPos.y = mInfo.nPos;
return mCurrentPos;
}

virtual void EraseEmptyRgn();
virtual void ResizeParentToFit(BOOL bShrinkOnly = TRUE);

private:
protected:
SCROLLINFO mInfo;

CWnd &mSubject;
CSize mImageSize;
CSize mPageSize;
CSize mLineSize;
CPoint mCurrentPos;

void UpdateCurrentPostion();
};

// class to be used in a CView subclass
class CViewScroller : public CWndScroller
{
public:
CViewScroller(CWnd &inWnd) : CWndScroller(inWnd)
{
}
virtual void AdjustFrame();
};

CWndScroller::CWndScroller(CWnd &inWnd) : mSubject(inWnd)
{
mInfo.cbSize = sizeof(SCROLLINFO);
mInfo.cbSize = 0;
mInfo.fMask = 0;
mInfo.nMin = 0;
mInfo.nMax = 0;
mInfo.nPage = 0;
mInfo.nPos = 0;
mInfo.nTrackPos = 0;
}

void CWndScroller::SetScrollSizes(
const SIZE& sizeImage,
const SIZE& sizePage,
const SIZE& sizeLine)
{

// CWnd *scroll = mSubject.GetScrollBarCtrl(SB_HORZ);
// if (scroll) scroll->ModifyStyle(0, SIF_DISABLENOSCROLL, 0);
// scroll = mSubject.GetScrollBarCtrl(SB_HORZ);
// if (scroll) scroll->ModifyStyle(0, SIF_DISABLENOSCROLL, 0);

mPageSize = sizePage;
mLineSize = sizeLine;
this->ResizeImage(sizeImage);
}

void CWndScroller::ResizeImage(const SIZE& sizeImage)
{
mImageSize = sizeImage;
this->AdjustFrame();
}

void CViewScroller::AdjustFrame()
{
mInfo.fMask = SIF_RANGE;
mInfo.nMin = 0;

CRect r;
mSubject.GetWindowRect(r);

SInt32 xRange = mImageSize.cx - (r.right-r.left);
SInt32 yRange = mImageSize.cy - (r.bottom-r.top);

SInt32 xScrollWidth = xRange > 0 ? ::GetSystemMetrics(SM_CXHSCROLL) : 0;
SInt32 yScrollWidth = yRange > 0 ? ::GetSystemMetrics(SM_CYHSCROLL) : 0;

SInt32 xBorder2 = ::GetSystemMetrics(SM_CXFRAME); // 4
SInt32 yBorder2 = ::GetSystemMetrics(SM_CYFRAME);

SInt32 xTotalWidth = xRange > 0 or yScrollWidth ? xRange + yScrollWidth : 0;
SInt32 yTotalWidth = yRange > 0 or xScrollWidth ? yRange + xScrollWidth : 0;

mInfo.nMax = xTotalWidth + ( xTotalWidth ? xBorder2 : 0 );
mSubject.SetScrollInfo(SB_HORZ, &mInfo);

mInfo.nMax = yTotalWidth + ( yTotalWidth ? yBorder2 : 0 );
mSubject.SetScrollInfo(SB_VERT, &mInfo);

this->UpdateCurrentPostion();
}

void CWndScroller::AdjustFrame()
{
mInfo.fMask = SIF_RANGE;
mInfo.nMin = 0;

CRect r;
mSubject.GetWindowRect(r);

SInt32 xRange = mImageSize.cx - (r.right-r.left);
SInt32 yRange = mImageSize.cy - (r.bottom-r.top);

SInt32 hScrollHeight = ::GetSystemMetrics(SM_CYHSCROLL);
SInt32 vScrollWidth = ::GetSystemMetrics(SM_CXVSCROLL);

SCROLLINFO info;
mSubject.GetScrollInfo( SB_VERT, &info );
if ( info.nPage != 0 ) xRange += vScrollWidth;

mSubject.GetScrollInfo( SB_HORZ, &info );
if ( info.nPage != 0 ) yRange += hScrollHeight;

mInfo.nMax = xRange;
mSubject.SetScrollInfo(SB_HORZ, &mInfo);

mInfo.nMax = yRange;
mSubject.SetScrollInfo(SB_VERT, &mInfo);

this->UpdateCurrentPostion();
}

void CWndScroller::UpdateCurrentPostion()
{
mSubject.GetScrollInfo(SB_HORZ, &mInfo);
mCurrentPos.x = mInfo.nPos;
mSubject.GetScrollInfo(SB_VERT, &mInfo);
mCurrentPos.y = mInfo.nPos;
}

bool CWndScroller::OnScroll(int inBar, UInt sbCode, UInt pos, CScrollBar *bar)
{
if (bar) return false; // why should bar be null ??

mSubject.GetScrollInfo(inBar, &mInfo);
switch (inBar)
{
case SB_HORZ:
switch (sbCode)
{
case SB_LINEDOWN:
mInfo.nPos += mLineSize.cx;
if (mInfo.nPos > mImageSize.cx) mInfo.nPos = mImageSize.cx;
break;
case SB_LINEUP:
mInfo.nPos -= mLineSize.cx;
if (mInfo.nPos < 0) mInfo.nPos = 0;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
mInfo.nPos = pos;
break;
case SB_PAGEDOWN:
mInfo.nPos += mPageSize.cx;
if (mInfo.nPos > mImageSize.cx) mInfo.nPos = mImageSize.cx;
break;
case SB_PAGEUP:
mInfo.nPos -= mPageSize.cx;
if (mInfo.nPos < 0) mInfo.nPos = 0;
break;
}
mCurrentPos.x = mInfo.nPos;
break;
case SB_VERT:
switch (sbCode)
{
case SB_LINEDOWN:
mInfo.nPos += mLineSize.cy;
if (mInfo.nPos > mImageSize.cy) mInfo.nPos = mImageSize.cy;
break;
case SB_LINEUP:
mInfo.nPos -= mLineSize.cy;
if (mInfo.nPos < 0) mInfo.nPos = 0;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
mInfo.nPos = pos;
break;
case SB_PAGEDOWN:
mInfo.nPos += mPageSize.cy;
if (mInfo.nPos > mImageSize.cy) mInfo.nPos = mImageSize.cy;
break;
case SB_PAGEUP:
mInfo.nPos -= mPageSize.cy;
if (mInfo.nPos < 0) mInfo.nPos = 0;
break;
}
mCurrentPos.y = mInfo.nPos;
break;
}
return mSubject.SetScrollInfo(inBar, &mInfo);
}

void CWndScroller::OnKeyDown(UINT nChar, UINT, UINT)
{
switch (nChar)
{
case VK_HOME:
this->OnScroll(SB_VERT, SB_TOP, 0, NULL);
this->OnScroll(SB_HORZ, SB_LEFT, 0, NULL);
break;
case VK_END:
this->OnScroll(SB_VERT, SB_BOTTOM, 0, NULL);
this->OnScroll(SB_HORZ, SB_RIGHT, 0, NULL);
break;
case VK_UP:
this->OnScroll(SB_VERT, SB_LINEUP, 0, NULL);
break;
case VK_DOWN:
this->OnScroll(SB_VERT, SB_LINEDOWN, 0, NULL);
break;
case VK_PRIOR:
this->OnScroll(SB_VERT, SB_PAGEUP, 0, NULL);
break;
case VK_NEXT:
this->OnScroll(SB_VERT, SB_PAGEDOWN, 0, NULL);
break;
case VK_LEFT:
this->OnScroll(SB_HORZ, SB_LINELEFT, 0, NULL);
break;
case VK_RIGHT:
this->OnScroll(SB_HORZ, SB_LINERIGHT, 0, NULL);
break;
default:
break;
}
}

void CWndScroller::ResizeParentToFit(BOOL bShrinkOnly)
{
// adjust parent rect so client rect is appropriate size
// ASSERT(m_nMapMode != MM_NONE); // mapping mode must be known
CSize m_totalDev = mImageSize;

// determine current size of the client area as if no scrollbars present
CRect rectClient;
mSubject.GetWindowRect(rectClient);
CRect rect = rectClient;
mSubject.CalcWindowRect(rect);
rectClient.left += rectClient.left - rect.left;
rectClient.top += rectClient.top - rect.top;
rectClient.right -= rect.right - rectClient.right;
rectClient.bottom -= rect.bottom - rectClient.bottom;
rectClient.OffsetRect(-rectClient.left, -rectClient.top);
ASSERT(rectClient.left == 0 && rectClient.top == 0);

// determine desired size of the view
CRect rectView(0, 0, m_totalDev.cx, m_totalDev.cy);
if (bShrinkOnly)
{
if (rectClient.right <= m_totalDev.cx)
rectView.right = rectClient.right;
if (rectClient.bottom <= m_totalDev.cy)
rectView.bottom = rectClient.bottom;
}
mSubject.CalcWindowRect(rectView, CWnd::adjustOutside);
rectView.OffsetRect(-rectView.left, -rectView.top);
ASSERT(rectView.left == 0 && rectView.top == 0);
if (bShrinkOnly)
{
if (rectClient.right <= m_totalDev.cx)
rectView.right = rectClient.right;
if (rectClient.bottom <= m_totalDev.cy)
rectView.bottom = rectClient.bottom;
}

// dermine and set size of frame based on desired size of view
CRect rectFrame;
CFrameWnd* pFrame = mSubject.GetParentFrame();
ASSERT_VALID(pFrame);
pFrame->GetWindowRect(rectFrame);
CSize size = rectFrame.Size();
size.cx += rectView.right - rectClient.right;
size.cy += rectView.bottom - rectClient.bottom;
pFrame->SetWindowPos(NULL, 0, 0, size.cx, size.cy,
SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
}

void CWndScroller::EraseEmptyRgn()
{

CRect winRect;
mSubject.GetWindowRect(winRect);
winRect.OffsetRect(-winRect.left, -winRect.top);

Rect portRect, vertRect, horzRect;
RgnHandle vertRgn = nil;
RgnHandle horzRgn = nil;
RgnHandle finalRgn = nil;
ARectToRect(winRect, portRect);

if (mImageSize.cx < winRect.right-winRect.left)
{
::MacSetRect(&vertRect, mImageSize.cx, 0, portRect.right, portRect.bottom);
vertRgn = ::NewRgn();
::RectRgn(vertRgn, &vertRect);
finalRgn = vertRgn;
}
if (mImageSize.cy < winRect.bottom-winRect.top)
{
::MacSetRect(&horzRect, 0, mImageSize.cy, portRect.right, portRect.bottom);
horzRgn = ::NewRgn();
::RectRgn(horzRgn, &horzRect);
finalRgn = horzRgn;
}
if (vertRgn and horzRgn)
{
::MacUnionRgn(vertRgn, horzRgn, horzRgn);
}
if (finalRgn)
{
RGBColor c = {65535, 65535, 65535};
::RGBForeColor(&c);
::RGBBackColor(&c);
::EraseRgn(finalRgn);
}
if (vertRgn) ::DisposeRgn(vertRgn);
if (horzRgn) ::DisposeRgn(horzRgn);
}

// declare a view or control

class CMyWnd : public CWnd
{
public:
CMyWnd() : mScroller(*this);
protected:
CWndScroller mScroller;
// CViewScroller mScroller;
}

// these are example overrides and message mappings
// mQT is my interal representation of a QuickTime graphic
// do whatever translations you need to do

bool CMyWndMakeFit(SInt32 resizeStyle, bool inRefresh)
{
mScroller.ScrollTo(0, 0);
if (mQT) mQT->TranslateTo(0, 0);

if (not mQT) resizeStyle = resize_NoQT;
switch (resizeStyle)
{
case resize_ImageToQT:
if (mQT->Ready())
{
SDimension16 p;
mQT->GetVisualSize(p);
if (inRefresh) this->Invalidate(true);
CSize sizeTotal(p.width, p.height);
CSize sizePage(sizeTotal.cx / 2, sizeTotal.cy / 2);
CSize sizeLine(sizeTotal.cx / 50, sizeTotal.cy / 50);
mScroller.SetScrollSizes(sizeTotal, sizePage, sizeLine);
if (inRefresh) this->OnNcPaint();
return true;
}
break;
case resize_QTToView:
if (mQT->Ready())
{

return true;
}
break;
case resize_ViewToQT:
if (mQT->Ready())
{
SDimension16 p;
mQT->GetVisualSize(p);
CSize sizeTotal(p.width, p.height);
CSize sizePage(0, 0);
CSize sizeLine(0, 0);
mScroller.SetScrollSizes(sizeTotal, sizePage, sizeLine);

mScroller.ResizeParentToFit();
if (inRefresh) this->OnNcPaint();
return true;
}
break;
case resize_NoQT:
{
CSize sizeTotal(0, 0);
CSize sizePage(0, 0);
CSize sizeLine(0, 0);
mScroller.SetScrollSizes(sizeTotal, sizePage, sizeLine);
if (inRefresh) this->OnNcPaint();
return true;
}
break;
case resize_None:
if (inRefresh) this->OnNcPaint();
return true;
break;
}
return false;
}


void CMyWnd OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
mScroller.OnKeyDown(nChar, nRepCnt, nFlags);
}

void CMyWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (mScroller.OnScroll(SB_HORZ, nSBCode, nPos, pScrollBar))
{
CPoint p = mScroller.GetPosition();
if (mQT) mQT->TranslateTo(-p.x, -p.y);
this->OnNcPaint();
}
}

void CMyWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (mScroller.OnScroll(SB_VERT, nSBCode, nPos, pScrollBar))
{
CPoint p = mScroller.GetPosition();
if (mQT) mQT->TranslateTo(-p.x, -p.y);
this->OnNcPaint();
}
}

void CMyWnd::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if ((mResizeStyle == resize_ViewToQT or mResizeStyle == resize_QTToView) and mQT)
{
SDimension16 p = { cx, cy };
mQT->ChangeVisualSize(p);
CSize s(cx, cy);
mScroller.ResizeImage(s);
}
else
{
CPoint p = mScroller.GetPosition();
mScroller.AdjustFrame();
}
}





I hope this code works for you.

Dave