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);
}
}
}