Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm trying to create images from symbols so that I can create a custom symbol dialog. Found this sample code on the ESRI forums and it workes great on almost all symbols. I'm having problems with a IMultiLayerFillSymbol that has a IPictureFillSymbol on one of it's layers. It's throwing an exception on symbol.Draw(geometry);

Does anyone know if there is any additional steps that has to taken to get it to work with a IMultiLayerFillSymbol?

static public Image ImageFromSymbol(ISymbol symbol, Int32 width, Int32 height)
{
    try
    {
        Bitmap bitmap = new Bitmap(width, height);
        Graphics g = Graphics.FromImage(bitmap);
        IntPtr hdc = g.GetHdc();

        IGeometry geometry = null;
        if (symbol is IMarkerSymbol)
        {
            IPoint point = new PointClass();
            point.X = (width / 2);
            point.Y = (height / 2);
            geometry = point;
        }
        else if (symbol is ILineSymbol)
        {
            IPolyline line = new PolylineClass();
            IPoint ptFrom = new PointClass();
            IPoint ptTo = new PointClass();
            ptFrom.X = 3; ptFrom.Y = (height / 2);
            ptTo.X = (width - 3); ptTo.Y = ptFrom.Y;
            line.FromPoint = ptFrom;
            line.ToPoint = ptTo;
            geometry = line;
        }
        else
        {
            IEnvelope bounds = new EnvelopeClass();
            bounds.XMin = 1; bounds.XMax = width - 1;
            bounds.YMin = 1; bounds.YMax = height - 1;
            geometry = bounds;
        }

        symbol.SetupDC(hdc.ToInt32(), null);
        symbol.Draw(geometry);
        symbol.ResetDC();
        g.ReleaseHdc(hdc);
        g.Dispose();

        return bitmap as Image;
    }
    catch (Exception ex)
    {
        Debug.Print(ex.Message);
        return null;
    }
}

Update, Added the following code to make it work:

Updated the ImageFromSymbol metod with:

ITransformation pTransformation = CreateTransFromDC(
                       hDC, size.Width, size.Height);
pSymbol.SetupDC(hDC.ToInt32(), pTransformation);

Added:

 private const int LOGPIXELSY = 90;

[DllImport("GDI32.dll", EntryPoint = "GetDeviceCaps",
           ExactSpelling = true, SetLastError = true)]
       private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);


private static ITransformation CreateTransFromDC(IntPtr hDC,
           int lWidth, int lHeight) {
           // Calculate the parameters for the new transformation,
           // based on the dimensions passed to this function.
           try {
               IEnvelope pBoundsEnvelope = new EnvelopeClass();
               pBoundsEnvelope.PutCoords(0.0, 0.0, (double)lWidth,
                   (double)lHeight);

               tagRECT deviceRect;
               deviceRect.left = 0;
               deviceRect.top = 0;
               deviceRect.right = lWidth;
               deviceRect.bottom = lHeight;

               int dpi = GetDeviceCaps(hDC, LOGPIXELSY);
               if (dpi == 0) {
                   throw new Exception(
                     "Could not retrieve Resolution from device context.");
               }

               // Create a new display transformation and set its properties
               IDisplayTransformation newTrans =
                   new DisplayTransformationClass();
               newTrans.VisibleBounds = pBoundsEnvelope;
               newTrans.Bounds = pBoundsEnvelope;
               newTrans.set_DeviceFrame(ref deviceRect);
               newTrans.Resolution = dpi;

               return newTrans;
           }
           catch {
               return null;
           }
       }
share|improve this question
    
Yes, when I tried to loop through layers of the IMultiLayerFillSymbol and drawing the individual IPictureFillSymbol it throws the same exception. –  MathiasWestin Oct 6 '10 at 14:54

1 Answer 1

up vote 2 down vote accepted

I'd try creating a new DisplayTransformation class and passing it to SetupDC (instead of null). I think you'll need to set the device frame to match the pixel extent, along with visible extent. Then pass an envelope to Draw that matches the visible extent.

Update: try Richie Carmichael's SymbolToBitmap function here.

share|improve this answer
    
Great! Adding a ITransformation solved the problem! –  MathiasWestin Oct 6 '10 at 15:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.