From: ttp Date: Sat, 22 Nov 2008 15:40:23 +0000 (+0000) Subject: AppliStation-GUI,アイコン生成メソッドの改良およびそれに伴う変更 X-Git-Tag: v1.1.0~3 X-Git-Url: http://git.sourceforge.jp/view?p=applistation%2FAppliStation.git;a=commitdiff_plain;h=32bc8532eff2826912feb85062514c69f3542355;ds=inline AppliStation-GUI,アイコン生成メソッドの改良およびそれに伴う変更 git-svn-id: http://localhost/svn/AppliStation/trunk@990 34ed2c89-c49f-4a4b-abdb-c318350108cf --- diff --git a/AppliStation/AppliStation.Util/GUIUtils.cs b/AppliStation/AppliStation.Util/GUIUtils.cs index 486bfa8..737f897 100644 --- a/AppliStation/AppliStation.Util/GUIUtils.cs +++ b/AppliStation/AppliStation.Util/GUIUtils.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Runtime.InteropServices; using System.Drawing; using System.Drawing.Imaging; using NaGet.Packages; @@ -12,6 +13,76 @@ namespace AppliStation.Util /// 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 + /// /// パッケージに対応するアイコンを返す /// @@ -19,14 +90,10 @@ namespace AppliStation.Util /// 対応するアイコン。検出できなかった場合はnull。 public static Icon GetIconForPackage(InstalledPackage pkg) { + Icon ico = null; string iconPath = pkg.UninstallInfo.IconPath; if (! string.IsNullOrEmpty(iconPath)) { - if (iconPath.EndsWith(",0") || iconPath.EndsWith(",-0")) { - iconPath = iconPath.Substring(0, iconPath.LastIndexOf(',')); - } - if (File.Exists(iconPath)) { - return Icon.ExtractAssociatedIcon(iconPath); - } + ico = ExtractIcon(null, iconPath); } else if (pkg.Type == InstallerType.ARCHIVE) { string progGrp = Path.Combine(NaGet.Env.ArchiveProgramGroup, pkg.Name); if (Directory.Exists(progGrp)) { @@ -36,7 +103,7 @@ namespace AppliStation.Util try { using (NaGet.InteropServices.ShellLink link = new NaGet.InteropServices.ShellLink(lnkFiles[0])) { if (File.Exists(link.GetPath(0))) { - return Icon.ExtractAssociatedIcon(link.GetPath(0)); + ico = Icon.ExtractAssociatedIcon(link.GetPath(0)); } } } catch (System.Runtime.InteropServices.COMException) { @@ -45,7 +112,7 @@ namespace AppliStation.Util } } } - return null; + return ico; } /// diff --git a/AppliStation/AppliStation.Util/ToolStripPetitLauncherMenuItem.cs b/AppliStation/AppliStation.Util/ToolStripPetitLauncherMenuItem.cs index 8d7040c..b90d674 100644 --- a/AppliStation/AppliStation.Util/ToolStripPetitLauncherMenuItem.cs +++ b/AppliStation/AppliStation.Util/ToolStripPetitLauncherMenuItem.cs @@ -44,7 +44,7 @@ namespace AppliStation.Util public void BuildItems() { if (thread != null) { - if (! thread.Join(1000)) { + if (! thread.Join(500)) { thread.Interrupt(); } thread = null; @@ -81,6 +81,27 @@ namespace AppliStation.Util } } + private void _insertItemFor(string filepath, ref bool cmdIsAdded) + { + string extension = Path.GetExtension(filepath).ToLower(); + if (extension == ".exe") { + switch (NaGet.InteropServices.PEFileInfoUtils.GetPEFileType(filepath)) { + case NaGet.InteropServices.PEFileInfoUtils.PEFileType.WinGUI: + _addToItemsInv(CreateMenuItemForFile(filepath)); + break; + case NaGet.InteropServices.PEFileInfoUtils.PEFileType.WinConsole: + case NaGet.InteropServices.PEFileInfoUtils.PEFileType.MSDosCom: + if (! cmdIsAdded) { + _insertToItemsInv(0, CreateMenuItemForCmdAt(Path.GetDirectoryName(filepath))); + cmdIsAdded = true; + } + break; + } + } else if ((extension == ".bat") || (extension == ".lnk")) { + _addToItemsInv(CreateMenuItemForFile(filepath)); + } + } + private void buildItems() { @@ -92,21 +113,11 @@ namespace AppliStation.Util _addToItemsInv(CreateMenuItemForFolder(folderPath)); _addToItemsInv(sep); - if (Directory.Exists(folderPath)) { - foreach (string exeFile in Directory.GetFiles(folderPath, "*.exe")) { + if (Directory.Exists(folderPath)) { + foreach (string filepath in Directory.GetFiles(folderPath)) { if (baseFolderPath != folderPath) return; // 途中でなんか操作されているならば終了 - switch (NaGet.InteropServices.PEFileInfoUtils.GetPEFileType(exeFile)) { - case NaGet.InteropServices.PEFileInfoUtils.PEFileType.WinGUI: - _addToItemsInv(CreateMenuItemForFile(exeFile)); - break; - case NaGet.InteropServices.PEFileInfoUtils.PEFileType.WinConsole: - if (! cmdIsAdded) { - _insertToItemsInv(0, CreateMenuItemForCmdAt(folderPath)); - cmdIsAdded = true; - } - break; - } + _insertItemFor(filepath, ref cmdIsAdded); } } } catch (ThreadInterruptedException) {} @@ -122,6 +133,7 @@ namespace AppliStation.Util public static ToolStripMenuItem CreateMenuItemForFolder(string folderPath) { ToolStripMenuItem item = CreateMenuItemForFile(folderPath); + item.Image = GUIUtils.GetShellIconForFolder().ToBitmap(); item.Text = "フォルダを開く(&O)"; return item; }