views:

140

answers:

0

I'm developing an application in MSVC++ 2003 (not using .Net at all) it's an older application uses GDI primarily. A lot of our function prototypes include a reference or pointer to a deviceContext in the parameter list. I figured that within any of those functions I can create a Grpahics object using Graphics.FromHDC(dc) and draw my shapes and such.

However, what used to render correctly using GDI now demonstrates some interesting artifacts. For example, we have a some polygons of odd shapes that we display and can zoom into or out of as the user desires. In the old code (GDI) we could zoom such that part of a polygon would be off screen and the visible part of the polygon was still rendered correctly. With GDI+ we are seeing the object as expected when it is completely within the viewable part of the window but when we zoom in and one or more points go off screen those points aren't used to create the shape anymore. So a rectangle looks fine within view, but if one of the corner points goes off screen then the remaining three points are drawn as a triangle.

At first i thought this was a clipping issue, but testing showed that if the clipping region were set such that anything within 200 pixels of the border was clipping the shapes are clipped as expected. This is very frustrating and I want to know what I'm doing wrong here.

The following code bytes are the old (works properly) and the new (does not work properly, as described above) both sections will take the geo points of an object (defining a shape) and convert them to screen coords then draw the polygon to the screen.

Old GDI:

const std::vector<RefPtr<Feature::SpatialObject> >& spatials = object.getSpatials();
 if (spatials.size() <= 0)
  return;

 int penColour = (selection)?RGB(255,0,0):m_penColour;
 int brushColour = (selection)?RGB(255,0,0):m_brushColour;

 int penWidth = m_penWidth;
 int brushStyle = m_brushStyle;
    int penStyle = m_penStyle;

    this->getCustomSettings(object,brushColour,brushStyle,penWidth,penColour);

 // get the colour from the object
    if (!selection)
 {
  if (brushStyle == BS_NULL || (object.getClassification() != Feature::FC_POLYGON || 
            Feature::isComposite(object.getClassification())))
   penColour = brushColour;
 }

    // get settings from the lookup table
    if (m_lookupTable.ptr() != NULL)
    {
        StyleLookupTable::StyleRecord* record = m_lookupTable->lookup(object);
        if (record)
        {
            penColour = record->m_lineColour;
            penWidth = record->m_lineWidth;
            penStyle = record->m_lineStyle;

            brushColour = (selection)?RGB(255,0,0):record->m_fillColour;
            brushStyle = record->m_fillStyle;
        }
    }

 if (FeatureRender::drawWireFrameQuery())
  brushStyle = BS_NULL;

    // Create a geometric pen.
    LOGBRUSH logBrush;
    logBrush.lbStyle = BS_SOLID;
    logBrush.lbColor = penColour;
    CPen pen(PS_GEOMETRIC|penStyle, penWidth, &logBrush);
    CPen* oldPen = displayContext.SelectObject(&pen);

 LOGBRUSH br;
 br.lbStyle = brushStyle;
 br.lbColor = brushColour;
    if (brushStyle == BS_HATCHED)
        br.lbHatch = HS_DIAGCROSS;

 CBrush brush;
 brush.Attach(CreateBrushIndirect(&br));

 CBrush* oldBrush = displayContext.SelectObject(&brush);

 int i = 0;
 CPoint* pts = static_cast<CPoint*>(malloc(sizeof(CPoint)* spatials.size()));
 std::vector<RefPtr<Feature::SpatialObject> >::const_iterator pos = spatials.begin();
 while (pos != spatials.end())
 {
  this->getScreenPosition((*pos)->getLongitude(),(*pos)->getLatitude(),pts[i++],
        featureProjection,displayProj,projectionCover,wndRect);

  pos++;
 }


    displayContext.Polygon(pts,(int)spatials.size());

 displayContext.SelectObject(oldPen);
 displayContext.SelectObject(oldBrush);

 free(pts);

New GDI+:

 // Get the spatials belonging to the object
 const std::vector<RefPtr<Feature::SpatialObject> >& spatials = object.getSpatials();
 if (spatials.size() <= 0)
  return;

 // make a graphics object
 Graphics myGraphics(displayContext);
 myGraphics.SetSmoothingMode(SmoothingModeAntiAlias);

 // get colors
 int penColour = (selection)?RGB(255,0,0):m_penColour;
 int brushColour = (selection)?RGB(255,0,0):m_brushColour;

 int penWidth = m_penWidth;
 int brushStyle = m_brushStyle;
    int penStyle = m_penStyle;

 this->getCustomSettings(object,brushColour,brushStyle,penWidth,penColour);

 // get the colour from the object
    if (!selection)
 {
  if (brushStyle == BS_NULL || (object.getClassification() != Feature::FC_POLYGON || 
            Feature::isComposite(object.getClassification())))
   penColour = brushColour;
 }

    // get settings from the lookup table
    if (m_lookupTable.ptr() != NULL)
    {
        StyleLookupTable::StyleRecord* record = m_lookupTable->lookup(object);
        if (record)
        {
            penColour = record->m_lineColour;
            penWidth = record->m_lineWidth;
            penStyle = record->m_lineStyle;

            brushColour = (selection)?RGB(255,0,0):record->m_fillColour;
            brushStyle = record->m_fillStyle;
        }
    }
 if (FeatureRender::drawWireFrameQuery())
  brushStyle = BS_NULL;

 // Create a Pen object
 Color penColor;
 if (this->getTranslucency() == 0)
 {
  penColor.SetFromCOLORREF(penColour);
 }
 else
 {
  BYTE aVal = (BYTE)(255 - (this->getTranslucency()/100.00)*255);
  BYTE rVal = GetRValue(penColour);
  BYTE gVal = GetGValue(penColour);
  BYTE bVal = GetBValue(penColour);
  penColor.SetValue(Color::MakeARGB(aVal,rVal,gVal,bVal));
 }
 Pen pen(penColor,(REAL)penWidth);

 // Create Brush object
 Color brushColor;
 if (this->getTranslucency() == 0)
 {
  brushColor.SetFromCOLORREF(brushColour);
 }
 else
 {
  BYTE aVal = (BYTE)(255 - (this->getTranslucency()/100.00)*255);
  BYTE rVal = GetRValue(brushColour);
  BYTE gVal = GetGValue(brushColour);
  BYTE bVal = GetBValue(brushColour);
  brushColor.SetValue(Color::MakeARGB(aVal,rVal,gVal,bVal));
 }
 HatchBrush brush(HatchStyleCross,brushColor,brushColor);

 // Get spatials from the feature object
 int i = 0, xVal, yVal;
 PointF* pts = static_cast<PointF*>(malloc(sizeof(PointF)* spatials.size()));
 std::vector<RefPtr<Feature::SpatialObject> >::const_iterator pos = spatials.begin();
 while (pos != spatials.end())
 {
  this->getScreenPosition((*pos)->getLongitude(),(*pos)->getLatitude(),xVal,yVal,
        featureProjection,displayProj,projectionCover,wndRect);
  pts[i].X = (REAL)xVal;
  pts[i].Y = (REAL)yVal;
  pos++;
  i++;
 }

 // Draw Polygon object
 myGraphics.DrawPolygon(&pen,pts,(int)spatials.size());
 if (brushStyle != BS_NULL)
  myGraphics.FillPolygon(&brush,pts,(int)spatials.size());

 myGraphics.SetSmoothingMode(SmoothingModeDefault);

 free(pts);