Problema ScrollBar

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
Post Reply
carrera
Junior
Junior
Posts: 38
Joined: 23 Aug 2007, 12:06

Problema ScrollBar

Post by carrera » 30 Mar 2012, 10:24

Va salut, as avea nevoie de un sfat:

-Se da o aplicatie tip MDI in care incarc o imagine dintr-un fisier, imaginea deschizandu-se intr-o fereastra child.
-Am facut ca imaginea sa se deschida/pastreze tot timpul centrata pe mijlocul ferestrei child cind fereastra se redimensioneaza, iar cand dimensiunea ferestrei este mai mica ca imaginea, am facut sa apara scrollbar-ul vertical/orizontal, iar aceste scrollbar-uri vor apare de asemeni centrate pe mijlocul ferestrei din cauza ca si imaginea va fi tot pe mijloc.
-Problema e ca atunci cand fac scroll imaginea nu-si mai face update, apar niste linii in locul unde ar trebui sa apara imaginea scroll-ata.Am incercat eu sa-i fac niste update-uri la imagine dar fara efect.Am atasat si-o imagine in sensul asta + niste bucati de cod mai reprezentativ din clasa Child.

Merci.

Code: Select all

void CChildFrame::OnSize(UINT u, int x, int y)
{

	CMDIChildWnd::OnSize(u, x, y);

	cx = x;
	cy = y;


	m_nViewWidth = CImageEditorDoc::x;
	m_nViewHeight = CImageEditorDoc::y;

	//////////////////////////
	//////////////////////////
	//
// Set the horizontal scrolling parameters.
//
	int nHScrollMax = 0;
	m_nHScrollPos = m_nHPageSize = 0;

	if (cx < m_nViewWidth) 
	{
		nHScrollMax = m_nViewWidth - 1;
		m_nHPageSize = cx;
		m_nHScrollPos = /*min (m_nHScrollPos,*/ (m_nViewWidth - m_nHPageSize - 1) / 2;
    }

	SCROLLINFO si;
	si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
	si.nMin = 0;
	si.nMax = nHScrollMax;
	si.nPos = m_nHScrollPos;
	si.nPage = m_nHPageSize;

	SetScrollInfo (SB_HORZ, &si, TRUE);

	//
	// Set the vertical scrolling parameters.
	//
	int nVScrollMax = 0;
	m_nVScrollPos = m_nVPageSize = 0;

	if (cy < m_nViewHeight) 
	{ //if the client area height is less than the workspace height then execute
		nVScrollMax = m_nViewHeight - 1;
		m_nVPageSize = cy; // sets VPageSize to the client areas height
		m_nVScrollPos = /*min (m_nVScrollPos,*/ (m_nViewHeight - m_nVPageSize - 1) / 2;
	}

	si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
	si.nMin = 0;
	si.nMax = nVScrollMax;    
	si.nPos = m_nVScrollPos;
	si.nPage = m_nVPageSize;

	SetScrollInfo (SB_VERT, &si, TRUE);
	
}

void CChildFrame::OnPaint () // this is the paint command.
{
	CPaintDC dc (this); // creates a paint device context.

	dc.UpdateColors();

/*	dc.SetWindowOrg (m_nHScrollPos, m_nVScrollPos);
	
	CBrush brush (HS_DIAGCROSS, RGB (255,0,0)); // sets the criscrosses to bright red.
	dc.SelectObject (&brush); //selects the brush into the DC (device context)
	dc.SetBkColor (RGB (0,0,0)); // sets the background color to BLACK
	dc.Rectangle (0,0,300,300);//Draws a rectangle that is 10000 by 10000
*/
}

void CChildFrame::OnHScroll (UINT nCode, UINT nPos, CScrollBar* pScrollBar)
{
	int nDelta;

//
// Compute the horizontal scroll distance, or "delta."
//
	switch (nCode) {

	case SB_LINELEFT:
	nDelta = -LINESIZE;
	break;

	case SB_PAGELEFT:
	nDelta = -m_nHPageSize;
	break;

	case SB_THUMBTRACK:
	nDelta = (int) nPos - m_nHScrollPos;
	break;

	case SB_PAGERIGHT:
	nDelta = m_nHPageSize;
	break;

	case SB_LINERIGHT:
	nDelta = LINESIZE;
	break;

	default: // Ignore other scroll bar messages
	return;
}

//
// Adjust the delta if adding it to the current scroll position would
// cause an underrun or overrun.
//
	int nScrollPos = m_nHScrollPos + nDelta;
	int nMaxPos = m_nViewWidth - m_nHPageSize;

	if (nScrollPos < 0)
		nDelta = -m_nHScrollPos;
	else if (nScrollPos > nMaxPos)
		nDelta = nMaxPos - m_nHScrollPos;

//
// Update the scroll position and scroll the window.
//
	if (nDelta != 0) 
	{
		m_nHScrollPos += nDelta;
		SetScrollPos (SB_HORZ, m_nHScrollPos, TRUE);
		ScrollWindow (-nDelta, 0);
	}
}


//************************************************************************
//************************************************************************
//************************************************************************


void CChildFrame::OnVScroll (UINT nCode, UINT nPos, CScrollBar* pScrollBar)
{
	int nDelta;

//
// Compute the vertical scroll distance, or "delta."
//
	switch (nCode) {

	case SB_LINEUP:
	nDelta = -LINESIZE;
	break;

	case SB_PAGEUP:
	nDelta = -m_nVPageSize;
	break;

	case SB_THUMBTRACK:
	nDelta = (int) nPos - m_nVScrollPos;
	break;

	case SB_PAGEDOWN:
	nDelta = m_nVPageSize;
	break;

	case SB_LINEDOWN:
	nDelta = LINESIZE;
	break;

	default: // Ignore other scroll bar messages
	return;
}

//
// Adjust the delta if adding it to the current scroll position would
// cause an underrun or overrun.
//	
	int nScrollPos = m_nVScrollPos + nDelta;
	int nMaxPos = m_nViewHeight - m_nVPageSize;

	if (nScrollPos < 0)
		nDelta = -m_nVScrollPos;
	else if (nScrollPos > nMaxPos)
		nDelta = nMaxPos - m_nVScrollPos;

//
// Update the scroll position and scroll the window.
//
	if (nDelta != 0)
	    {
			m_nVScrollPos += nDelta;
			SetScrollPos (SB_VERT, m_nVScrollPos, TRUE);
			ScrollWindow (0, -nDelta);
		}
}
Attachments
Untitled.jpg
Untitled.jpg (160.27 KiB) Viewed 6425 times



User avatar
bu7ch3r
Membru++
Membru++
Posts: 326
Joined: 17 May 2011, 15:17
Judet: Iaşi
Location: Sofia
Contact:

Re: Problema ScrollBar

Post by bu7ch3r » 30 Mar 2012, 21:08

Baga si tu cate un Invalidate() peste tot vezi care-i treaba :)
Cu stima,
Lupu Claudiu

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Problema ScrollBar

Post by Ovidiu Cucu » 30 Mar 2012, 21:41

Nu e bine ce faci.
Intr-o arhitectura SDI/MDI, de desenat si de scroll se ocupa view-ul si nu frame-ul.
In plus, daca derivezi din CScrollView, nu mai e nevoie nevoie sa-l faci tu la mana pe WM_HSCROLL/WM_VSCROLL.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Problema ScrollBar

Post by Ovidiu Cucu » 01 Apr 2012, 08:27

Gasesti aici un viewer de imagini MDI, simplificat la maximum. Trage un ochi la CSimpleImageViewerView::OnUpdate ca sa observi ca tot ce trebuie sa faci cu privire la scroll este sa apelezi SetScrollSizes in functie de dimensiunile imaginii.
Vezi si CScrollView::SetScrollSizes in MSDN.
SimpleImageViewer.zip
(29.05 KiB) Downloaded 301 times

carrera
Junior
Junior
Posts: 38
Joined: 23 Aug 2007, 12:06

Re: Problema ScrollBar

Post by carrera » 01 Apr 2012, 22:29

Merci de ajutor, Ovidiu.

Problema ar fi rezolvata pe jumatate, am lucrat putin pe exemplul tau, insa atunci cind fac resize la fereastra child imaginea se duce intr-o parte si nu ramane centrata pe mijloc - desi scroll-ul ramane pe mijloc, asa cum ma intereseaza.Cred ca prin OnSize() ar fi ceva de modificat dar nu-mi dau seama ce.
Vreo idee?

Thx.

ps: Am atasat exemplul modificat.
Attachments
SimpleImageViewer.rar
(40.52 KiB) Downloaded 276 times

User avatar
bu7ch3r
Membru++
Membru++
Posts: 326
Joined: 17 May 2011, 15:17
Judet: Iaşi
Location: Sofia
Contact:

Re: Problema ScrollBar

Post by bu7ch3r » 02 Apr 2012, 00:32

Nici desenarea nu tre s-o faci tu :) Ai si niste flick-aieli...

Code: Select all

void CSimpleImageViewerView::OnDraw(CDC* pDC)
{
	CSimpleImageViewerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

   CImage& img = pDoc->m_img;
   if(!img.IsNull())
   {
      img.Draw(pDC->GetSafeHdc(), 0,0);//(cx - pDoc->m_img.GetWidth())  , (cy - pDoc->m_img.GetHeight()) );//:)
	   //img.BitBlt(pDC->GetSafeHdc(), (cx - pDoc->m_img.GetWidth()) , (cy - pDoc->m_img.GetHeight()));
   }
}
Cu stima,
Lupu Claudiu

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Problema ScrollBar

Post by Ovidiu Cucu » 02 Apr 2012, 13:02

Ai reusit si-ai pus din nou scroll-ul pe chituci, de data asta pe OnSize.
Cum am mai spus, CScrollView e o clasa minunata care face mai tot ce tine de scroll si nu trebuie sa te bagi dedesubt.

No problem, sa reluam...
  1. Chemi CScrollView::SetScrollSizes pe OnUpdate ca sa-i spui care-s dimensiunile imaginii (de fapt ale view-ului virtual).
  2. Daca vrei sa faci fit la frame pe dimensiunea imaginii chemi CScrollView::ResizeParentToFit.
  3. Daca vrei sa centrezi imaginea in zona client, te duci in OnSize si calculezi coordonatele, pe care le folosesti mai apoi in OnDraw.
  4. Daca vrei sa scapi de fickaiala la resize, mapezi WM_ERASEBKGND iar in OnEraseBkgnd dai cu bidineaua doar in spatiile de langa imagine (daca sunt).
Cam atat pentru un viewer simplu. Daca derivezi din CScrollView, nu e nevoie sa faci scroll "la mana" (dupa cum banui ca ai vazut prin unele "tutoriale").
Doar daca ai de-a face cu dimensiuni mai mari decat 65535 pe 65535 ceea ce uzual, nu e cazul. Ia-o usurel mai intai. ;)

Vezi demo-ul atasat.
SimpleImageViewer (2).zip
(30.1 KiB) Downloaded 321 times

carrera
Junior
Junior
Posts: 38
Joined: 23 Aug 2007, 12:06

Re: Problema ScrollBar

Post by carrera » 03 Apr 2012, 21:05

S-a rezolvat.
Ovidiu, esti de mare ajutor pe aici ;)

Thx again.

Post Reply