Re: Scaling of data into dc
Joseph M. Newcomer schrieb:
See below...
On Sun, 13 May 2007 12:18:03 +0200, Matthias Pospiech <matthiaspospiech@arcor.de> 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;
}
};