⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tilecache.cs

📁 在windows mobile 5上的地图查看器
💻 CS
字号:
// Copyright (c) Jason Fuller. 
//
// Use of this source code is subject to the terms of the license found in the
// file License.txt.  If you did not accept the terms of that license, you are
// not authorized to use this source code.

#region Using directives

using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;

#endregion

namespace PocketEarth
{


    /// <summary>
    /// Summary description for TileCache.
    /// </summary>
    public class TileCache
    {
        /// <summary>
        /// The cache of Tiles.
        /// </summary>
        private ArrayList tiles = new ArrayList();


        /// <summary>
        /// The file cache.
        /// </summary>
        private ArrayList files = new ArrayList();



        /// <summary>
        /// The maximum number of files to cache.  Files tend to average 10K each.
        /// </summary>
        public int MaxCachedFiles
        {
            get
            {
                return (int)Registry.GetValue(
                                Registry.GetRootKey(Registry.HKey.CURRENT_USER),
                                "Software\\Jason Fuller's\\VirtualEarthMobile", "CacheSizeKB")
                             / 10; // Each file tends to be around 10KB.
            }
        }

        /// <summary>
        /// The maximum number of tiles (bitmaps) to cache in memory.
        /// </summary>
        private int maxCachedTiles = 4;

        /// <summary>
        /// The directory in persistent storage where the cached files live.
        /// </summary>
        private string persistentStoragePath;

        /// <summary>
        /// The directory on the storage card where the cached files live.
        /// </summary>
        private string storageCardPath;

        /// <summary>
        /// The bitmap to show when the real bitmap cannot be gotten 
        /// from the server.
        /// </summary>
        private static Bitmap badBitmap = new Bitmap(MapTiles.TileSize, MapTiles.TileSize);


        [System.Runtime.InteropServices.DllImport("coredll.dll")]
        private static extern bool SHGetSpecialFolderPath(IntPtr hwndOwner, StringBuilder lpszPath, int nFolder, bool fCreate);





        public struct CachedFileInfo
        {
            public string Name;
            public DateTime CreationTime;

            public CachedFileInfo(string name, DateTime time)
            {
                Name = name;
                CreationTime = time;
            }
        }


        /// <summary>
        /// Compares two FileInfos based on CreationTime.
        /// </summary>
        public class TimeSorter : IComparer
        {
            int IComparer.Compare(Object x, Object y)
            {
                CachedFileInfo f1 = (CachedFileInfo)x;
                CachedFileInfo f2 = (CachedFileInfo)y;
                if (f1.CreationTime < f2.CreationTime)
                {
                    return -1;
                }
                else if (f1.CreationTime == f2.CreationTime)
                {
                    return 0;
                }
                else
                {
                    return +1;
                }
            }
        }



        public TileCache()
        {
            // Set up file cache.

            DirectoryInfo di = new DirectoryInfo(CachePath);
            // Read in all the pre-existing files.
            foreach (FileInfo fileinfo in di.GetFiles())
            {
                files.Add(new CachedFileInfo(fileinfo.FullName, fileinfo.CreationTime));
            }
            files.Sort(new TimeSorter());
        }


        /// <summary>
        /// The directory where the file cache lives if persistent storage is used.
        /// </summary>
        private string PersistentStoragePath
        {
            get
            {
                if (persistentStoragePath == null)
                {
                    int MAX_PATH = 260;
                    int CSIDL_APPDATA = 26;
                    StringBuilder sb = new StringBuilder(MAX_PATH);
                    SHGetSpecialFolderPath(IntPtr.Zero, sb, CSIDL_APPDATA, false);
                    persistentStoragePath = sb.ToString() + "\\VirtualEarthMobile";
                    if (!Directory.Exists(persistentStoragePath))
                    {
                        Directory.CreateDirectory(persistentStoragePath);
                    }
                }
                return persistentStoragePath;
            }
        }

        /// <summary>
        /// The directory where the file cache lives if a storage card is used.
        /// </summary>
        private string StorageCardPath
        {
            get
            {
                if (storageCardPath == null)
                {
                    DirectoryInfo rootDir = new DirectoryInfo(@"\");

                    foreach (DirectoryInfo di in rootDir.GetDirectories())
                    {
                        if ((di.Attributes & FileAttributes.Temporary) == FileAttributes.Temporary)
                        {
                            storageCardPath = "\\" + di.Name + "\\VirtualEarthMobileCache";
                            if (!Directory.Exists(storageCardPath))
                            {
                                Directory.CreateDirectory(storageCardPath);
                            }
                            break;
                        }
                    }
                }
                return storageCardPath;
            }
        }

        /// <summary>
        /// The directory where the file cache lives.
        /// </summary>
        private string CachePath
        {
            get
            {
                int useStorageCard = (int)Registry.GetValue(Registry.GetRootKey(Registry.HKey.CURRENT_USER),
                                  "Software\\Jason Fuller's\\VirtualEarthMobile",
                                  "UseStorageCard");
                if (useStorageCard != 0)
                {
                    string stgCardPath = StorageCardPath;
                    if (Directory.Exists(stgCardPath))
                    {
                        return stgCardPath;
                    }
                }
                return PersistentStoragePath;
            }
        }




        /// <summary>
        /// Looks up the cached file corresponding to the given url.
        /// If found, the resulting bitmap is cached.
        /// </summary>
        /// <param name="url">The url of the tile bitmap</param>
        /// <returns>The bitmap, or bull if not found.</returns>
        private Bitmap LookupCachedFile(string url)
        {
            Bitmap bitmap;
            string filename = UrlToFilename(url);

            if (!File.Exists(filename))
            {
                return null;
            }

            FileStream stm = File.Open(filename, FileMode.Open);
            if (stm != null)
            {
                bitmap = new Bitmap(stm);
                stm.Close();
                // Cache the image
                this.Add(url, bitmap);
            }
            else
            {
                bitmap = null;
            }
            return bitmap;
        }


        /// <summary>
        /// Convert a URL to a local filename where the content of the URL
        /// was or will be stored.
        /// </summary>
        /// <param name="url">The url.</param>
        /// <returns>A filename in the local filesystem.</returns>
        private string UrlToFilename(string url)
        {
            // Extract the local filename from the url.
            int start = url.LastIndexOf('/');
            int end = url.LastIndexOf('?');
            string filename = CachePath + "\\" + url.Substring(start + 1, end - start - 1);
            return filename;
        }




        /// <summary>
        /// Looks up the bitmap corresponding to the given url.
        /// </summary>
        /// <param name="url">The url of the tile bitmap.</param>
        /// <returns>The bitmap, or null if not found.</returns>
        public Bitmap LookupUrl(string url)
        {
            Bitmap bitmap = LookupCachedBitmap(url);
            if (bitmap != null)
            {
                return bitmap;
            }

            bitmap = LookupCachedFile(url);
            if (bitmap != null)
            {
                return bitmap;
            }

            bitmap = LookupBitmapFromServer(url);
            if (bitmap != null)
            {
                return bitmap;
            }

            // We do this twice because fairly often the first attempt
            // will fail, but a retry will succeed.
            bitmap = LookupBitmapFromServer(url);
            if (bitmap != null)
            {
                return bitmap;
            }

            // Last resort: Return an empty bitmap
            this.Add(url, badBitmap);
            return badBitmap;
        }


        /// <summary>
        /// Get a bitmap from the Virtual Earth server.  If found, cache the 
        /// file and the bitmap.
        /// </summary>
        /// <param name="url">The url to retrieve.</param>
        /// <returns>The bitmap.</returns>
        private Bitmap LookupBitmapFromServer(string url)
        {
            WebResponse response = null;
            Stream stream = null;

            // Get bitmap from VirtualEarth server.
            WebRequest req = WebRequest.Create(url);
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                response = req.GetResponse();
                stream = response.GetResponseStream();
            }
            catch (WebException/* ex*/)
            {
#if false
                MessageBox.Show("Could not get the image from the MSN VirtualEarth server.  "
                    /*+ ex.Message*/,
                                "PocketEarth");
#endif
            }
            Cursor.Current = Cursors.Default;

            if (stream != null)
            {
                // Create the local file
                string filename = UrlToFilename(url);
                FileStream fileStream = File.Open(filename, FileMode.CreateNew);
                byte[] bytes = new byte[1024];
                int bytesRead;
                while ((bytesRead = stream.Read(bytes, 0, 1024)) != 0)
                {
                    fileStream.Write(bytes, 0, bytesRead);
                }
                fileStream.Close();
                response.Close();

                // Cache the local file
                files.Add(new CachedFileInfo(filename, DateTime.Now));

                // Delete the least recently-used file if necessary
                while (files.Count > MaxCachedFiles)
                {
                    File.Delete(((CachedFileInfo)files[0]).Name);
                    files.RemoveAt(0);
                }
            }

            // Now get a bitmap from the cached file we just created.
            return LookupCachedFile(url);
        }



        /// <summary>
        /// Looks up the cached bitmap corresponding to the given url.
        /// </summary>
        /// <param name="url">The url of the tile bitmap.</param>
        /// <returns>The bitmap, or null if not found.</returns>
        public Bitmap LookupCachedBitmap(string url)
        {
            Tile foundTile = null;
            Bitmap bitmap;

            foreach (Tile t in this.tiles)
            {
                if (t.Url == url)
                {
                    foundTile = t;
                }
            }
            if (foundTile != null)
            {
                // Since someone is looking up this tile, move it to the end
                // of the list, which marks it as the most recently used tile.
                tiles.Remove(foundTile);
                tiles.Add(foundTile);
                bitmap = foundTile.Bitmap;
            }
            else
            {
                bitmap = null;
            }
            return bitmap;
        }


        /// <summary>
        /// Adds a tile to the cache.
        /// </summary>
        /// <param name="url"></param>
        /// <param name="bitmap"></param>
        public void Add(string url, Bitmap bitmap)
        {
            // Create a new tile and add it to the end of the list,
            // which marks it as the most recently used.
            tiles.Add(new Tile(url, bitmap));

            // Remove older tiles if necessary.
            if (tiles.Count > maxCachedTiles)
            {
                // Remove from the front of the list, where the 
                // least recently used tile is.
                tiles.RemoveAt(0);

                // I know you're not supposed to call GC.Collect but if I don't,
                // I get OutOfMemory exceptions.
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }




        /// <summary>
        /// Remove from the cache any tiles whose bitmap is bad.
        /// (We'll try to refetch the bitmap from the server next time.)
        /// </summary>
        public void PurgeBadBitmaps()
        {
            // List of bad tiles to remove.
            ArrayList bads = new ArrayList();

            foreach (Tile t in tiles)
            {
                if (t.Bitmap == badBitmap)
                {
                    bads.Add(t);
                }
            }
            foreach (Tile t in bads)
            {
                tiles.Remove(t);
            }
        }

        public void PurgeAllBitmaps()
        {
            // Throw away the old cache and create a new one.
            tiles = new ArrayList();
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -