using System; using System.IO; using System.Runtime.InteropServices; using System.Drawing; using System.Drawing.Imaging; using NaGet.Packages; using NaGet.Packages.Install; namespace AppliStation.Util { /// /// GUIに関する雑多な関数 /// public sealed class GUIUtils { #region ExtraIcon関連 [DllImport("shell32.dll")] private static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex); [DllImport("user32.dll", SetLastError=true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool DestroyIcon(IntPtr hIcon); /// /// アイコンファイル(実行ファイル・DLL)を開いてアイコンを作る /// /// 内部でコピーされるのでWin32APIのDestroyIconを使わないでいいが、やや遅い動作 /// ハンドラ /// 対象ファイル /// アイコンインデックス /// 生成されたアイコン public static Icon ExtractIcon(System.Windows.Forms.Form form, string lpszExeFileName, uint nIconIndex) { Icon ico = null; if (! File.Exists(lpszExeFileName)) { ico = Icon.ExtractAssociatedIcon(lpszExeFileName); // ExtractAssociatedIconに例外を吐いてもらう } else { IntPtr hInst = (form != null)? form.Handle : IntPtr.Zero; IntPtr hIcon = IntPtr.Zero; try { hIcon = ExtractIcon(hInst, lpszExeFileName, (int) nIconIndex); if ((hIcon != IntPtr.Zero) && (hIcon.ToInt32() != 2)) { ico = (Icon) Icon.FromHandle(hIcon).Clone(); DestroyIcon(hIcon); } } catch (System.Runtime.InteropServices.COMException) { // ExtraIconのP/Invoke失敗時用 } } return ico; } /// /// アイコンファイル(実行ファイル・DLL)を開いてアイコンを作る /// /// ハンドラ /// 対象ファイルとアイコンインデックスの文字列表現 /// 生成されたアイコン。 public static Icon ExtractIcon(System.Windows.Forms.Form form, string lpszExeFileNameAndIndex) { int index = lpszExeFileNameAndIndex.LastIndexOf(','); if (index >= 0) { uint nIconIndex = uint.Parse(lpszExeFileNameAndIndex.Substring(index+1)); return ExtractIcon(form, lpszExeFileNameAndIndex.Substring(0, index), nIconIndex); } else { return Icon.ExtractAssociatedIcon(lpszExeFileNameAndIndex); } } /// /// シェルからフォルダアイコンを生成して返す /// /// フォルダアイコン public static Icon GetShellIconForFolder() { // Vista以降ならば、SHGetStockIconInfo(SIID_FOLDER, SHGSI_ICON, &sInfo); をP/Invoke呼び出しするのが王道かと string windir = Environment.GetEnvironmentVariable("windir"); return ExtractIcon(null, Path.Combine(windir, @"system32\shell32.dll"), 3); } #endregion /// /// パッケージに対応するアイコンを返す /// /// パッケージ /// 対応するアイコン。検出できなかった場合はnull。 public static Icon GetIconForPackage(InstalledPackage pkg) { Icon ico = null; string iconPath = pkg.UninstallInfo.IconPath; if (! string.IsNullOrEmpty(iconPath)) { ico = ExtractIcon(null, iconPath); } else if (pkg.Type == InstallerType.ARCHIVE) { string progGrp = Path.Combine(NaGet.Env.ArchiveProgramGroup, pkg.Name); if (Directory.Exists(progGrp)) { string[] lnkFiles = Directory.GetFiles(progGrp, "*.lnk"); if (lnkFiles.Length >= 1) { try { using (NaGet.InteropServices.ShellLink link = new NaGet.InteropServices.ShellLink(lnkFiles[0])) { if (File.Exists(link.GetPath(0))) { ico = Icon.ExtractAssociatedIcon(link.GetPath(0)); } } } catch (System.Runtime.InteropServices.COMException) { // ShellLinkのオープンあるいは、リンク先解決に失敗した場合 } } } } return ico; } /// /// グレーアウトアイコンを作るための ImageAttributes を作って返す。 /// /// 透明度。(1.0が不透明、0.0が完全透明) /// 生成されたImageAttributes public static ImageAttributes GetImageAttributeToGrayOut(float alpha) { // RGB比率として、YIQカラーモデルの値を採用する const float r = 0.298912f; const float g = 0.586611f; const float b = 0.114478f; ColorMatrix cm = new ColorMatrix(new float[][]{ new float[]{r, r, r, 0, 0}, new float[]{g, g, g, 0, 0}, new float[]{b, b, b, 0, 0}, new float[]{0, 0, 0, alpha, 0}, new float[]{0, 0, 0, 0, 1}, }); ImageAttributes ia = new ImageAttributes(); ia.SetColorMatrix(cm); return ia; } /// /// 画像を指定領域の真中に描く /// /// 描画対象のグラフィックス /// 画像 /// 指定領域 /// ImageAttributes。nullでもかまわない public static void Graphics_DrawCenterImage(Graphics g, Image img, Rectangle b, ImageAttributes ia) { int x = b.Left + (b.Width - img.Width ) / 2; int y = b.Top + (b.Height - img.Height) / 2; g.DrawImage(img, new Rectangle(x, y, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia); } } }