ImageListStreamer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / ImageListStreamer.cs / 1305376 / ImageListStreamer.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 */ 
namespace System.Windows.Forms {
    using System.Runtime.InteropServices; 
    using System.Runtime.Serialization;
    using System.Diagnostics;
    using System;
    using System.Drawing; 
    using System.ComponentModel;
    using System.IO; 
    using System.Windows.Forms; 
    using Microsoft.Win32;
    using System.Globalization; 
    using System.Security.Permissions;

    /// 
    ///  
    /// 
    [Serializable] 
    public sealed class ImageListStreamer : ISerializable, IDisposable { 

        // compressed magic header.  If we see this, the image stream is compressed. 
        // (unicode for MSFT).
        //
        private static readonly byte[] HEADER_MAGIC = new byte[] {0x4D, 0x53, 0x46, 0X74};
        private static object internalSyncObject = new object(); 

        private ImageList imageList; 
        private ImageList.NativeImageList nativeImageList; 

        internal ImageListStreamer(ImageList il) { 
            imageList = il;
        }

        /** 
         * Constructor used in deserialization
         */ 
        private ImageListStreamer(SerializationInfo info, StreamingContext context) 
        {
            SerializationInfoEnumerator sie = info.GetEnumerator(); 
            if (sie == null)
            {
                return;
            } 
            while (sie.MoveNext())
            { 
                if (String.Equals(sie.Name, "Data", StringComparison.OrdinalIgnoreCase)) 
                {
#if DEBUG 
                    try {
#endif
                    byte[] dat = (byte[])sie.Value;
                    if (dat != null) 
                    {
                        //VSW #123063: We enclose this imagelist handle create in a theming scope. This is a temporary 
                        //             solution till we tackle the bigger issue tracked by VSW #95247 
                        IntPtr userCookie = UnsafeNativeMethods.ThemingScope.Activate();
 
                        try
                        {
                            MemoryStream ms = new MemoryStream(Decompress(dat));
 
                            lock (internalSyncObject) {
                                SafeNativeMethods.InitCommonControls(); 
                                nativeImageList = new ImageList.NativeImageList( 
                                    SafeNativeMethods.ImageList_Read(new UnsafeNativeMethods.ComStreamFromDataStream(ms)));
                            } 
                        }
                        finally
                        {
                            UnsafeNativeMethods.ThemingScope.Deactivate(userCookie); 
                        }
                        if (nativeImageList.Handle == IntPtr.Zero) 
                        { 
                            throw new InvalidOperationException(SR.GetString(SR.ImageListStreamerLoadFailed));
                        } 
                    }
#if DEBUG
                    }
                    catch (Exception e) { 
                        Debug.Fail("ImageList serialization failure: " + e.ToString());
                        throw; 
                    } 
#endif
                } 
            }
        }

        ///  
        ///     Compresses the given input, returning a new array that represents
        ///     the compressed data. 
        ///  
        private byte[] Compress(byte[] input) {
 
            int finalLength = 0;
            int idx = 0;
            int compressedIdx = 0;
 
            while(idx < input.Length) {
 
                byte current = input[idx++]; 
                byte runLength = 1;
 
                while(idx < input.Length && input[idx] == current && runLength < 0xFF) {
                    runLength++;
                    idx++;
                } 

                finalLength += 2; 
            } 

            byte[] output = new byte[finalLength + HEADER_MAGIC.Length]; 

            Buffer.BlockCopy(HEADER_MAGIC, 0, output, 0, HEADER_MAGIC.Length);
            int idxOffset = HEADER_MAGIC.Length;
            idx = 0; 

            while(idx < input.Length) { 
 
                byte current = input[idx++];
                byte runLength = 1; 

                while(idx < input.Length && input[idx] == current && runLength < 0xFF) {
                    runLength++;
                    idx++; 
                }
 
                output[idxOffset + compressedIdx++] = runLength; 
                output[idxOffset + compressedIdx++] = current;
            } 

            Debug.Assert(idxOffset + compressedIdx == output.Length, "RLE Compression failure in ImageListStreamer -- didn't fill array");

            // Validate that our compression routine works 
            #if DEBUG
            byte[] debugCompare = Decompress(output); 
            Debug.Assert(debugCompare.Length == input.Length, "RLE Compression in ImageListStreamer is broken."); 
            int debugMaxCompare = input.Length;
            for(int debugIdx = 0; debugIdx < debugMaxCompare; debugIdx++) { 
                if (debugCompare[debugIdx] != input[debugIdx]) {
                    Debug.Fail("RLE Compression failure in ImageListStreamer at byte offset " + debugIdx);
                    break;
                } 
            }
            #endif // DEBUG 
 
            return output;
        } 

        /// 
        ///     Decompresses the given input, returning a new array that represents
        ///     the uncompressed data. 
        /// 
        private byte[] Decompress(byte[] input) { 
 
            int finalLength = 0;
            int idx = 0; 
            int outputIdx = 0;

            // Check for our header. If we don't have one,
            // we're not actually decompressed, so just return 
            // the original.
            // 
            if (input.Length < HEADER_MAGIC.Length) { 
                return input;
            } 

            for(idx = 0; idx < HEADER_MAGIC.Length; idx++) {
                if (input[idx] != HEADER_MAGIC[idx]) {
                    return input; 
                }
            } 
 
            // Ok, we passed the magic header test.
 
            for (idx = HEADER_MAGIC.Length; idx < input.Length; idx+=2) {
                finalLength += input[idx];
            }
 
            byte[] output = new byte[finalLength];
 
            idx = HEADER_MAGIC.Length; 

            while(idx < input.Length) { 
                byte runLength = input[idx++];
                byte current = input[idx++];

                int startIdx = outputIdx; 
                int endIdx = outputIdx + runLength;
 
                while(startIdx < endIdx) { 
                    output[startIdx++] = current;
                } 

                outputIdx += runLength;
            }
 
            return output;
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)]
        public void /*cpr: ISerializable*/GetObjectData(SerializationInfo si, StreamingContext context) { 
            MemoryStream stream = new MemoryStream();
 
            IntPtr handle = IntPtr.Zero; 
            if (imageList != null) {
                handle = imageList.Handle; 
            }
            else if (nativeImageList != null) {
                handle = nativeImageList.Handle;
            } 

            if (handle == IntPtr.Zero || !WriteImageList(handle, stream)) 
                throw new InvalidOperationException(SR.GetString(SR.ImageListStreamerSaveFailed)); 

            si.AddValue("Data", Compress(stream.ToArray())); 
        }

        /// 
        ///  
        internal ImageList.NativeImageList GetNativeImageList() {
            return nativeImageList; 
        } 

        private bool WriteImageList(IntPtr imagelistHandle, Stream stream) { 
            // What we need to do here is use WriteEx if comctl 6 or above, and Write otherwise. However, till we can fix
            // VSWhidbey #248889, there isn't a reliable way to tell which version of comctl fusion is binding to.
            // So for now, we try to bind to WriteEx, and if that entry point isn't found, we use Write.
 
            try {
                int hResult = SafeNativeMethods.ImageList_WriteEx(new HandleRef(this, imagelistHandle), NativeMethods.ILP_DOWNLEVEL, new UnsafeNativeMethods.ComStreamFromDataStream(stream)); 
                return (hResult == NativeMethods.S_OK); 
            }
            catch (EntryPointNotFoundException) { 
                // WriteEx wasn't found - that's fine - we will use Write.
            }

            return SafeNativeMethods.ImageList_Write(new HandleRef(this, imagelistHandle), new UnsafeNativeMethods.ComStreamFromDataStream(stream)); 
        }
 
        ///  
        /// 
        ///     Disposes the native image list handle. 
        /// 
        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this); 
        }
 
        private void Dispose(bool disposing) { 
            if (disposing) {
                if (nativeImageList != null) { 
                    nativeImageList.Dispose();
                    nativeImageList = null;
                }
            } 
        }
 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK