Peter Ritchie Inc. Software Consulting Co. Home
      Downloads    General    .NET Topics    C++ Topics    C# Topics

Home
Products & Services
Articles/Blog
Downloads
Links
Members Only
Support
Contact
Login
Register
Defect in MFC CDC::DPtoLP(LPSIZE) and CDC::LPtoDP(LPSIZE)

Posted by on Monday, November 28, 2005 (EST)

Description of a bug in MFC's CDC::DPtoLP(LPSIZE) and CDC::LPtoDP(LPSIZE)

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.

 


Average Rating:

Comments:

haha
By synercard on Friday, December 09, 2005 (EST)

Very good topic. I think that might be one of the reasons I used WViewMap instead.

By the way, this can be a very handy website. And I surprisedly noticed that this window I am typing inside is very well designed and RichText enabled

Reply to this Comment

Add Your Comment

Advertisement
Seek Truth

RSS Feed Temporarily Unavailable
Feed will retried at 8/28/2008 4:48:18 PM
Last Refreshed 8/28/2008 9:03:41 AM

 
Copyright © 2005, Peter A. Ritchie All rights reserved