ファイラーその4
アイコンをつける。
Win32apiのSHGetFileInfoを呼べるようにする
[StructLayout(LayoutKind.Sequential)] public struct SHFILEINFO { public IntPtr hIcon; public IntPtr iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; class Win32 { public const uint SHGFI_ICON = 0x100; public const uint SHGFI_LARGEICON = 0x0; // 'Large icon public const uint SHGFI_SMALLICON = 0x1; // 'Small icon [DllImport("shell32.dll")] public static extern IntPtr SHGetFileInfo( string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); [DllImport("user32")] public static extern int DestroyIcon(IntPtr hIcon); }
ファイルパスからアイコン画像を得る。ObservableCollection
class Item { public FileSystemInfo Info { set; get; } public String Name { get { return Info.Name; } } public String Length { get { var file = Info as FileInfo; if (file == null) { return ""; } else { return file.Length.ToString(); } } } public BitmapSource Bitmap { get { SHFILEINFO shinfo = new SHFILEINFO(); var hImgLarge = Win32.SHGetFileInfo(Info.FullName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON); BitmapSource source = Imaging.CreateBitmapSourceFromHIcon(shinfo.hIcon, Int32Rect.Empty, null); Win32.DestroyIcon(shinfo.hIcon); return source; } } };
ListViewのDataTemplateにBitmapをバインディングする
<ListView Grid.Row="1" ItemsSource="{Binding Path=Files}" AlternationCount="2"> <ListView.View> <GridView> <GridView.Columns> <GridViewColumn Header="Name"> <GridViewColumn.CellTemplate> <DataTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Image Grid.Column="0" Source="{Binding Path=Bitmap}" Margin="5,0,5,0" /> <Label Grid.Column="1" Content="{Binding Path=Name}"/> </Grid> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn Header="Size"> <GridViewColumn.CellTemplate> <DataTemplate> <Label Content="{Binding Path=Length}" HorizontalAlignment="Right"/> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> </GridView.Columns> </GridView> </ListView.View> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}" > <Setter Property="HorizontalContentAlignment" Value="Stretch" /> <EventSetter Event="MouseDoubleClick" Handler="listBoxItem_DoubleClick"/> </Style> </ListView.ItemContainerStyle> </ListView>
アイコンが出るようになった。
別スレッドでアイコン画像の読み込みをする
public DirectoryInfo Current { get { return current_; } set { current_ = value; NotifyPropertyChanged("Current"); NotifyPropertyChanged("Path"); files_.Clear(); var workList=new List<Item>(); try { foreach (var e in current_.GetFileSystemInfos()) { // FileSystemInfoだけのリストを作って、 // 後でアイコン画像をロードする var item=new Item { Info = e }; files_.Add(item); workList.Add(item); } // 別スレッドでビットマップ更新を呼び出す var task = new Task(() => { foreach (var item in workList) { var source = LoadBitmapSource(item.Info); source.Freeze(); // 重要 Action action = () => { // UIスレッド item.Bitmap = source; }; dispatcher_.Invoke(action); } }); task.Start(); } catch (UnauthorizedAccessException e) { // do nothing } catch (DirectoryNotFoundException e) { // do nothing } } }