Иногда требуется отображать в textBlock картинку, с .png всё отлично, а тут попалось .svg и они игнорируются, собственно MSDN это подтвердил.
Как всё таки отобразить SVG по url ?
Желательно объяснить действия шаг за шагом.
Image image = new Image();
image.Height = 50;
image.Source = new BitmapImage(new Uri(src));
textBlock.Inlines.Add(image);
Ответ
Можно просто преобразовать SVG в растровое изображение и отобразить его. Это можно сделать с помощью сторонних библиотек, или, при наличии Internet Explorer 11, стандартными средствами.
Добавим ссылки на System.Drawing и COM -> Microsoft HTML Object Library. Создадим вспомогательный класс для преобразования SVG в BMP:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
//Reference: System.Drawing
//Reference: Microsoft HTML Object Library
namespace WpfApplication1
{
public class SvgConvert
{
//преобразует SVG, заданный строкой svgcontent, в Bitmap заданных размеров и записывает его в поток output
public static void ToBitmap(string svgcontent, int w_image,int h_image,System.IO.Stream output)
{
RECTL rcClient = new RECTL();
bool b = SystemParametersInfo(SPI_GETWORKAREA, 0, ref rcClient, 0);
if (b == false) { rcClient.bottom = 480; rcClient.right = 640; }
int width = (int)(rcClient.right - rcClient.left);
int height = (int)(rcClient.bottom - rcClient.top);
IntPtr screendc = GetDC(IntPtr.Zero);
string svghtml =
"" + svgcontent + "";
mshtml.HTMLDocument doc = null;
mshtml.IHTMLDocument2 d2 = null;
IOleObject pObj = null;
IViewObject pView = null;
try
{
doc = new mshtml.HTMLDocument(); //создание документа
d2 = (mshtml.IHTMLDocument2)doc;
int hr;
//установка размера документа
pObj = (IOleObject)d2;
SIZEL sz = new SIZEL();
sz.x = (uint)MulDiv(width, HIMETRIC_INCH, GetDeviceCaps(screendc, LOGPIXELSX));
sz.y = (uint)MulDiv(height, HIMETRIC_INCH, GetDeviceCaps(screendc, LOGPIXELSY));
hr = pObj.SetExtent((int)System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT, ref sz);
if (hr != 0) throw Marshal.GetExceptionForHR(hr);
//запись SVG в документ
d2.write(svghtml);
d2.close();
//преобразование в Bitmap
pView = (IViewObject)d2;
Bitmap bmp = new Bitmap(w_image, h_image);
Graphics g = Graphics.FromImage(bmp);
using (g)
{
IntPtr hdc = g.GetHdc();
hr = pView.Draw((int)System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT,
-1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, hdc, ref rcClient, IntPtr.Zero,
IntPtr.Zero, 0);
if (hr != 0) throw Marshal.GetExceptionForHR(hr);
g.ReleaseHdc(hdc);
}
//сохранение
bmp.Save(output, System.Drawing.Imaging.ImageFormat.Bmp);
}
finally
{
//освобождение ресурсов
if (d2 != null) Marshal.ReleaseComObject(d2);
if (pObj != null) Marshal.ReleaseComObject(pObj);
if (pView != null) Marshal.ReleaseComObject(pView);
if (doc != null) Marshal.ReleaseComObject(doc);
}
}
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool SystemParametersInfo(int nAction, int nParam, ref RECTL rc, int nUpdate);
public static int MulDiv(int number, int numerator, int denominator)
{
return (int)(((long)number * numerator) / denominator);
}
const int LOGPIXELSX = 88;
const int LOGPIXELSY = 90;
const int HIMETRIC_INCH = 2540;
const int SPI_GETWORKAREA = 48;
}
[ComImport()]
[GuidAttribute("0000010d-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IViewObject
{
int Draw([MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, IntPtr ptd, IntPtr hdcTargetDev, IntPtr hdcDraw,
ref RECTL lprcBounds, IntPtr lprcWBounds, IntPtr pfnContinue, int dwContinue);
int a();
int b();
int c();
int d();
int e();
}
[ComImport()]
[Guid("00000112-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleObject
{
void f();
void g();
void SetHostNames(object szContainerApp, object szContainerObj);
void Close(uint dwSaveOption);
void SetMoniker(uint dwWhichMoniker, object pmk);
void GetMoniker(uint dwAssign, uint dwWhichMoniker, object ppmk);
void x();
void y();
void DoVerb(uint iVerb, uint lpmsg, object pActiveSite, uint lindex, uint hwndParent, uint lprcPosRect);
void EnumVerbs(ref object ppEnumOleVerb);
void Update();
void IsUpToDate();
void GetUserClassID(uint pClsid);
void GetUserType(uint dwFormOfType, uint pszUserType);
int SetExtent(uint dwDrawAspect, ref SIZEL psizel);
void GetExtent(uint dwDrawAspect, uint psizel);
void Advise(object pAdvSink, uint pdwConnection);
void Unadvise(uint dwConnection);
void EnumAdvise(ref object ppenumAdvise);
void GetMiscStatus(uint dwAspect, uint pdwStatus);
void SetColorScheme(object pLogpal);
};
public struct RECTL
{
public uint left;
public uint top;
public uint right;
public uint bottom;
}
public struct SIZEL
{
public uint x;
public uint y;
}
}
Тогда отобразить по URL можно так:
string svgcontent="";
if (uri.IsFile)
{
svgcontent = File.ReadAllText(uri.LocalPath);
}
else
{
var client = new System.Net.WebClient();
using (client)
{
svgcontent = client.DownloadString(uri);
}
}
MemoryStream ms = new MemoryStream();
SvgConvert.ToBitmap(svgcontent, 500,500, ms);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = ms;
bi.EndInit();
Image image = new Image();
image.Source = bi;
textblock.Inlines.Add(image);
Комментариев нет:
Отправить комментарий