/// <summary> /// Gets file icon as <b>Bitmap</b>. /// Returns null if the icon is not cached and failed to get it, eg file does not exist. /// </summary> /// <param name="file">Any file or folder.</param> /// <param name="useExt"> /// Get file type icon, depending on filename extension. Use this to avoid getting separate image object for each file of same type. /// This is ignored if filename extension is ".ico" or ".exe" or starts with ".exe," or ".dll,". /// </param> /// <param name="giFlags">Flags for <see cref="AIcon.GetFileIconImage"/>.</param> /// <param name="autoUpdate"> /// If not null, the cached image will be auto-updated when changed. Then will be called this function. It can update the image in UI. /// How it works: If this function finds cached image, it sets timer that after ~50 ms loads that icon/image from file again and compares with the cached image. If different, updates the cache. Does it once, not periodically. /// Use only in UI threads. Does not work if this thread does not retrieve/dispatch posted messages. /// </param> /// <param name="auParam">Something to pass to the <i>autoUpdate</i> callback function.</param> /// <remarks> /// If the icon is in the memory cache, gets it from there. /// Else if it is in the file cache, gets it from there and adds to the memory cache. /// Else gets from file (uses <see cref="AIcon.GetFileIconImage"/> and adds to the file cache and to the memory cache. /// </remarks> public Bitmap GetImage(string file, bool useExt, IconGetFlags giFlags = 0, Action <Bitmap, object> autoUpdate = null, object auParam = null) { if (useExt) { var ext = APath.GetExtension(file); if (ext.Length == 0) { if (AFile.ExistsAsDirectory(file)) { ext = file; } else { ext = ".no-ext"; } } else { //ext = ext.Lower(); if (ext.Eqi(".ico") || ext.Eqi(".exe") || ext.Starts(".exe,", true) || ext.Starts(".dll,", true)) { ext = file; } } file = ext; } else if (APath.IsFullPathExpandEnvVar(ref file)) { file = APath.Normalize_(file, noExpandEV: true); } return(_GetImage(file, giFlags, null, autoUpdate, auParam, true)); }
/// <summary> /// Starts getting icons of added files. /// </summary> /// <param name="callback">A callback function delegate.</param> /// <param name="iconSize">Icon width and height.</param> /// <param name="flags"></param> /// <param name="objCommon">Something to pass to callback functions.</param> /// <remarks> /// After this function returns, icons are asynchronously extracted with <see cref="AIcon.GetFileIconHandle"/>, and callback called with icon handle (or default(IntPtr) if failed). /// The callback is called in this thread. This thread must have a message loop (eg Application.Run). /// If you'll need more icons, you can add more files and call this function again with the same <b>IconsAsync_</b> instance, even if getting old icons if still not finished. /// </remarks> public void GetAllAsync(Callback callback, int iconSize, IconGetFlags flags = 0, object objCommon = null) { if (_files.Count == 0) { return; } var work = new _AsyncWork(); _works.Add(work); work.GetAllAsync(this, callback, iconSize, flags, objCommon); _files.Clear(); }
bool _LoadImage(out Bitmap b, string file, IconGetFlags giFlags, Func <Bitmap> callback) { if (callback != null) { b = callback(); } else { b = AIcon.GetFileIconImage(file, _iconSize, giFlags); } return(b != null); }
internal void GetAllAsync(IconsAsync_ host, Callback callback, int iconSize, IconGetFlags flags, object objCommon) { Debug.Assert(_callback == null); //must be called once _host = host; _callback = callback; _iconSize = iconSize; _iconFlags = flags; _objCommon = objCommon; _counter = _host._files.Count; using (new Util.EnsureWindowsFormsSynchronizationContext_()) { foreach (var v in _host._files) { if (!v.file.NE()) { _GetIconAsync(new Result(v.file, v.obj)); } } } }
Bitmap _GetImage(string file, IconGetFlags giFlags, Func <Bitmap> callback, Action <Bitmap, object> autoUpdate, object auParam, bool auDispose) { bool cached = true; lock (this) { Bitmap R = null; //is in memory cache? if (_table == null) { _table = new Hashtable(StringComparer.OrdinalIgnoreCase); } else { R = _table[file] as Bitmap; } if (R == null) { //is in file cache? try { if (_x == null && AFile.ExistsAsFile(_cacheFile)) { _x = AExtXml.LoadElem(_cacheFile); if (_iconSize != _x.Attr("size", 0) || ADpi.BaseDPI != _x.Attr("dpi", 0)) { _x = null; ADebug.Print("info: cleared icon cache"); } //FUTURE: Delete unused entries. Maybe try to auto-update changed icons. // Not very important, because there is ClearCache. } if (_x != null) { var x = _x.Elem("i", "name", file, true); if (x != null) { using var ms = new MemoryStream(Convert.FromBase64String(x.Value), false); R = new Bitmap(ms); } } } catch (Exception ex) { ADebug.Print(ex.Message); } if (R != null) { _table[file] = R; //add to memory cache } else if (_LoadImage(out R, file, giFlags, callback)) //get file icon { _AddImage(file, R, false); //add to file cache and memory cache cached = false; } } //auto-update if (cached && autoUpdate != null) { var d = new _AUData() { cache = this, oldImage = R, file = file, callback = callback, autoUpdated = autoUpdate, auParam = auParam, giFlags = giFlags, canDispose = auDispose, }; _AutoUpdateAdd(d); } return(R); } }
/// <summary> /// Gets file icon. /// More info: <see cref="GetFileIcon"/>. /// </summary> /// <returns>Returns icon handle, or default(IntPtr) if failed. Later call <see cref="DestroyIconHandle"/> or some <b>HandleToX</b> function that will destroy it.</returns> public static IntPtr GetFileIconHandle(string file, int size = 0, IconGetFlags flags = 0) { if (file.NE()) { return(default);
///// If not full path, the function will look in <see cref="AFolders.ThisAppImages"/>. See also <see cref="IconGetFlags"/>. /// <summary> /// Gets file icon. /// More info: <see cref="GetFileIcon"/>. /// </summary> /// <returns>Returns null if failed.</returns> public static Bitmap GetFileIconImage(string file, int size = 0, IconGetFlags flags = 0) => HandleToImage(GetFileIconHandle(file, size, flags), true);
/// <summary> /// Gets file icon. /// Extracts icon directly from the file, or gets shell icon, depending on file type, icon index, etc. /// </summary> /// <returns>Returns null if failed.</returns> /// <param name="file"> /// Can be: /// - Path of any file or folder. Supports environment variables. /// - Any shell object, like <c>":: ITEMIDLIST"</c>, <c>@"::{CLSID-1}\::{CLSID-2}"</c>, <c>@"shell:AppsFolder\WinStoreAppId"</c>. /// - File type or protocol, like <c>".txt"</c>, <c>"http:"</c>. /// - Icon resource index or negative id, like "c:\file.dll,4", "c:\file.dll,-4". /// - URL. /// </param> /// <param name="size">Icon width and height. If 0 (default), uses <see cref="SizeSmall"/>.</param> /// <param name="flags"></param> /// <remarks> /// If not full path, the function uses <see cref="AFolders.ThisAppImages"/> and <see cref="AFile.SearchPath"/>. /// /// ITEMIDLIST can be of any file, folder, URL or virtual object like Control Panel. See <see cref="APidl.ToBase64String"/>. /// </remarks> public static Icon GetFileIcon(string file, int size = 0, IconGetFlags flags = 0) => HandleToIcon(GetFileIconHandle(file, size, flags), true);