using System; using System.IO; using System.ComponentModel; using System.Reflection; using System.Windows; using System.Windows.Media.Imaging; namespace SharpVectors.Runtime { public class EmbeddedBitmapSource : BitmapSource { #region Private Fields private BitmapImage _bitmap; private MemoryStream _stream; #endregion Fields #region Constructors and Destructor public EmbeddedBitmapSource() : base() { // // Set the _useVirtuals private fields of BitmapSource to true. otherwise you will not be able to call BitmapSource methods. FieldInfo field = typeof(BitmapSource).GetField("_useVirtuals", BindingFlags.NonPublic | BindingFlags.Instance); field.SetValue(this, true); } // ------------------------------------------------------------------ public EmbeddedBitmapSource(MemoryStream stream) : this() { if (stream == null) throw new ArgumentNullException("stream"); _stream = stream; // // Associated this class with source. this.BeginInit(); _bitmap = new BitmapImage(); _bitmap.BeginInit(); _bitmap.StreamSource = _stream; _bitmap.EndInit(); this.InitWicInfo(_bitmap); this.EndInit(); } #endregion Constructors #region Public Properties [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public EmbeddedBitmapData Data { get { return new EmbeddedBitmapData(_stream); } set { BeginInit(); _stream = value.Stream; _bitmap = new BitmapImage(); _bitmap.BeginInit(); _bitmap.StreamSource = _stream; _bitmap.EndInit(); InitWicInfo(_bitmap); EndInit(); } } #endregion Properties #region Protected Methods protected override void CloneCore(Freezable sourceFreezable) { EmbeddedBitmapSource cloneSource = (EmbeddedBitmapSource)sourceFreezable; CopyFrom(cloneSource); //base.CloneCore( sourceFreezable ); } protected override void CloneCurrentValueCore(Freezable sourceFreezable) { EmbeddedBitmapSource cloneSource = (EmbeddedBitmapSource)sourceFreezable; CopyFrom(cloneSource); //base.CloneCurrentValueCore( sourceFreezable ); } protected override void GetAsFrozenCore(Freezable sourceFreezable) { EmbeddedBitmapSource cloneSource = (EmbeddedBitmapSource)sourceFreezable; CopyFrom(cloneSource); //base.GetAsFrozenCore( sourceFreezable ); } protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable) { EmbeddedBitmapSource cloneSource = (EmbeddedBitmapSource)sourceFreezable; CopyFrom(cloneSource); //base.GetCurrentValueAsFrozenCore( sourceFreezable ); } protected override Freezable CreateInstanceCore() { return new EmbeddedBitmapSource(); } #endregion Override Methods #region Private Methods /// /// Call BeginInit every time the WICSourceHandle is going to be change. /// again this methods is not exposed and reflection is needed. /// private void BeginInit() { FieldInfo field = typeof(BitmapSource).GetField( "_bitmapInit", BindingFlags.NonPublic | BindingFlags.Instance); MethodInfo beginInit = field.FieldType.GetMethod( "BeginInit", BindingFlags.Public | BindingFlags.Instance); beginInit.Invoke(field.GetValue(this), null); } /// /// Call EndInit after the WICSourceHandle was changed and after using BeginInit. /// again this methods is not exposed and reflection is needed. /// private void EndInit() { FieldInfo field = typeof(BitmapSource).GetField( "_bitmapInit", BindingFlags.NonPublic | BindingFlags.Instance); MethodInfo endInit = field.FieldType.GetMethod( "EndInit", BindingFlags.Public | BindingFlags.Instance); endInit.Invoke(field.GetValue(this), null); } /// /// Set the WicSourceHandle property with the source associated with this class. /// again this methods is not exposed and reflection is needed. /// /// private void InitWicInfo(BitmapSource source) { // // Use reflection to get the private property WicSourceHandle Get and Set methods. PropertyInfo wicSourceHandle = typeof(BitmapSource).GetProperty( "WicSourceHandle", BindingFlags.NonPublic | BindingFlags.Instance); MethodInfo wicSourceHandleGetMethod = wicSourceHandle.GetGetMethod(true); MethodInfo wicSourceHandleSetMethod = wicSourceHandle.GetSetMethod(true); // // Call the Get method of the WicSourceHandle of source. object wicHandle = wicSourceHandleGetMethod.Invoke(source, null); // // Call the Set method of the WicSourceHandle of this with the value from source. wicSourceHandleSetMethod.Invoke(this, new object[] { wicHandle }); } private void CopyFrom(EmbeddedBitmapSource source) { this.BeginInit(); _bitmap = source._bitmap; this.InitWicInfo(_bitmap); this.EndInit(); } #endregion Methods } }