Re: Scaling of data into dc



Joseph M. Newcomer schrieb:
See below...
On Sun, 13 May 2007 12:18:03 +0200, Matthias Pospiech <matthiaspospiech@xxxxxxxx> wrote:

Joseph M. Newcomer schrieb:
This is a completely wrong approach. Use SetViewportExt/SetWindowExt to accomplish this.
Otherwise, you end up scaling the bitmap which gets really lousy representation for the
graphics.

I tried to implement the scaling with SetViewportExt/SetWindowExt.

That however worked only partly

- What is the difference between the two ?
****
One sets the specificaiton of the size of the viwport and one sets the specification of
the size the window. The ratio of the two provides the mapping between physical and
logical coordinates. RTM.
****
Well, I understand the sizing of the viewport, but sizing of the window does not resize the window, so what does is resize it then ?
Maybe the concept is just confusing to me - I know the one from VB6 which has a scale property of a window which I thought is what the viewport does. But that is not the most important part of my problem...

- I changed in CMemDC.h the lines

SetMapMode(pDC->GetMapMode());
SetWindowExt(pDC->GetWindowExt());
SetViewportExt(pDC->GetViewportExt());

to

SetMapMode(MM_ANISOTROPIC);
SetWindowExt(CSize(m_rect_dest.Width(), m_rect_dest.Height()));
SetViewportExt(CSize(m_rect_source.Width(), m_rect_source.Height()));
*****
You have not specified what pDC is. Note that you would apply the mapping mode to EITHER
the MemDC or the actual DC, but not both, because then the two mapping modes compound each
other.
Clearly.
I do apply these commands to the dc of MemDC (so it is inside the MemDC class), and not to the dc of the window like it is done in your example, see also code at the end.

If you feel the compulsion to use the intermediate memory DC, then you would apply
it there, although it appeared that the only reason you were doing this is so you could do
a StretchBlt,
No that is not the reason. I use CMemDC because it does the double buffering I need. The StretchBlt was implemented by myself as my first approach, but as I had written I changed it back to its original state with BitBlt, so below.


and changed from StrechBlt to BitBlt again, because I do not want to mix two differend streching ways.
****
Yes, that's right. It is not clear you even need the extra MemDC and the BitBlt, unless
you have other reasons for doing this
*****
BitBlt is necessary for the double buffering.

The generated bitmap is now scaled, BUT

- only the size of the data (if smaller the the dc size) is invalidated/shown, although the UpdatePlot invalidates the whole area:
*****
This is probably caused by the apparent rescaling of the original DC. Scale only one.
I only scale the dc applied to MemDC by
SetViewportExt(CSize(m_rect_source.Width(), m_rect_source.Height()));

There appears no other scaling.

*****
Scale only the one you are drawing into. The MemDC needs to have the same dimensions as
the target window.
I thought is would be doing that already, if not I do not see where.

Here more code to make clear what I do:


------------ Painting in the overloaded CStatic Class
void CGraphCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting

CRect (rc_dest);
rc_dest=GetSize();

CRect (rc_source);
rc_source=GetPlotDataSize();

CMemDC pDC(&dc,&rc_source, &rc_dest); // Double Buffering

PlotToDC(& pDC);
}
------------ Painting the data
void CGraphCtrl::PlotToDC(CMemDC* pDC)
{
COLORREF c;
if ((m_PixelNumberX>0) && (m_PixelNumberY > 0))
{
for (int ix=0; ix < m_PixelNumberX; ix++)
{
for (int iy=0; iy < m_PixelNumberY; iy++)
{
c=PlotData[ix][iy];
pDC->SetPixel(ix,iy,c);
}
}
}
}
-------------- Sizes
CRect CGraphCtrl::GetSize()
{
CRect rc;
GetClientRect(rc);
return rc;
}
--------------
CRect CGraphCtrl::GetPlotDataSize() // Size of dataarray to be plotted
{
CRect rc(0,0,m_PixelNumberX, m_PixelNumberY);
return rc;
}
-------------- Update
void CGraphCtrl::UpdatePlot()
{
Invalidate();
UpdateWindow();
}
============== MemDC class
class CMemDC : public CDC {
private:
CBitmap m_bitmap; // Offscreen bitmap
CBitmap* m_oldBitmap; // bitmap originally found in CMemDC
CDC* m_pDC; // Saves CDC passed in constructor
CRect m_rect_dest; // Rectangle of drawing area.
CRect m_rect_source; // Rectangle of source area.
BOOL m_bMemDC; // TRUE if CDC really is a Memory DC.
public:

CMemDC(CDC* pDC, const CRect* pSourceRect = NULL, const CRect* pDestRect = NULL) : CDC()
{
ASSERT(pDC != NULL);

// Some initialization
m_pDC = pDC;
m_oldBitmap = NULL;
m_bMemDC = !pDC->IsPrinting();

// Get the rectangle to draw
if (pDestRect == NULL) {
pDC->GetClipBox(&m_rect_dest);
} else {
m_rect_dest = *pDestRect;
}
// Get the rectangle to draw
if (pSourceRect == NULL) {
pDC->GetClipBox(&m_rect_source);
} else {
m_rect_source = *pSourceRect;
}

if (m_bMemDC) {
// Create a Memory DC
CreateCompatibleDC(pDC);
pDC->LPtoDP(&m_rect_dest);

m_bitmap.CreateCompatibleBitmap(pDC, m_rect_dest.Width(), m_rect_dest.Height());
m_oldBitmap = SelectObject(&m_bitmap);

//SetMapMode(pDC->GetMapMode());
SetMapMode(MM_ANISOTROPIC);

//SetWindowExt(pDC->GetWindowExt());
//SetViewportExt(pDC->GetViewportExt());
SetWindowExt(CSize(m_rect_dest.Width(), m_rect_dest.Height()));
SetViewportExt(CSize(m_rect_source.Width(), m_rect_source.Height()));



pDC->DPtoLP(&m_rect_dest);
SetWindowOrg(m_rect_dest.left, m_rect_dest.top);
} else {
// Make a copy of the relevent parts of the current DC for printing
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}

// Fill background
FillSolidRect(m_rect_dest, pDC->GetBkColor());
}

~CMemDC()
{
if (m_bMemDC) {
//m_pDC->StretchBlt(
// m_rect_dest.left, // x-coord of destination upper-left corner
// m_rect_dest.top, // y-coord of destination upper-left corner
// m_rect_dest.Width(), // width of destination rectangle
// m_rect_dest.Height(), // height of destination rectangle
// this, // handle to source DC
// 0, // x-coord of source upper-left corner
// 0, // y-coord of source upper-left corner
// m_rect_source.Width(), // width of source rectangle
// m_rect_source.Height(), // height of source rectangle
// SRCCOPY);

m_pDC->BitBlt(
m_rect_dest.left, // x-coord of destination upper-left corner
m_rect_dest.top, // y-coord of destination upper-left corner
m_rect_dest.Width(), // width of destination rectangle
m_rect_dest.Height(), // height of destination rectangle
this,
m_rect_dest.left, // x-coord of destination upper-left corner
m_rect_dest.top, // y-coord of destination upper-left corner
SRCCOPY);


//Swap back the original bitmap.
SelectObject(m_oldBitmap);
} else {
// All we need to do is replace the DC with an illegal value,
// this keeps us from accidently deleting the handles associated with
// the CDC that was passed to the constructor.
m_hDC = m_hAttribDC = NULL;
}
}

// Allow usage as a pointer
CMemDC* operator->()
{
return this;
}

// Allow usage as a pointer
operator CMemDC*()
{
return this;
}
};

.



Relevant Pages

  • Re: Scaling of data into dc
    ... class), and not to the dc of the window like it is done in your example, see also code at the end. ... pDC inside CMemDC is the memoryDC, wheras m_pDC is the dc of the window. ... scale and scale to larger logical values. ... CMemDC(CDC* pDC, const CRect* pSourceRect = NULL, const CRect* pDestRect = NULL): ...
    (microsoft.public.vc.mfc)
  • Re: resize SDI Application Flickers
    ... and 'freeze" all updates to the window until everything is in place. ... CRect r; ... What it *represents* is a null pointer or null handle. ... Do eliminate the flicker, you can handle the WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE messages ...
    (microsoft.public.vc.mfc)
  • Re: resize SDI Application Flickers
    ... and 'freeze" all updates to the window until everything is in place. ... CRect r; ... What it *represents* is a null pointer or null handle. ... Do eliminate the flicker, you can handle the WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE messages ...
    (microsoft.public.vc.mfc)
  • Re: resize SDI Application Flickers
    ... window is not properly invalidated. ... CRect r; ... What it *represents* is a null pointer or null handle. ... Multi-line CEdit Control on it for performing resizing on these items. ...
    (microsoft.public.vc.mfc)
  • Re: resize SDI Application Flickers
    ... window is not properly invalidated. ... CRect r; ... What it *represents* is a null pointer or null handle. ... Multi-line CEdit Control on it for performing resizing on these items. ...
    (microsoft.public.vc.mfc)