OSDN Git Service

AppliStation-GUI,アイコン生成メソッドの改良およびそれに伴う変更
authorttp <ttp@users.sourceforge.jp>
Sat, 22 Nov 2008 15:40:23 +0000 (15:40 +0000)
committerttp <ttp@users.sourceforge.jp>
Sat, 22 Nov 2008 15:40:23 +0000 (15:40 +0000)
git-svn-id: http://localhost/svn/AppliStation/trunk@990 34ed2c89-c49f-4a4b-abdb-c318350108cf

AppliStation/AppliStation.Util/GUIUtils.cs
AppliStation/AppliStation.Util/ToolStripPetitLauncherMenuItem.cs

index 486bfa8..737f897 100644 (file)
@@ -1,5 +1,6 @@
 using System;\r
 using System.IO;\r
+using System.Runtime.InteropServices;\r
 using System.Drawing;\r
 using System.Drawing.Imaging;\r
 using NaGet.Packages;\r
@@ -12,6 +13,76 @@ namespace AppliStation.Util
        /// </summary>\r
        public sealed class GUIUtils\r
        {\r
+               #region ExtraIcon関連\r
+               \r
+               [DllImport("shell32.dll")]\r
+               private static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);\r
+               \r
+               [DllImport("user32.dll", SetLastError=true)]\r
+               [return: MarshalAs(UnmanagedType.Bool)]\r
+               private static extern bool DestroyIcon(IntPtr hIcon);\r
+               \r
+               /// <summary>\r
+               /// アイコンファイル(実行ファイル・DLL)を開いてアイコンを作る\r
+               /// </summary>\r
+               /// <remarks>内部でコピーされるのでWin32APIのDestroyIconを使わないでいいが、やや遅い動作</remarks>\r
+               /// <param name="form">ハンドラ</param>\r
+               /// <param name="lpszExeFileName">対象ファイル</param>\r
+               /// <param name="nIconIndex">アイコンインデックス</param>\r
+               /// <returns>生成されたアイコン</returns>\r
+               public static Icon ExtractIcon(System.Windows.Forms.Form form, string lpszExeFileName, uint nIconIndex)\r
+               {\r
+                       Icon ico = null;\r
+                       \r
+                       if (! File.Exists(lpszExeFileName)) {\r
+                               ico = Icon.ExtractAssociatedIcon(lpszExeFileName); // ExtractAssociatedIconに例外を吐いてもらう\r
+                       } else {\r
+                               IntPtr hInst = (form != null)? form.Handle : IntPtr.Zero;\r
+                               IntPtr hIcon = IntPtr.Zero;\r
+                               \r
+                               try {\r
+                                       hIcon = ExtractIcon(hInst, lpszExeFileName, (int) nIconIndex);\r
+                                       if ((hIcon != IntPtr.Zero) && (hIcon.ToInt32() != 2)) {\r
+                                               ico = (Icon) Icon.FromHandle(hIcon).Clone();\r
+                                               DestroyIcon(hIcon);\r
+                                       }\r
+                               } catch (System.Runtime.InteropServices.COMException) {\r
+                                       // ExtraIconのP/Invoke失敗時用\r
+                               }\r
+                       }\r
+                       return ico;\r
+               }\r
+               \r
+               /// <summary>\r
+               /// アイコンファイル(実行ファイル・DLL)を開いてアイコンを作る\r
+               /// </summary>\r
+               /// <param name="form">ハンドラ</param>\r
+               /// <param name="lpszExeFileNameAndIndex">対象ファイルとアイコンインデックスの文字列表現</param>\r
+               /// <returns>生成されたアイコン。</returns>\r
+               public static Icon ExtractIcon(System.Windows.Forms.Form form, string lpszExeFileNameAndIndex)\r
+               {\r
+                       int index = lpszExeFileNameAndIndex.LastIndexOf(',');\r
+                       if (index >= 0) {\r
+                               uint nIconIndex = uint.Parse(lpszExeFileNameAndIndex.Substring(index+1));\r
+                               return ExtractIcon(form, lpszExeFileNameAndIndex.Substring(0, index), nIconIndex);\r
+                       } else {\r
+                               return Icon.ExtractAssociatedIcon(lpszExeFileNameAndIndex);\r
+                       }\r
+               }\r
+               \r
+               /// <summary>\r
+               /// シェルからフォルダアイコンを生成して返す\r
+               /// </summary>\r
+               /// <returns>フォルダアイコン</returns>\r
+               public static Icon GetShellIconForFolder()\r
+               {\r
+                       // Vista以降ならば、SHGetStockIconInfo(SIID_FOLDER, SHGSI_ICON, &sInfo); をP/Invoke呼び出しするのが王道かと\r
+                       string windir = Environment.GetEnvironmentVariable("windir");\r
+                       return ExtractIcon(null, Path.Combine(windir, @"system32\shell32.dll"), 3);\r
+               }\r
+               \r
+               #endregion\r
+               \r
                /// <summary>\r
                /// パッケージに対応するアイコンを返す\r
                /// </summary>\r
@@ -19,14 +90,10 @@ namespace AppliStation.Util
                /// <returns>対応するアイコン。検出できなかった場合はnull。</returns>\r
                public static Icon GetIconForPackage(InstalledPackage pkg)\r
                {\r
+                       Icon ico = null;\r
                        string iconPath = pkg.UninstallInfo.IconPath;\r
                        if (! string.IsNullOrEmpty(iconPath)) {\r
-                               if (iconPath.EndsWith(",0") || iconPath.EndsWith(",-0")) {\r
-                                       iconPath = iconPath.Substring(0, iconPath.LastIndexOf(','));\r
-                               }\r
-                               if (File.Exists(iconPath)) {\r
-                                       return Icon.ExtractAssociatedIcon(iconPath);\r
-                               }\r
+                               ico = ExtractIcon(null, iconPath);\r
                        } else if (pkg.Type == InstallerType.ARCHIVE) {\r
                                string progGrp = Path.Combine(NaGet.Env.ArchiveProgramGroup, pkg.Name);\r
                                if (Directory.Exists(progGrp)) {\r
@@ -36,7 +103,7 @@ namespace AppliStation.Util
                                                try {\r
                                                        using (NaGet.InteropServices.ShellLink link = new NaGet.InteropServices.ShellLink(lnkFiles[0])) {\r
                                                                if (File.Exists(link.GetPath(0))) {\r
-                                                                       return Icon.ExtractAssociatedIcon(link.GetPath(0));\r
+                                                                       ico = Icon.ExtractAssociatedIcon(link.GetPath(0));\r
                                                                }\r
                                                        }\r
                                                } catch (System.Runtime.InteropServices.COMException) {\r
@@ -45,7 +112,7 @@ namespace AppliStation.Util
                                        }\r
                                }\r
                        }\r
-                       return null;\r
+                       return ico;\r
                }\r
                \r
                /// <summary>\r
index 8d7040c..b90d674 100644 (file)
@@ -44,7 +44,7 @@ namespace AppliStation.Util
                public void BuildItems()\r
                {\r
                        if (thread != null) {\r
-                               if (! thread.Join(1000)) {\r
+                               if (! thread.Join(500)) {\r
                                        thread.Interrupt();\r
                                }\r
                                thread = null;\r
@@ -81,6 +81,27 @@ namespace AppliStation.Util
                        }\r
                }\r
                \r
+               private void _insertItemFor(string filepath, ref bool cmdIsAdded)\r
+               {\r
+                       string extension = Path.GetExtension(filepath).ToLower();\r
+                       if (extension == ".exe") {\r
+                               switch (NaGet.InteropServices.PEFileInfoUtils.GetPEFileType(filepath)) {\r
+                                       case NaGet.InteropServices.PEFileInfoUtils.PEFileType.WinGUI:\r
+                                               _addToItemsInv(CreateMenuItemForFile(filepath));\r
+                                               break;\r
+                                       case NaGet.InteropServices.PEFileInfoUtils.PEFileType.WinConsole:\r
+                                       case NaGet.InteropServices.PEFileInfoUtils.PEFileType.MSDosCom:\r
+                                               if (! cmdIsAdded) {\r
+                                                       _insertToItemsInv(0, CreateMenuItemForCmdAt(Path.GetDirectoryName(filepath)));\r
+                                                       cmdIsAdded = true;\r
+                                               }\r
+                                               break;\r
+                               }\r
+                       } else if ((extension == ".bat") || (extension == ".lnk")) {\r
+                               _addToItemsInv(CreateMenuItemForFile(filepath));\r
+                       }\r
+               }\r
+               \r
                        \r
                private void buildItems()\r
                {\r
@@ -92,21 +113,11 @@ namespace AppliStation.Util
                                _addToItemsInv(CreateMenuItemForFolder(folderPath));\r
                                _addToItemsInv(sep);\r
                                \r
-                               if (Directory.Exists(folderPath)) {\r
-                                       foreach (string exeFile in Directory.GetFiles(folderPath, "*.exe")) {\r
+                               if (Directory.Exists(folderPath)) {                                     \r
+                                       foreach (string filepath in Directory.GetFiles(folderPath)) {\r
                                                if (baseFolderPath != folderPath) return; // 途中でなんか操作されているならば終了\r
                                                \r
-                                               switch (NaGet.InteropServices.PEFileInfoUtils.GetPEFileType(exeFile)) {\r
-                                                       case NaGet.InteropServices.PEFileInfoUtils.PEFileType.WinGUI:\r
-                                                               _addToItemsInv(CreateMenuItemForFile(exeFile));\r
-                                                               break;\r
-                                                       case NaGet.InteropServices.PEFileInfoUtils.PEFileType.WinConsole:\r
-                                                               if (! cmdIsAdded) {\r
-                                                                       _insertToItemsInv(0, CreateMenuItemForCmdAt(folderPath));\r
-                                                                       cmdIsAdded = true;\r
-                                                               }\r
-                                                               break;\r
-                                               }\r
+                                               _insertItemFor(filepath, ref cmdIsAdded);\r
                                        }\r
                                }\r
                        } catch (ThreadInterruptedException) {}\r
@@ -122,6 +133,7 @@ namespace AppliStation.Util
                public static ToolStripMenuItem CreateMenuItemForFolder(string folderPath)\r
                {\r
                        ToolStripMenuItem item = CreateMenuItemForFile(folderPath);\r
+                       item.Image = GUIUtils.GetShellIconForFolder().ToBitmap();\r
                        item.Text = "フォルダを開く(&O)";\r
                        return item;\r
                }\r