Visual Basic 初級講座
VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

 

Visual Basic 中学校 > 初級講座 >

第25回 実技2 フォルダ情報一覧

今回は フォルダのサイズ・ファイル数・フォルダ数を一覧表示するソフトを作ります。これはWindowsにはない機能ですのである程度の使いではあると思います。とくにフォルダのサイズがわかるとハードディスクを整理するときに便利なのが嬉しいです。

今回のソフトの作成にあたってはこれまで初級講座で解説してきたコントロールの知識はあまり使いません。初級講座ではコントロールの一般的な説明をしてきただけで個別のコントロールの具体的な使用方法については説明していないからです。

しかしながら、今回の目標は実際にいろいろなコントロールを使って「使えるアプリケーション」を作る手順を体験してもらうことです。未知のコントロールや未知のプログラミング技法は余裕綽々(よゆうしゃくしゃく)で受け流してください。一応簡単な解説もしてあります。

この回の要約

・フォルダ情報一覧ソフトを作る

便宜のために完成版をダウンロードできるようにしておきます。実際に動かしながら説明を読みたい方は先にダウンロードしてください。

完成版 フォルダ情報一覧 10.85KB lha形式(拡張子lzh)

 

 

1.今回作るソフトの機能

 

はじめにこれから作るソフトの主な機能・使い方を説明します。

■画像1:完成版

ソフトは左側のフォルダツリーと右側の一覧にわかれます。左側のツリーで選択したフォルダに含まれるファイルとフォルダの一覧が右側の一覧部分に表示されます。このとき、ファイルについてはサイズも表示されます。

一覧で、フォルダのサイズ・ファイル数・フォルダ数を表示するには[詳細表示]ボタンをクリックします。ここでいうサイズ等はエクスプロらーでファイルを右クリックして表示されるプロパティ画面の値と同じですべてのサブフォルダの合計です。

一覧はタイトルの部分をクリックすることで並び替えることもできます。たとえば、サイズ順に並び替えたければ「サイズ」と書かれているタイトルをクリックします。クリックするたびに降順と昇順が入れ替わります。

「自動的に詳細を表示する」チェックボックスをチェックしている場合は左側のツリーでフォルダを選択した段階で一覧にフォルダのサイズ・ファイル数・フォルダ数も表示されますが、これらを計算するためには時間がかかりますので注意です。

その他の小さな機能として一覧部分でファイルやフォルダをクリックすると、そのファイルやフォルダを開くことができます。また、ステータスバーには現在一覧しているフォルダのフルパスが表示されます。

 

2.ファイル・フォルダの一覧とループ

 

実際の作業の説明に入る前にファイル・フォルダの一覧とループについて簡単に説明しておきます。今回のソフトではファイル・フォルダの一覧をループで処理する個所が何箇所かあるので最初にこの点を知っておくとプログラムの理解の助けになると思います。

VBではフォルダの情報を取得したりフォルダを操作するときにDirectoryInfoクラス(読み方:DirectoryInfo = ディレクトリインフォ)を使うのが一般的です。このクラスはインスタンス化するとき(つまりNewを使うとき)に対象のフォルダをフルパスで指定します。たとえば、C:\Program Files\を表すDirectoryInfoクラスのインスタンスを作成するには次のようにします。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応


Dim
Folder As New IO.DirectoryInfo("C:\Program Files\")
 

■リスト1:DirectoryInfoクラスのインスタンシング

これだけでもこのフォルダに対して情報を取得したり操作するためのメソッドやプロパティが使えるようになるので便利なのですがその中でもGetFilesメソッド(読み方:GetFiles = ゲットファイルズ)とGetDirectoriesメソッド(読み方:GetDirectories = ゲットディレクトリーズ)はそれぞれ、そのフォルダの直下にあるファイルの一覧とフォルダの一覧を返すのでよく使います。

このメソッドの詳しい使い方は今後の初級講座で解説します。ここではこの2つを使ってファイルやフォルダを1つずつ処理していくループの記述方法だけ紹介します。

次のように記述するとこのフォルダに属するフォルダの名前がひとつずつリストボックスに追加されていきます。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Dim Folder As New IO.DirectoryInfo("C:\Program Files\")
Dim oFolder As IO.DirectoryInfo

For Each oFolder In Folder.GetDirectories
    ListBox1.Items.Add(oFolder.Name)
Next

■リスト2:フォルダの列挙

ここでは説明を簡単にするために名前だけを取り出していますが、変数oFolderDirectoryInfo型ですので名前以外にもさまざまな情報を取り出すことができます。とにかくFor EachNextループとGetDirectoriesメソッドを組み合わせた処理は何かと使う機会がありますので丸暗記しても良いくらいです。For EachNext ループについては次々回かその次くらいで解説する予定です。

ファイルの場合はFileInfoクラス(読み方:FileInfo = ファイルインフォ)を使って次のようにループを回します。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Dim Folder As New IO.DirectoryInfo("C:\Windows\")
Dim oFile As IO.FileInfo

For Each oFile In Folder.GetFiles
    ListBox1.Items.Add(oFile.Name)
Next

■リスト3:ファイルの列挙

 

3.画面の配置

 

前置きはこのくらいにしてそろそろプログラムを開始します。新規プロジェクトを作成し、名前はFolderInfoとしてください。

フォームには次の通りにコントロールを配置してください。

■画像2:コントロールの配置。ここには表示されてないがImageListも配置する(本文参照)。

コントロールを配置する順番は重要です。次の順番では位置してください。

StatusBar1
Splitter1
tvFolders(TreeView)
Panel1
lvFolder(ListView)
その他のコントロール

■表1:配置する順番

他の順番で配置してもZオーダーを調節すればなんとかなりますが、下手な順番で配置するとDockプロパティによる配置の制御がうまくいかないので面倒です。

この他に、ImageListも配置してください。ImageListはフォームに貼り付けると、フォームではなくフォームの下の部分(コントロールトレイ)に表示されます。ImageListはツリービューやリストビューに表示するアイコンを管理するためのコントロールで、これ自体が画面に表示されると言うことはありません。

今回は第3章 コントロール の実技にあたりますのでできるだけいろいろな種類のコントロールを扱ってみました。

各コントロールのプロパティは次の通りに設定してください。プロパティに何も指定していないコントロールに対してはこの段階では何も設定する必要はありません。

コントロール 種類 プロパティ
Form1 Form Text フォルダ情報一覧
Splitter1 Splitter    
tvFolders TreeView Dock Left
    ImageList ImageList1
Panel1 Panel Dock Top
lvFolder ListView AutoArrange False
    Columns (本文中で説明)
    SmallImageList ImageList1
    Dock Fill
    View Details
btnDetail Button Text 詳細表示
chkDetail CheckBox Text 自動的に詳細を表示する
StatusBar1 StatusBar    
ImageList1 ImageList Images (本文中で説明)

■表2:コントロールのプロパティ

以上のプロパティ設定が終了した段階で実行してみる何も機能はしませんが、フォームのサイズ変更やスプリッターによる領域のサイズ変更がうまく動作することが確認できます。

 

4.リストビュー

 

ここでリストビューについてごく簡単に説明しておきます。リストビューは複数の項目を表示するためのコントロールです。この点はリストボックスなどとも共通ですが、リストビューは他のコントロールと異なり4つの違った形式で項目を表示することができます。この形式を指定するのがViewプロパティ(読み方:View = ビュー)です。

Viewプロパティには次の4つの値を設定することができます。

読み方 意味
LargeIcon ラージアイコン 大きいアイコン形式
SmallIcon スモールアイコン 小さいアイコン形式
List リスト 一覧形式
Details ディテイルズ 詳細形式

■表3:リストビューの表示形式

これらはWindowsのエクスプローラの表示形式とまったく同じです。Windowsではファイルの表示方法をアイコン・一覧・詳細などの形式から選択できますが、まさにそれがリストビューの表示形式です。「小さいアイコン形式」はWindowsXPには存在しないようですが、たしかWindows98くらいにはあったように記憶しています。

これらの表示形式のうち詳細形式がもっとも重要です。詳細形式の場合は他の形式とことなり複数の情報を表示することができるからです。他の形式ではファイルの「名前」を表示するだけで終わってしまいますが、詳細形式なら「名前」の他に「サイズ」どの「ファイル数」だのいろいろな情報を表示することができます。リストビューのメソッドやプロパティでも詳細形式の場合でしか使わないものが多いです。

このようにリストビューはなかなか便利なのですが、多機能なために使い方を理解するのが少しばかり大変です。リストボックスなどは機能が単純なためにちょっと練習すればすぐ使い方がわかるのですがリストビューを使いこなすにはより多くの訓練が必要です。今回のソフト作りを通してリストビューの使い方の概要が把握できればすばらしい成果といえるでしょう。

 

5.アイコンの設定

 

さて、ツリービュー(tvFolders)やリストビュー(lvFolder)のためにあらかじめアイコンを用意しておく必要があります。用意したアイコンはImageList1Imagesプロパティ(読み方:Images = イメージス)に登録します。

まず、以下のリンクをクリックしてフォルダのアイコンをダウンロードしてください。お手元に開いているフォルダのアイコンと閉じているフォルダのアイコンがあればそれを使用しても構いません。

アイコン 767B lha形式(拡張子lzh)

アイコンを用意したら、ImageList1のプロパティウィンドウでImagesプロパティを選択します。3点ボタン( ... と表示されているボタン)をクリックしてアイコン登録画面を開いてください。

■画像3:Imagesプロパティ

ここに、[追加]ボタンを押して、閉じているフォルダのアイコンと開いているフォルダのアイコンを追加します。

■画像4:アイコンの登録

最後はOKボタンをクリックして閉じてください。

これで、ツリービュー(tvFolders)とリストビュー(lvFolders)はこのアイコンを使用できるようになります。最初にプロパティを設定したときにtvFoldersImageListプロパティとlvFoldersSmallImageListプロパティにこのImageList1を設定したことを思い出してください。

 

6.一覧の列の設定

 

次に一覧のために列を追加します。今回は名前、サイズ、ファイル数、フォルダ数を表示するので4列必要です。

プロパティウィンドウでlvFoldersColumnsプロパティ(読み方:Columns = カラムス)を選択し、3点ボタン( ... と表示されているボタン)をクリックします。

ImageListImagesを登録したのを同じようなダイアログ画面が開きますのでここに列を追加していきます。[追加]ボタンをクリックするたびに列が1つ増えるので列が4つになるようにしてください。

■画像5:列の設定

それぞれの列をクリックすると右側にプロパティが表示されるので、次の表の通りにプロパティを設定してください。

プロパティ
ColumnHeader1 Text 名前
  Width 200
ColumnHeader2 Text サイズ
  TextAlign Right
ColumnHeader3 Text ファイル数
  TextAlign Right
ColumnHeader4 Text フォルダ数
  TextAlign Right

■表4:列の設定

作業が終わったら[OK]をクリックしてダイアログを閉じてください。

このプロパティの設定の意味はわかりやすいと思います。TextAlignプロパティ(読み方:TextAlign = テキストアライン)はわかりにくいかも知れないので補足しておきます。このプロパティは表示するテキストの配置を指定するものです。Rightを指定した場合はテキストが右詰で表示されます。パソコンの世界では数値は右詰で表示するのが常識となっています。

 

7.プログラムの下準備

 

さて、コントロールの設定がようやく完了しました。いよいよプログラムに取り掛かりたいのですがもう少し準備をします。

というのは今回予定している機能の中でどうしても初級レベルを越えてしまうの部分があるのでその部分を先にコピー&貼り付けしてもらいます。この部分のプログラムは解説しません。

ここで貼り付けてもらうプログラムの内容を簡単にまとめると次の通りです。

オブジェクト名 種類 説明
FolderProperty 構造体 フォルダのサイズ・ファイル数・フォルダ数を一括管理できるように変数をまとめた物。
ItemImage 列挙体 ImageList1のアイコンの番号を記録したもの。閉じたフォルダは0番(ClosedFolder)、開いたフォルダは1番(OpenedFolder)と言った具体
FileSorter クラス リストビューに並び替え機能を提供するクラス。昇順・降順の並び替えや並び替え対象列の判断などExecuteメソッドを呼び出すだけで並び替えに対するすべてをこのクラスが実行・管理する。

■表5

表をみるとわかるのですが初級講座で初めて自作のクラスが登場します。FileSorterがそれです。FileSorterが担当するリストビューの項目を並び替える機能は意外と複雑なのでこのように自作クラスとして独立させました。

では作業に移りましょう。

ソリューションエクスプローラでFolderInfoプロジェクトを右クリックして[追加] - [クラスの追加]を選択してください。

■画像6:クラスの追加

クラス名を入力するダイアログが表示されていますがデフォルトの「Class1」のまま[OK]ボタンをクリックしてクラスを追加します。そうするとプロジェクトにクラスのためのファイルが追加されます。

■画像7:クラス追加後のソリューションエクスプローラ

このClass1をダブルクリックすると次のように記述したプログラムが現れます。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Public Class Class1

End Class

■リスト4:クラスの初期状態。このコードはすべて削除する。

これを消してまっさらにして下さい。つまり何もない状態です。

そして、この下のプログラムをコピーして貼り付けてください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Public Structure FolderProperty
    Public Size As
Long
   
Public FileCount As Long
   
Public FolderCount As Long
End
Structure
 
Public Enum ItemImage
    ClosedFolder = 0
    OpenedFolder = 1
    File = 2
End Enum
 
Public Class FileSorter
   
Implements IComparer

    Private Column As Integer
   
Private SortOrder As SortOrder = SortOrder.Descending
    Private BindingListView As ListView

    Public Sub New(ByVal BindingListView As ListView)
       
Me.BindingListView = BindingListView
    End
Sub
    Public Sub Execute(ByVal Column As Integer)

        Me.Column = Column

        If Me.SortOrder = SortOrder.Ascending Then
            Me
.SortOrder = SortOrder.Descending
       
Else
            Me
.SortOrder = SortOrder.Ascending
        End
If

        If IsNothing(BindingListView.ListViewItemSorter) Then
           
BindingListView.ListViewItemSorter = Me
        Else
           
BindingListView.Sort()
        End
If

    End Sub

    Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare

        Dim strX As String = CType(x, ListViewItem).SubItems(Column).Text
        Dim strY As String = CType(y, ListViewItem).SubItems(Column).Text
        Dim XValue As
Long
       
Dim YValue As Long
       
Dim UnitLength As Integer

        '●[名前]列の場合は単純に比較

        If Column = 0 Then
           
If SortOrder = SortOrder.Ascending Then
               
Return Comparer.Default.Compare(strX, strY) '昇順
           
Else
               
Return Comparer.Default.Compare(strY, strX) '降順
           
End If
       
End If

        '●[サイズ]列の場合は単位(" KB")を除去して数値として比較

        '▼比較できるように形式を整える
       
If Column = 1 Then
           
UnitLength = Len(" KB")
        End
If

        If strX = "" Then
           
XValue = -1 ' ""を0より小さい物として扱うための技巧的処理
       
Else
           
XValue = Left(strX, Len(strX) - UnitLength) '単位(" KB")を除去して数値のみにする。
        End If

        If strY = "" Then
           
YValue = -1 ' ""を0より小さい物として扱うための技巧的処理
       
Else
           
YValue = Left(strY, Len(strY) - UnitLength) '単位(" KB")を除去して数値のみにする。
       
End If

        '▼比較実行

        If SortOrder = SortOrder.Ascending Then
           
Return Comparer.Default.Compare(XValue, YValue) '昇順
       
Else
           
Return Comparer.Default.Compare(YValue, XValue) '降順
       
End If

    End Function

End Class

■リスト5

この作業が終わった段階でもう一度実行してみてください。何か問題があればこの段階でエラーが発生します。エラーが発生しなかった場合はここまでの作業はうまくいっています。

これ以降の作業はすべてForm1に対して行います。間違えないようにソリューションエクスプローラでForm1をダブルクリックしてForm1のデザイン画面を開いておいてください。プログラムをコピー&貼り付けするときもClass1ではなくForm1に貼り付けるように注意してください。

 

8.フォルダツリーの生成

 

いよいよメインのプログラムにとりかかります。この後はまずフォルダツリーを表示できるようにしてから、フォルダの詳細情報一覧表示をできるようにします。その後残った細かい部分を片付けます。

まずフォルダツリーの部分をプログラムする前にツリービューの仕組みについて簡単に説明しておきます。ツリービューはWindowsのエクスプローラのフォルダツリーなどでもみなれているコントロールです。ツリービューでは各項目のことを「ノード」と呼びます。そして多くのノードには親ノードと子ノードが存在すると言う構造になっています。

トップレベルのノードには親ノードが存在しません。トップレベルのノードのことを「ルートノード」とも言います。

フォルダツリーを作成する場合はじめから見えない部分も含めて全フォルダをノードとして追加するわけではありません。全フォルダを追加していたらそれだけで大変な時間がかかってしまいます。フォルダツリーでは必要な部分だけをノードとして追加します。

たとえば、一番初めに追加されるのはコンピュータのドライブを表すノードです。CやDやEなどいくつかのノードが追加されるだけです。ユーザーがCのノードを展開しようとしたときにはじめてCドライブの直下にあるフォルダの一覧がノードに追加されます。

では、具体的にプログラムを開始します。

まずはドライブの一覧をトップレベルのノードして追加するためのShowDriveNodesメソッドを記述します。次のようになります。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'■ShowDriveNodes
'■機能:フォルダツリーにドライブを表すルートノードを追加する。
Private Sub ShowDriveNodes()

    Dim Drive As String
   
Dim DriveNode As TreeNode

    For Each Drive In IO.Directory.GetLogicalDrives

        DriveNode = New TreeNode(Drive.Replace("\", ""), ItemImage.ClosedFolder, ItemImage.OpenedFolder)
        tvFolders.Nodes.Add(DriveNode)

        'Cドライブを表すノードを選択状態にする。
       
If Drive.Substring(0, 1) = "C" Then
           
tvFolders.SelectedNode = DriveNode
            DriveNode.Collapse()
'このノードを閉じる(選択状態にすると開いてしまうので)
       
End If

    Next

End Sub

■リスト6:ドライブ一覧をツリービューに追加

ドライブの一覧を取得するためにDirectoryクラスのGetLogicalDrivesメソッド(読み方:GetLogicalDrives = ゲットロジカルドライブス)を使用しています。これはさきほど説明したGetDirectoriesメソッドによるループに似ています。

ここではループを回すごとに変数Driveに"C:\"だとか"D:\"だとかドライブを表す文字列がセットされます。ノードを追加するときは後のことも考えて \ を削除してから追加します。また、追加するときにノードが開いているときと閉じているときのアイコンを指定します。アイコンの指定は番号で行います。この番号はImageList1で指定したアイコンの番号と一致します。

この部分では 0 とか 1 とか直接数値で番号を指定することは避けてItemImage.ClosedFolderのように定義済みの列挙体を通して番号を指定しています。ItemImage列挙体はさきほどClass1にはりつけたプログラムの中に含まれています。直接0とか1とか書いても動作は同じです。

これだけのことを行っているのがこの1行です。この1行は機能が多いですね。

DriveNode = New TreeNode(Drive.Replace("\", ""), ItemImage.ClosedFolder, ItemImage.OpenedFolder)

なお、ノードを表すクラスはTreeNodeクラス(読み方:TreeNode = ツリーノード)です。

はじめからCドライブを選択するようにIf文でCドライブを探す処理もこのメソッドに含まれています。

このメソッドは呼び出されなければ機能しません。フォームのLoadイベントでこのメソッドを呼び出すようにしてください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    ShowDriveNodes()

End Sub

■リスト7

参考 Loadイベントの自動生成

フォームのLoadイベントはフォームをダブルクリックすると自動的に生成されますが、今回のプログラムのようにDockプロパティを使ってコントロールが画面いっぱいに配置されている場合フォームをダブルクリックできる場所がないように思えます。

こんなときはフォームのタイトルバーをダブルクリックしてみてください。これでもLoadイベントを自動生成することができます。

この段階で実行してみるとフォルダツリーにドライブの一覧が表示されてそれらしくなってきます。

■画像8:ドライブ一覧機能まで完成したところ

今度はツリービューでノードを選択するとその下のフォルダが表示されるようにしてみます。子ノードを追加するためのメソッドAddSubNodesをプログラムに追加してください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'■AddSubNodes
'■機能:フォルダツリーの子ノードにサブフォルダを追加する。
'■引数:ParentNode 対象のノード
Private Sub AddSubNodes(ByVal ParentNode As TreeNode)

    Try

        Dim Folder As New IO.DirectoryInfo(ParentNode.FullPath & "\")
        Dim oFolder As IO.DirectoryInfo
        Dim Node As TreeNode

        For Each oFolder In Folder.GetDirectories
            Node =
New TreeNode(oFolder.Name, ItemImage.ClosedFolder, ItemImage.OpenedFolder)
            ParentNode.Nodes.Add(Node)
       
Next

    Catch ex As Exception
       
'何もしない
   
End Try

End Sub

■リスト8:フォルダ一覧をツリービューに追加

ただ単にノードを追加するのではなく、実際のフォルダ一覧を見ながらフォルダに対応するノードを追加することになるのでこのようになります。具体的には 先ほど説明したようにGetDirectoriesメソッドによるループを使用します。

このメソッドも呼び出されなければ意味がないので、ツリービューのノード選択時に呼び出すようにします。ツリービューのAfterSelectイベント(読み方:AfterSelect = アフターセレクト)に次の通りプログラムしてください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'■tvFolders_AfterSelect
'■[フォルダツリー]ノード選択時
'■機能:子ノードを追加し、フォルダ一覧を表示する。
Private Sub tvFolders_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles tvFolders.AfterSelect

    '▼このノードがはじめて選択された場合は子ノードを追加する。
    'はじめてかどうかは子ノードがあるかないかで判断。

    If e.Node.GetNodeCount(False) = 0 Then
       
Call AddSubNodes(e.Node)
    End
If

    StatusBar1.Text = e.Node.FullPath

End Sub

■リスト9

ノードが選択されたときにいつでもフォルダの一覧を追加していては時間がもったいないのではじめてノードを選択したときだけフォルダ一覧を追加するようにしています。はじめてかどうかは子ノードがあるかないかで判断しています。ですから子フォルダがないフォルダのノードをクリックしたときは何度もAddSubNodesが呼ばれてしまいますが子フォルダのないのですからそれほど問題はありません。

子ノードが数はTreeNodeクラスのGetNodeCountメソッド(読み方:GetNodeCount = ゲットノードカウント)で取得できます。選択されたノードはこのイベントのTreeViewEventArgsクラス(読み方:TreeViewEventArgs = ツリービューイベントオーグス)である第2引数のNodeプロパティ(読み方:Node = ノード)で取得できます。

このイベントではついでに現在のノードをフルパスをステータスバーに表示します。

ここでも実際に実行して動作を確認してみてください。どうでしょうか?Windowsのエクスプローラと同じようにフォルダをたどることができましたか?

以上でフォルダツリーに関するプログラムは終了です。フォルダツリーはいろいろなソフトで使われるのでこの節で解説している手法を覚えておくと何かと重宝です。

 

9.詳細表示

 

それではメイン機能であるフォルダの詳細表示部分を作りましょう。ツリービューで選択したフォルダの内容をリストビューで一覧表示する機能です。

まず、フォルダのサイズ・ファイル数・フォルダ数を取得するために以下のGetFolderProperty関数を追加してください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'■GetFolderProperty
'■機能:フォルダのサイズ・ファイル数・フォルダ数を取得する。
'■引数:FolderName 対象のフォルダのフルパス。末尾に \ が必要。
'■備考:サイズの単位はバイト
Private Function GetFolderProperty(ByVal FolderName As String) As FolderProperty

    Dim Folder As New IO.DirectoryInfo(FolderName)
    Dim oFolder As IO.DirectoryInfo
    Dim oFile As IO.FileInfo
    Dim Detail As FolderProperty

    Try

        For Each oFile In Folder.GetFiles()
            Detail.Size += oFile.Length
            Detail.FileCount += 1
       
Next

        For Each oFolder In Folder.GetDirectories()
            Dim ThisProperty As FolderProperty = GetFolderProperty(oFolder.FullName)
            Detail.Size += ThisProperty.Size
            Detail.FileCount += ThisProperty.FileCount
            Detail.FolderCount += 1 + ThisProperty.FolderCount
       
Next

    Catch ex As System.UnauthorizedAccessException
       
'ここにアクセス権限がない場合の処理を書く
   
End Try

    Return Detail

End Function

■リスト10:フォルダ情報取得

この関数は初級講座の現段階では複雑すぎるので詳しくは触れません。

簡単に説明します。まず、この関数はサイズ・ファイル数・フォルダ数と3つの値を返したいので戻り値の型はFolderProperty型にしました。さきほどClass1に貼り付けてもらったコードの中にFolderPropertyがあったことを思い出してください。

具体的な処理内容を見ると、ここでもDirectoryInfoクラスのGetFilesメソッドとGetDirectoriesメソッドを使ったループが登場しています。ファイルのループではファイルサイズをどんどん足し算していきます。ファイル数(FileCount)も1ずつ足していきます。フォルダのループではフォルダのサイズ・ファイル数・フォルダ数をどんどん足していきます。ここでフォルダのサイズ・ファイル数・フォルダ数を取得するためにこの関数は自分自身を呼び出しているところがポイントです。このように自分で自分を呼び出す処理を再帰処理を呼びます。

なお、Windowsのアクセス権のないフォルダを対象とした場合セキュリティ上の理由でエラーが発生します。今回はこのエラーは無視しているのでアクセス権のないフォルダに対しては計算結果が正確でなくなりますので注意してください。

次に、この関数を利用してフォルダやファイルの詳細情報を一覧に表示するためのListFolderItemsメソッドを次の通り記述してください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'■ListFolderItems
'■機能:一覧(lvFolder)にフォルダ・ファイルを表示する。
'■引数:FolderPath 対象のフォルダのフルパス。末尾に \ はつけない。
'■ WithDetail フォルダの詳細情報を表示する場合True。
Private Sub ListFolderItems(ByVal FolderPath As String, Optional ByVal WithDetail As Boolean = False)

    Dim Folder As New IO.DirectoryInfo(FolderPath & "\")
    Dim oFolder As IO.DirectoryInfo
    Dim oFile As IO.FileInfo
    Dim ListRow As ListViewItem

    lvFolder.BeginUpdate()
    lvFolder.Items.Clear()

    '●サブフォルダの情報を取得・表示

    For Each oFolder In Folder.GetDirectories

        ListRow = New ListViewItem(oFolder.Name, ItemImage.ClosedFolder) '名前

        If WithDetail Then
           
'▼詳細情報を取得する場合
           
Dim Detail As FolderProperty = GetFolderProperty(oFolder.FullName)
            ListRow.SubItems.Add(Format(Detail.Size \ 1024, "#,0") & " KB")
'サイズ
           
ListRow.SubItems.Add(Detail.FileCount) 'ファイル数
           
ListRow.SubItems.Add(Detail.FolderCount) 'フォルダ数
       
Else
           
'▼詳細情報は取得しない場合
           
ListRow.SubItems.Add("") 'サイズ
           
ListRow.SubItems.Add("") 'ファイル数
           
ListRow.SubItems.Add("") 'フォルダ数
       
End If

        lvFolder.Items.Add(ListRow)

    Next

    '●ファイルの情報を取得・表示

    For Each oFile In Folder.GetFiles
        ListRow = New ListViewItem(oFile.Name)
'名前
       
ListRow.SubItems.Add(Format(oFile.Length \ 1024, "#,0") & " KB") 'サイズ
       
ListRow.SubItems.Add("") 'ファイル数
       
ListRow.SubItems.Add("") 'フォルダ数
       
lvFolder.Items.Add(ListRow)
   
Next

    lvFolder.EndUpdate()

End Sub

■リスト11:一覧を追加

少し長いですがやっていることは単純です。まずフォルダの一覧でループを回し、必要な情報を追加した上で、ファイルの一覧でループを回し同様に情報を追加します。ここのループもやはりGetDirectoriesメソッドとGetFilesメソッドを利用しています。

リストビューに項目を追加するにはリストボックスと同じでItems.Addメソッドを指定します。ただし、ここでは単に文字列を追加するわけではなく、名前・サイズ・ファイル数・フォルダ数のまとまりを1項目として登録したいので、Addメソッドを呼び出す前にこれらの内容を含んだ項目を作成しておきます。それがListRowです。なお、項目のうち1つがメインアイテムで残りのサブアイテムという扱いになります。ここでは名前をメインアイテムとし、残りをサブアイテムとしていますので処理の方法も名前とそれ以外では少しだけ違います。

このメソッドでは第2引数のWithDetailTrueが指定された場合だけフォルダの詳細情報を取得するために先ほどのGetFolderProperty関数を呼び出します。

サイズに関してはKB単位で表示したいので 1024 で割り算をします。ご存知だとは思いますがファイルのサイズは1024B = 1KBという関係があります。記号「\」 はわり算の答えを返す演算子です。サイズが1000KBを超える場合には「1,000KB」のように「 , 」を区切り文字として表示したいのでFormat関数(読み方:Format = フォーマット)を使って区切り文字の挿入を命令しています。

これで準備完了ですね。あとはこのメソッドを呼び出す部分を作りましょう。このメソッドもツリービューの項目が選択されたときに呼び出せばよいのでツリービューのAfterSelectメソッドに次の通り1行(コメントを含めると2行)追加してください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'▼このノードのフォルダ一覧(lvFolder)を表示する。
Call ListFolderItems(e.Node.FullPath, chkDetail.Checked)

■リスト12

第2引数がchkDetail.Checledになっていることに注意してください。つまり、「自動的に詳細を表示する」のチェックボックスがチェックされているときは第2引数はTrueになり、そうでないときはFalseになります。

それから、「詳細表示」ボタンをクリックしたときには強制的に詳細を表示したいのでこのボタンのクリックイベントにも次の通り追加してください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'■[詳細表示]ボタン
'■機能:一覧(lvFolder)に詳細情報を表示する。
Private Sub btnDetail_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDetail.Click

    ListFolderItems(StatusBar1.Text, True)

End Sub

■リスト13

ここではステータスバーに表示されているフルパスを利用してさきほごのメソッドを呼び出しています。

さぁ、ここまでの状態で実行してみましょう。一覧にフォルダの情報がちゃんと表示されますか?チェックボックスをチェックしてみたりボタンをクリックしてみたりいろいろ試してください。

ただし、フォルダの詳細情報を表示するときにはかなり計算に時間がかかる可能性があるので注意してください。

ここまでで主要な機能はすべて完成しました。今ではフォルダのサイズを一覧形式でみることができます。便利なものではありませんか。

 

10.並び替え

 

後は細かい機能を付け足していきましょう。まずは並び替え機能です。並び替えのことを「ソート」とも言います。

並び替えのためには最初にClass1に用意したFileSorterクラスを使えばよいだけなので楽です。

まず、クラスレベルでFileSorter型の変数を宣言してください。次にフォームのLoadイベントでFileSorterをインスタンシングします。ここまでのコードは次の通りです。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Private Sorter As FileSorter '一覧を昇順・降順で並び替えるためのクラス

'■[フォーム]
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Sorter = New FileSorter(lvFolder)
    ShowDriveNodes()

End Sub

■リスト14:FileSorterのインスタンシング

後はリストビューの列ヘッダ(列見出し)がクリックされたときにFileSorterExecuteメソッドを呼び出せば完了です。列ヘッダがクリックされるとColumnClickイベント(読み方:ColumnClick = カラムクリック)が発生します。Executeメソッドにはどの列を基準に並び替えを実行するのかを指定します。クリックされた列は例によってイベントの第2引数のColumnプロパティ(読み方:Column = カラム)でわかります。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'■lvFolder_ColumnClick
'■[一覧]列タイトルクリック時
'■機能:クリックされた列を基準に並び替えを行う。
Private Sub lvFolder_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles lvFolder.ColumnClick

    lvFolder.BeginUpdate()
    Sorter.Execute(e.Column)
    lvFolder.EndUpdate()

End Sub

■リスト15

BeginUpdateメソッド(読み方:BeginUpdate = ビギンアップデイト)とEndUpdateメソッド(読み方:EndUpdate = エンドアップデイト)メソッドがあると描画処理を高速になります。

 

11.ファイルやフォルダを開く機能

 

最後にリストビューで項目をダブルクリックしたときにその項目を開く機能をプログラムします。たとえば、フォルダをダブルクリックするとエクスプローラが起動してそのフォルダを開きます。ファイルをクリックすると関連付けられたアプリケーションが起動してファイルを開きます。テキストファイルならメモ帳が起動しますし、mp3ファイルならMedia Player等が起動します。

この処理はProcessクラス(読み方:Process = プロセス)のStartメソッド(読み方:Start = スタート)を使うと驚くほど簡単に記述できます。次の通りです。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

'■lvFolder_DoubleClick
'■[一覧]アイテムダブルクリック時
'■機能:アイテムを開く。
Private Sub lvFolder_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles lvFolder.DoubleClick

    Dim Path As String

    Try
       
Path = tvFolders.SelectedNode.FullPath & "\" & lvFolder.SelectedItems(0).Text
        Process.Start(Path)
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Exclamation)
    End
Try

End Sub

■リスト16

 

12.完成

 

ここまで読んでくれた方ありがとうございます。実際に手順どおりにソフトを作ってくださった方おつかれさまです。掲示板に質問や感想などお寄せくださると嬉しいです。

このソフトを改造してオリジナルな機能を追加してみると楽しいかもしれませんね。サイズやファイル数のほかの有用な情報が表示されるようにしてみると良いかもしれません。たとえば、拡張子別ファイル数、ファイルの平均サイズ、属性別ファイル数など。いいものができたら是非投稿してください。

今回出てきたファイル処理やFor Each Nextループなどは初級講座第4章で扱う予定です。