From: Luigino on
HI Stephen,

> What happens with
> memDC.SetMapMode(MM_TEXT);
> dc.BitBlt(0,0,r.Width(),r.Height(),&memDC,0,0,SRCCPY);
>
> ???
> Both memDC and dc are then using MM_TEXT, have the same size bitmaps, so
> this should work. Is there something going on with bSetDraw?
>
> Steve
>
> > //Swap back the original bitmap.
> > memDC.SelectObject(bOldBitmap);
> > }
>
> ...

Figured out right a bit ago.... had to do:

1) put the grid drawing BEFORE the mapping
2) adding:

memDC.SetWindowOrg(0, 0);
memDC.SetViewportOrg(0, 0);

to re-set the point origin, probably because even if setting MM_TEXT
the point origin won't be reset to (0,0)...so the right OnPaint()
structure is this:

void CGraphClass::OnPaint()
{
CPaintDC dc(this); // device context for painting

CRect r;
GetClientRect(&r);
dc.SetBkColor(RGB(0,0,0));

int saveobject = dc.SaveDC();

if(bSetDraw)
{
// ********** Background ***********
// Grid
CDC memDC;
CBitmap bBitmap; // Offscreen
bitmap
CBitmap* bOldBitmap; // bitmap
originally found in CMemDC

memDC.CreateCompatibleDC(&dc);
bBitmap.CreateCompatibleBitmap(&dc, r.right,
r.bottom);
bOldBitmap = memDC.SelectObject(&bBitmap);

memDC.FillRect(r,
CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)));

if (bActivateGrid)
{
CPen qLinePen(PS_SOLID, 1, RGB(0,139,0));
memDC.SelectObject(qLinePen);

// Grid - Horizontal lines
for(int y = 0; y < r.bottom; y += (int)12) {
/* scan y */
memDC.MoveTo(r.left, y);
memDC.LineTo(r.right,
y);
} /* scan y */

// Grid - Vertical lines
for(int x = 0 - (int)gridOffset; x <= r.right
- (int)gridOffset; x += (int)12 ) {
/* scan x */
memDC.MoveTo(x, r.top);
memDC.LineTo(x, r.bottom);
} /* scan x */
}

memDC.SetMapMode(MM_ANISOTROPIC);
memDC.SetWindowExt(-r.right, iYMaxInterval);
memDC.SetViewportExt(r.right, -r.bottom);
memDC.SetWindowOrg(r.right, 0);
memDC.SetViewportOrg(0, r.bottom);

if (vtPoints.capacity() == 1)
{
for (int i=vtPoints[0].size()-1;i>=0;i--) {
vtToDraw[0].at(i).x =
vtPoints[0].at(i).x;
vtToDraw[0].at(i).y =
( (vtPoints[0].at(i).y > 0) ? vtPoints[0].at(i).y : 86 );
}
//int savedraw = memDC.SaveDC();

CPen qPolylinePen(PS_SOLID, 1, RGB(0, 255,
0));
memDC.SelectObject(qPolylinePen);
vectfPoints* pointsline = &vtToDraw[0];
memDC.Polyline(&(*pointsline)[0],
(int)pointsline->size());
//dc.PolyPolyline()

//memDC.RestoreDC(savedraw);
}

// Copy the offscreen bitmap onto the screen.
memDC.SetMapMode(MM_TEXT);
memDC.SetWindowOrg(0, 0);
memDC.SetViewportOrg(0, 0);

// DC isn't altered about mapping!! so it should
SRCCOPY as like as the bitmap appears
dc.BitBlt(r.left, r.top, r.right, r.bottom,
&memDC, r.left, r.top,
SRCCOPY);

//Swap back the original bitmap.
memDC.SelectObject(bOldBitmap);
}
dc.RestoreDC(saveobject);
}

Now I have to implement the vertical bars which it should be a bit
easier I think... at least there's always this place where to find
hints :-)

Thanks a lot for now
Ciao
Luigi
From: Joseph M. Newcomer on
See below...
On Tue, 23 Feb 2010 09:50:52 -0800 (PST), Luigino <npuleio(a)rocketmail.com> wrote:

>HI Stephen,
>
>> What happens with
>> memDC.SetMapMode(MM_TEXT);
>> dc.BitBlt(0,0,r.Width(),r.Height(),&memDC,0,0,SRCCPY);
>>
>> ???
>> Both memDC and dc are then using MM_TEXT, have the same size bitmaps, so
>> this should work. Is there something going on with bSetDraw?
>>
>> Steve
>>
>> > //Swap back the original bitmap.
>> > memDC.SelectObject(bOldBitmap);
>> > }
>>
>> ...
>
>Figured out right a bit ago.... had to do:
>
>1) put the grid drawing BEFORE the mapping
>2) adding:
>
> memDC.SetWindowOrg(0, 0);
> memDC.SetViewportOrg(0, 0);
***
Note that you can nest SaveDC/RestoreDC. You have to retain the bitmap, so it would be
int save1 = memDC.SaveDC();
memDC.SelectObject(&bitmap);
...draw grid
int save2 = memDC.SaveDC();
...set coordinate mapping mode parameters
....do drawing
memDC.RestoreDC(save2);
... back in MM_TEXT mode with everything reset except the bitmap
dc.BitBlt(...);
memdc.RestoreDC(save1);

No need to keep resetting things one at a time. It only becomes confusing.
joe
*****
>
>to re-set the point origin, probably because even if setting MM_TEXT
>the point origin won't be reset to (0,0)...so the right OnPaint()
>structure is this:
>
>void CGraphClass::OnPaint()
>{
> CPaintDC dc(this); // device context for painting
>
> CRect r;
> GetClientRect(&r);
> dc.SetBkColor(RGB(0,0,0));
>
> int saveobject = dc.SaveDC();
>
> if(bSetDraw)
> {
> // ********** Background ***********
> // Grid
> CDC memDC;
> CBitmap bBitmap; // Offscreen
>bitmap
> CBitmap* bOldBitmap; // bitmap
>originally found in CMemDC
>
> memDC.CreateCompatibleDC(&dc);
****
int save1 = memDC.SaveDC();
****
> bBitmap.CreateCompatibleBitmap(&dc, r.right,
>r.bottom);
> bOldBitmap = memDC.SelectObject(&bBitmap);
****
No reason whatsoever to save the old bitmap. Get rid of this variable, it serves no
useful purpose. SaveDC/RestoreDC do everything you need!
****
>
> memDC.FillRect(r,
>CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)));
>
> if (bActivateGrid)
> {
****
The code below is incorrect because the destructor for the pen will try to destroy a pen
selected into the DC. So you should have
int save2 = memDC.SaveDC();
****
> CPen qLinePen(PS_SOLID, 1, RGB(0,139,0));
> memDC.SelectObject(qLinePen);
>
> // Grid - Horizontal lines
> for(int y = 0; y < r.bottom; y += (int)12) {
> /* scan y */
> memDC.MoveTo(r.left, y);
> memDC.LineTo(r.right,
>y);
> } /* scan y */
>
> // Grid - Vertical lines
> for(int x = 0 - (int)gridOffset; x <= r.right
>- (int)gridOffset; x += (int)12 ) {
> /* scan x */
> memDC.MoveTo(x, r.top);
> memDC.LineTo(x, r.bottom);
> } /* scan x */
*****
And here you need
memDC.RestoreDC(save2);
so the pen is deselected
*****
> }
>
****
{
int save3 = memDC.SaveDC();

I prefer to use braces for proper scoping
****
> memDC.SetMapMode(MM_ANISOTROPIC);
> memDC.SetWindowExt(-r.right, iYMaxInterval);
> memDC.SetViewportExt(r.right, -r.bottom);
> memDC.SetWindowOrg(r.right, 0);
> memDC.SetViewportOrg(0, r.bottom);
>
> if (vtPoints.capacity() == 1)
> {
> for (int i=vtPoints[0].size()-1;i>=0;i--) {
> vtToDraw[0].at(i).x =
>vtPoints[0].at(i).x;
> vtToDraw[0].at(i).y =
>( (vtPoints[0].at(i).y > 0) ? vtPoints[0].at(i).y : 86 );
> }
> //int savedraw = memDC.SaveDC();
>
> CPen qPolylinePen(PS_SOLID, 1, RGB(0, 255,
>0));
> memDC.SelectObject(qPolylinePen);
> vectfPoints* pointsline = &vtToDraw[0];
> memDC.Polyline(&(*pointsline)[0],
>(int)pointsline->size());
****
THis appears to be a clumsy way of saying
*pointsline
****
> //dc.PolyPolyline()
>
> //memDC.RestoreDC(savedraw);
****
Note that without the saveDC/RestoreDC you are leaking pen resources. You will run out of
GDI resources fairly soon.
****
> }
>
> // Copy the offscreen bitmap onto the screen.
****
memDC.RestoreDC(save3);
}

You keep trying to do this the hard way! Why?
****
> memDC.SetMapMode(MM_TEXT);
> memDC.SetWindowOrg(0, 0);
> memDC.SetViewportOrg(0, 0);
>
> // DC isn't altered about mapping!! so it should
>SRCCOPY as like as the bitmap appears
> dc.BitBlt(r.left, r.top, r.right, r.bottom,
> &memDC, r.left, r.top,
>SRCCOPY);
>
> //Swap back the original bitmap.
> memDC.SelectObject(bOldBitmap);
****
No need! The following code does it more cleanly:
memDC.RestoreDC(save1);

You can use my SaveDC/RestoreDC class from my MVP Tips site to automate this!
****
> }
> dc.RestoreDC(saveobject);
>}
>
>Now I have to implement the vertical bars which it should be a bit
>easier I think... at least there's always this place where to find
>hints :-)
>
>Thanks a lot for now
>Ciao
>Luigi
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Area Cinque on
HI Joe,

> ****
>          int save1 = memDC.SaveDC();
> ****>                bBitmap.CreateCompatibleBitmap(&dc, r.right,
> >r.bottom);
> >                bOldBitmap = memDC.SelectObject(&bBitmap);
>
> ****
> No reason whatsoever to save the old bitmap.  Get rid of this variable, it serves no
> useful purpose.  SaveDC/RestoreDC do everything you need!
> ****

I tried to get rid of saving old bitmap but then it doesn't show
anything... using old bitmap indeed the image is present... (I have
implemented also the SaveDC/RestoreDC stuffs)... maybe it's needed for
old bitmap?...

Thanks
Ciao
Luigi
From: Luigino on
HI Joe,

> ****
> int save1 = memDC.SaveDC();
> ****> bBitmap.CreateCompatibleBitmap(&dc, r.right,
> >r.bottom);
> > bOldBitmap = memDC.SelectObject(&bBitmap);
>
> ****
> No reason whatsoever to save the old bitmap. Get rid of this variable, it serves no
> useful purpose. SaveDC/RestoreDC do everything you need!
> ****

I tried to get rid of old bitmap but it looks like it's necessary
because without old bitmap it doesn't show anything on the form...

Thanks
Ciao
Luigi