Click here to Skip to main content
15,891,672 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
hi in my application the view is derived from CScrollView. it's usually required to redraw the view after handling user events. for removing flicker, i want to use a memory DC, so that the drawings occur on it and at last i copy it to the client area. i create the memory DC with size of the client. this causes the drawings limit to the size of the client. for example if the whole scroll view is 1000x1000 and the client size is 100x100 by scrolling the view nothing is drawn beyond rectangle (0, 0, 100, 100). i don't want to create a memory DC as big as the whole scroll view. it consumes a large amount of memory most of it is out of the visible part of it.
how can i implement it?
thx
Posted

You need to figure out (from the scroll positions) which part of your drawing is to be displayed, and then map that onto the rectangle that is physically at location [0, 0, 100, 100]. For example, if horizontal scroll is +50 and vertical scroll is +100, then you need to draw the logical picture [ 100, 50, 200, 150] onto the DC at [0, 0, 100, 100]. It's just a matter of mathematics.
 
Share this answer
 
Comments
ilostmyid2 29-Feb-12 9:38am    
when i don't use memory DC and draw directly on screen, i see that just newly exposed parts of the view are invalidated and drawn. i prefer not to change anything but the DC which drawings are done on. i like not to change the ScrollView mechanism and let it do what it thinks that is required on the memory DC instead of client DC. as u see, the client DC size is the same as memory DC which is client size. i tried to override OnPaint and call OnPrepareDC for the memory DC instead of paint DC. after all drawings made on the memory DC, then by using a BitBlt i tried to copy the result onto the client. look at the code below:
void Ct2View::OnPaint()
{
CPaintDC dc(this);
CDC *pDC = d_bAvoidFlicker ? &d_memDC : &dc;
OnPrepareDC(pDC);

OnDraw(pDC);

if (d_bAvoidFlicker)
dc.BitBlt(0, 0, d_clientSize.cx, d_clientSize.cy, pDC, 0, 0, SRCCOPY);
}
but it didn't result to a proper drawing.
Richard MacCutchan 29-Feb-12 10:04am    
Yes, but what happens in your OnDraw() function? That is where you have to decide which part of your image must be drawn, based on the position of your two scrollbars.
ilostmyid2 29-Feb-12 10:10am    
here's the code:

void Ct2View::pr_getItemLeftTopCorner(CPoint &p, int col, int row)
{
p.x = d_margin.left + col * (CMainFrame::itemSize.cx + d_gap.cx);
p.y = d_margin.top + row * (CMainFrame::itemSize.cy + d_gap.cy);
}

void Ct2View::pr_drawItem(CDC *pDC, int col, int row)
{
CPoint p;
pr_getItemLeftTopCorner(p, col, row);

if (d_pItemsProperties[row][col])
{
d_pItemsProperties[row][col]->drawItemInMemory();
pDC->BitBlt(p.x, p.y, CMainFrame::itemSize.cx, CMainFrame::itemSize.cy, &CMainFrame::tmpDC, 0, 0, SRCCOPY);
}
else
{
CPen pen(PS_DOT, 1, RGB(255,255,255));
CPen *pOldPen = pDC->SelectObject(&pen);
pDC->SelectStockObject(BLACK_BRUSH);
pDC->SetBkColor(BLACK);
CRect r(p, CMainFrame::itemSize);
pDC->Rectangle(r);
CString s;
s.Format(_T("(%d, %d)"), col, row);
CSize sz = pDC->GetTextExtent(s);
pDC->SetTextColor(RGB(255,0,0));
pDC->TextOut(r.left + (CMainFrame::itemSize.cx - sz.cx)/2, r.top + (CMainFrame::itemSize.cy - sz.cy)/2, s);
pDC->SelectObject(pOldPen);
}
}

void Ct2View::pr_drawSelRect(CDC *pDC)
{
CPoint p;
CRect r;

pr_getItemLeftTopCorner(p, d_curCol, d_curRow);
r = CRect(p, CMainFrame::itemSize);
r.InflateRect(5, 5);

pDC->SelectStockObject(NULL_BRUSH); // not to draw inside of rect
pDC->SetBkColor(BLACK); // ta ino nazanim pen-emun dotted nemisheh!
CPen pen(PS_DOT, 1, WHITE);
CPen *pOldPen = pDC->SelectObject(&pen);

pDC->Rectangle(r);

pDC->SelectObject(pOldPen);
}

void Ct2View::OnDraw(CDC* pDC)
{
for (int j=0; j < d_numRows; j++)
for (int i=0; i < d_numCols; i++)
pr_drawItem(pDC, i, j);
pr_drawSelRect(pDC);
}

Richard MacCutchan 29-Feb-12 10:22am    
Fine, not that I can be expected to figure out quite what it's doing. But, I ask again, where do you make adjustments for the current scroll position? For example if you wish to draw a line across the client area that is 200 pixels wide and you have scrolled the window right 80 pixels, and the client is 100 pixels wide, then you need to draw from logical point 81 to 180.
ilostmyid2 29-Feb-12 10:38am    
i think this is the art of ScrollView that accepts responsibility of locations of things which are drawn inside the scroll view. everything gets ok when i put my code in OnDraw instead of OnPaint. all adjustments get true when it calls OnPrepareDC. then i may suppose that i'm going to draw the whole view which begins from the left top corner of the client area and is wide and high enough to hold the whole content. i may forget scrollbars and forget that the content may be scrolled. as u see in the code, i've not to worry about the scroll position. i just draw and the ScrollView handles the remainder.
it is usually like this
1. create a source dc which contains the original thing to draw(bitmap,shape or whatever)
2. depends upon your scroll bar position, use BitBlt function to copy the required amount of pixels from source DC to your client dc(whose size is GetClientRect)..

hopes this will help you somewhat.

jkchan
http://cgmath.blogspot.com
 
Share this answer
 
Comments
ilostmyid2 29-Feb-12 9:33am    
source DC is the memory DC which size is GetClientRect, so the amount of pixels is not dependent to the scroll position. as i said, i'm not going to make the whole DC.
jk chan 29-Feb-12 23:25pm    
you need to create a source dc same size as of the thing to draw.. i don't think creating 1000x1000 size dc will affect the perfomance..

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900