Loading [MathJax]/extensions/tex2jax.js

2011年3月13日日曜日

C#でアイコン取得2 (マイコンピュータ)

やりたいこと
前回の方法で、ファイルやフォルダのパスがわかれば、そのアイコンを取得することが可能になりました。

ただ、この方法だとマイコンピュータのアイコンがとれない。。。

で、いろいろ調べたら方法がわかったのでまとめておきます。

こんなのをつくる。
OKボタンを押すとマイコンピュータのアイコンが表示される。

ポイント

前回との差異を中心に説明すると。

①SHGetFileInfo()の第一引数がポインタのものを準備する。またフラグにpidl用のフラグを追加。
※ここがよくわからず、ずっとpidlをstringに変換して渡そうなどとして壁にぶつかっていた。。。

②SHGetSpecialFolderLocation()にて、mycomputerのpidlを取得。
※pidlはパスの代わりになるようなものという理解でよさそう。

③ウィンドウハンドルはFormがもっており、this.handleで取り出すことができる。
これをapiにわたせばよい。(GetActiveWindowなどでとろうとしてちょっと苦労した。。。)

④pidlは解放する必要がある。

コード
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Text;  
  7. using System.Windows.Forms;  
  8. using System.Runtime.InteropServices;  
  9.   
  10. namespace GetMyComputerIcon  
  11. {  
  12.     public partial class Form1 : Form  
  13.     {  
  14.         private int nIndex = 0;  
  15.   
  16.         public Form1()  
  17.         {  
  18.             InitializeComponent();  
  19.         }  
  20.         //===================  
  21.         // ボタン押下時のイベントハンドラ  
  22.         //===================  
  23.         private void button1_Click(object sender, EventArgs e)  
  24.         {  
  25.   
  26.             IntPtr hImgSmall; //the handle to the system image list  
  27.             IntPtr hImgLarge; //the handle to the system image list  
  28.             SHFILEINFO shinfo = new SHFILEINFO();  
  29.   
  30.             listView1.SmallImageList = imageList1;  
  31.             listView1.LargeImageList = imageList1;  
  32.   
  33.             FolderID startLocation = FolderID.MyComputer;  
  34.             IntPtr pidlRoot = IntPtr.Zero;  
  35.   
  36.             Win32.SHGetSpecialFolderLocation(this.Handle, (int)startLocation, out pidlRoot);  
  37.   
  38.             //Use this to get the small Icon  
  39.             hImgSmall = Win32.SHGetFileInfo(pidlRoot, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON | Win32.SHGFI_PIDL);  
  40.   
  41.             //Use this to get the large Icon  
  42.             //hImgLarge = Win32.SHGetFileInfo(pidlRoot, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON | Win32.SHGFI_PIDL);  
  43.   
  44.             //The icon is returned in the hIcon member of the shinfo struct  
  45.             System.Drawing.Icon myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);  
  46.   
  47.             imageList1.Images.Add(myIcon);  
  48.   
  49.             //Add file name and icon to listview  
  50.             listView1.Items.Add("my computer", nIndex++);  
  51.   
  52.             // pidlを解放する。   
  53.             if (pidlRoot != IntPtr.Zero)  
  54.             {  
  55.                 Win32.IMalloc malloc;  
  56.                 int nret = Win32.SHGetMalloc(out malloc);  
  57.                 malloc.Free(pidlRoot);  
  58.             }  
  59.         }  
  60.     }  
  61.   
  62.     [StructLayout(LayoutKind.Sequential)]  
  63.     public struct SHFILEINFO  
  64.     {  
  65.         public IntPtr hIcon;  
  66.         public IntPtr iIcon;  
  67.         public uint dwAttributes;  
  68.         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]  
  69.         public string szDisplayName;  
  70.         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]  
  71.         public string szTypeName;  
  72.     };  
  73.   
  74.     //===================  
  75.     // win 32 api dll import  
  76.     //===================  
  77.     class Win32  
  78.     {  
  79.         // SHGetFileInfo用のフラグ。   
  80.         public const uint SHGFI_ICON = 0x100;  
  81.         public const uint SHGFI_LARGEICON = 0x0; // 'Large icon  
  82.         public const uint SHGFI_SMALLICON = 0x1; // 'Small icon  
  83.         public const uint SHGFI_PIDL = 0x8; // pidl  
  84.   
  85.         //[DllImport("shell32.dll")]   こちらはパスからアイコン取得するときに必要。今回は不要。  
  86.         //public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);  
  87.   
  88.         [DllImport("shell32.dll")] // これが重要。  
  89.         public static extern IntPtr SHGetFileInfo(IntPtr pIDL, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);  
  90.   
  91.   
  92.         [DllImport("Shell32.DLL")] // こちらで特殊フォルダのpidlを取得する。  
  93.         public static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, int nFolder, out IntPtr ppidl);  
  94.   
  95.         // pidlのfree用   
  96.         [InterfaceType(ComInterfaceType.InterfaceIsIUnknown),  
  97.            Guid("00000002-0000-0000-C000-000000000046")]  
  98.         public interface IMalloc  
  99.         {  
  100.             [PreserveSig]  
  101.             IntPtr Alloc([In] int cb);  
  102.             [PreserveSig]  
  103.             IntPtr Realloc([In] IntPtr pv, [In] int cb);  
  104.             [PreserveSig]  
  105.             void Free([In] IntPtr pv);  
  106.             [PreserveSig]  
  107.             int GetSize([In] IntPtr pv);  
  108.             [PreserveSig]  
  109.             int DidAlloc(IntPtr pv);  
  110.             [PreserveSig]  
  111.             void HeapMinimize();  
  112.         }  
  113.         [DllImport("Shell32.DLL")]  
  114.         public static extern int SHGetMalloc(out IMalloc ppMalloc);  
  115.     }  
  116.   
  117.     //===================  
  118.     // SHGetSpecialFolderLocationに使用するFolderのIDの定義。  
  119.     // ここをかえるといろいろな特殊フォルダpidlが取得できる。  
  120.     //===================  
  121.     public enum FolderID  
  122.     {  
  123.         Desktop = 0x0000,  
  124.         Printers = 0x0004,  
  125.         MyDocuments = 0x0005,  
  126.         Favorites = 0x0006,  
  127.         Recent = 0x0008,  
  128.         SendTo = 0x0009,  
  129.         StartMenu = 0x000b,  
  130.         MyComputer = 0x0011,  
  131.         NetworkNeighborhood = 0x0012,  
  132.         Templates = 0x0015,  
  133.         MyPictures = 0x0027,  
  134.         NetAndDialUpConnections = 0x0031,  
  135.     }  
  136. }  

参考
・Visual C# を使用して [フォルダの参照] コモン ダイアログ ボックスをラップするマネージ コンポーネントを実装する方法
http://support.microsoft.com/kb/306285/ja

・シェルネームスペースとPIDL
http://yokohama.cool.ne.jp/chokuto/urawaza/com/shell3.html
0 件のコメント:
コメントを投稿