Feedback & Feature Requests

Coordinator
Nov 22, 2007 at 4:11 PM
These tools were created for my own uses, so I do not know how well they will fit the needs or interests of others. If you find them useful - or wish they behaved differently, please let me know.
Sep 24, 2008 at 10:20 AM
Hi,

VERY useful for me.

I need a translation from flash to emf, and the direct solutions I found didn't work with the images I use, so I found a way to convert from flash to XAML (ia SWF2XAML http://drawlogic.com/2007/06/03/swf-to-xaml-converter-swf2xaml-flash-to-wpfsilverlight/), and your tools brings the rest.

So, for me, even more perfect would be in import from swf, but I'm glad that this project exists. Thanks
Sep 30, 2008 at 7:21 AM
Edited Sep 30, 2008 at 7:23 AM
Hi,
Thanks for the excellent utility to convert XAML graphics to other formats. I got my application working (need to copy graphics made in WPF program to PowerPoint) with the help of your utility, but unfortunately only by first rendering the graphics to a file and then reading the file to the clipboard. Can you help how to copy "System.Drawing" or "System.Drawing.Graphics" object directly to clipboard (simple Clipboard.SetDataObject doesn't seem to work). Thanks in advance.
Coordinator
Oct 1, 2008 at 3:35 AM
While I've not had reason to try it myself, but what you want to put on the clipboard are the bits from a System.Drawing.Imaging.Metafile.   There's no direct support for this in the current API, but if you look at the code for Utility.CreateEMF() you'll see where you could replace the File.Create() with a passed in MemorySteam.

regards,
-Blake
Sep 15, 2009 at 12:18 PM

hi,

I'm are going to use your tool for converting our custom user controls to scalable vector graphics (svg) or simple System.Drawing.Image.

But i recognized that your CreateEMF method makes the image smaller than i expect. we always have an invisible boarder of eg 5-10px around it.

When i use Bitmap with the PngBitmapEncoder the dimensions are correct.

Do you have a better solution for the lines below?

Drawing vectorGraphic = BCDev.XamlToys.Utility.GetDrawingFromXaml(control);

Graphics g = BCDev.XamlToys.Utility.CreateEmf(Path.GetTempFileName(), vectorGraphic.Bounds);
IntPtr ipHdc = g.GetHdc();

using (MemoryStream ms = new MemoryStream())
{
Metafile mf = new Metafile(ms, ipHdc);

g.ReleaseHdc();
g.Dispose();

g = Graphics.FromImage(mf);
vectorGraphic.RenderTo(g, 1.0);

g.Dispose();

ms.Position = 0;

Image = new Metafile(ms);
}

Coordinator
Sep 15, 2009 at 4:07 PM
rs200 wrote:

I'm are going to use your tool for converting our custom user controls to scalable vector graphics (svg) or simple System.Drawing.Image.

But i recognized that your CreateEMF method makes the image smaller than i expect. we always have an invisible boarder of eg 5-10px around it.

When i use Bitmap with the PngBitmapEncoder the dimensions are correct.

 There are a few things in your question that confuse me a bit. 

  • This library won't help you create SVG output, that's an entirely different format.
  • If you want to create PNG files, you shouldn't go via System.Drawing.Image, you should just use RenderTargetBitmap.

The included xaml2emf tool just takes the bounding box (drawing.Bounds) and passes that as the second parameter to CreateEmf.   This is a 'feature' of xaml2emf, in that the resulting file is snapped tight around the visible elements of the input drawing.   It may well not be what you want in your case.   If that's the issue, simply pass the full bounds, including the invisible border, as the second parameter of CreateEmf.

regards,
-Blake

Sep 16, 2009 at 8:15 AM

may be my description was not exact.

my goal is to get a System.Drawing.Image out of a wpf control for integrating it in a winforms solution (report) were have to set a property which is type of Image.

i already went the way via RenderTargetBitmap but there i had a bad quality with 96dpi or a bad performance when i raised the resolution (to 600dpi).
The positive is that the dimensions are which i expect. without space/boarder.

the problem with your tool is that our control does not have any invisible boarders so the bounds are the full visible ones. And also when i raise the bounds of the control before i runs through your two methods the resulting image does not getting bigger, the quality gets better instead. !?! The advantage of using metafiles and your tools is the good performance. But the boarders around raise with the size of the resulting image.

 

regards

Robert

 

Coordinator
Sep 17, 2009 at 8:05 AM
Edited Sep 17, 2009 at 8:11 AM

Okay, I believe I understand your situation better now.  The usual way to do that sort of WPF->WinForms interop would be to place a HostElement on the WinForms report and host your WPF control within it.   I presume you've already explored that and your reporting tool doesn't support it.

It still sounds like my answer above it what you are looking for, but code is always more clear:

using System;
using System.Windows;
using System.Windows.Controls;
using wf = System.Windows.Forms;
using d = System.Drawing;
using di = System.Drawing.Imaging;
using BCDev.XamlToys;

class Test {
    [STAThread]
    static void Main() {
    var control = new UserControl() {Content = new Button() {Margin = new Thickness(10), Width=100, Height=50}};
    var drawing = Utility.GetDrawingFromXaml(control);
    Console.WriteLine("UserControl Size: {0},{1}", control.ActualWidth, control.ActualHeight);
    Console.WriteLine("Drawing Bounds: {0}", drawing.Bounds);

    di.Metafile mf;
    using (var refDC = d.Graphics.FromImage(new d.Bitmap(1, 1)))
        mf = new di.Metafile(refDC.GetHdc(), 
            new d.RectangleF(0, 0, (float)control.ActualWidth, (float)control.ActualHeight), 
            di.MetafileFrameUnit.Pixel, di.EmfType.EmfPlusOnly);

    using (var g = d.Graphics.FromImage(mf))
        Utility.RenderDrawingToGraphics(drawing, g);

    wf.Application.Run(new wf.Form() {BackgroundImage = mf});
    }
}

When you run this program you will have a WinForm Form displayed with the visual of WPF button tiled as it's background image.
There are several things to notice.   On the console it will read:

UserControl Size: 120,70
Drawing Bounds: 10,10,100,50

This is what I was warning about in the previous message.  The control is 120px wide, but the visual is only 100px wide, and so you can't pass the drawing bounds into CreateEMF and have it do what you expect.  You need to use the 0,0,120,70.

Unrelated to that, it doesn't appear you want the EMF file kept around, you just want the in-memory metafile.  When I looked more closely, you were effectively throwing away the metafile from your call to CreateEMF anyway,and I can't promise what might be happening when you create a metafile off that memory stream.  Better to use the Metafile constructor above and just render to it's Graphic directly.

Hope this gets things working for you,
-Blake

Sep 18, 2009 at 7:58 AM

yeah, now i got the meaning of your warning

it works fine with the right dimension. :-)

thanks for this

the other point regarding the EMF works also fine at the first try. But only for 2 of 3 controls.
The last one doesn't get painted and when i try to integrate it in our report designer i get an inexpressive error message 'a general GDI+ error occurred' at mf =  new Metafile(...).
So i had to go back to the memory stream solution.

i also had to modify your code a little bit. At GetDrawingFromXaml i have to go always the way via the Framework element because i have to manipulate the control before it gets rendered.
For example in your controls we use Path shapes with LineSegments where some are stroked and some not. When the control gets rendered the IsStroked will be ignored and i see also the line which i wont see. 

 

regards

Robert

Coordinator
Sep 18, 2009 at 10:29 AM
Edited Sep 18, 2009 at 10:30 AM
The last one doesn't get painted and when i try to integrate it in our report designer i get an inexpressive error message 'a general GDI+ error occurred' at mf =  new Metafile(...).
So i had to go back to the memory stream solution.

i also had to modify your code a little bit. At GetDrawingFromXaml i have to go always the way via the Framework element because i have to manipulate the control before it gets rendered.
For example in your controls we use Path shapes with LineSegments where some are stroked and some not. When the control gets rendered the IsStroked will be ignored and i see also the line which i wont see. 

I'd guess that the first problem is occuring because the width or height being passed for the metafile bounding box is zero. 
That will certainly cause the exception you are seeing, and it's the only way I've provoked it in the past.  
(Though of course with wording like that, there must be other code-paths in GDI+ that throw that message.)
If that is the problem, try the GetDrawingFromXaml overload that takes a width and height.  Not all controls handle the layout pass properly without being given a desired size like that.

There are a small number of WPF Drawing features that aren't supported.  Unstroked path segments are certainly one of those. 
If you attach a Trace Listener you will get warning messages any things not converted.   It is also worth a grep through XamlToys.cs for "Utility.Warning" to see what the missing edge cases are ahead of time.

Glad to hear the library is useful in general.
-Blake