I ran across a defect in MFC when dealing with the following functions: CDC::DPtoLP(LPSIZE) and CDC::LPtoDP(LPSIZE). Unlike the other logical-to-device and device-to-logical conversion functions in CDC, these do not delgate to the system functions DPtoLP(HDC, LPPOINT, int) and LPtoDP(HDC, LPPOINT, int), respectively. These two functions assume that logical coordinates are only scaled (zoomed) and/or offset (offsets don't apply to size). The size is manually calculated via the ratio between the Window extent and the Viewport extent. CDC::LPtoDP(LPSIZE), for example, calculates the device size from the logical size as follows:
CSize sizeWinExt = GetWindowExt();
CSize sizeVpExt = GetViewportExt();
lpSize->cx = MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx));
lpSize->cy = MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy));
If the DC has been scaled, skewed, rotated, or reflected via a call the the SDK functions SetWorldTransform() or ModifyWorldTransform(), then CDC::DPtoLP(LPSIZE) and CDC::LPtoDP(LPSIZE) result in incorrect values.
To workaround the problem use the following class:
class CDCRepaired : public CDC
{
public:
virtual ~CDCRepaired()
{
Detach();
}
CDCRepaired(const CDC & rhs)
{
Attach(rhs.GetSafeHdc());
SetAttribDC(rhs.m_hAttribDC);
}
CDCRepaired(const CDC * const rhs)
{
Attach(rhs->GetSafeHdc());
SetAttribDC(rhs->m_hAttribDC);
}
public:
const CDCRepaired & operator=(const CDC & rhs)
{
if(&rhs != this)
{
Attach(rhs.GetSafeHdc());
SetAttribDC(rhs.m_hAttribDC);
}
return *this;
}
const CDCRepaired & operator=(const CDC * const rhs)
{
if(rhs != this)
{
Attach(rhs->GetSafeHdc());
SetAttribDC(rhs->m_hAttribDC);
}
return *this;
}
// LPtoDP and DPtoLP repairs
public:
using CDC::LPtoDP; // make the other forms of LPtoDP available in our class
using CDC::DPtoLP; // make the other forms of DPtoLP available in our class
public:
void LPtoDP(LPSIZE const lpSize)
{
CRect rectangle(CPoint(0,0), *lpSize);
LPtoDP(&rectangle);
*lpSize = rectangle.Size();
}
void DPtoLP(LPSIZE const lpSize)
{
CRect rectangle(CPoint(0,0), *lpSize);
DPtoLP(&rectangle);
*lpSize = rectangle.Size();
}
};
... which can be used as follows:
CDC * pDC;
// ...
CSize size(10,10);
((CRepairedDC *)pDC)->DPtoLP(&size);
// ...
I've logged the problem with the MSDN Product Feedback Center, and it can be voted upon by clicking this link: here.