DOBON.NET DOBON.NETプログラミング掲示板過去ログ

リストビューにファイルの種類を表示する。

環境/言語:[vb.net2003]
分類:[.NET]

こんにちわ。
VB初心者です。

リストビューにファイルを表示する際に、ファイルの種類の表示で、
”.txt”と、拡張子の表示でなく”テキストファイル”などというふ
うに表示したいのですがうまくいきません。

だれかよろしかったら教えてください。
お願いします。
2004/10/26(Tue) 11:07:44 編集(投稿者)

 「うまくいかない」というのは

  何かを試したが意図した結果にならなかった

時に使う言葉ではないでしょうか。
 No6980 からは貴方が「どういう結果を期待して」「何を試して」「どのような結果を得た」のか推し量ることが出来ません。
貴方がどのような努力を払い、何に躓いているのか、この内容からは伝わってこないのです。

 1.リストビューを詳細表示にする方法が解らないのでしょうか?
 2.リストビューにアイテムを追加する方法が解らないのでしょうか?
 3.リストビューにアイテムを追加することは出来るけど、サブアイテムの追加が出来ないのでしょうか?
 4.拡張子から”テキストファイル”という文字列を取得する方法が解らないのでしょうか?


 素直な見方をするなら4のような気はします。が、だとしたらリストビュー云々というのは余分な情報ですよね?

 プログラムの初心者であっても、日本語の初心者ではない筈です(#もし海外の方であるなら主に英語圏のサイトで情報を集めた方が有益でしょう)。
 http://dobon.net/vb/bbs/index.html の内容なども参考にしながら、質問内容を吟味されては如何でしょう?

===================================================================
 因みに

  ○○というものを作りたいけど、わからない。教えて。

といった主旨のカキコは、往々にして

  コピペして動くソースをくれ。

と言ってるものとして受け取られます。
 貴方の真意が別のところにあることを願って止みません。
===================================================================



 尚、もし上記4の内容がお知りになりたかったのであれば SHGetFileInfo という API について調べてみて下さい。
拡張子ではなくファイル名(フルパス)が情報として必要になりますが、用件は満足するかと思います。

 (上述されなかったものも含めて)4以外の内容であるなら、詳細な状況を説明することでレスが付き易くなるでしょう。



#って、これはマルチポストになったのかなぁ? 口調も開発環境も違うから別人?
http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200410/04100116.txt
#暫く様子見て反応がなければ、この発言を削除した上で既定のマルチポスト報告に変更します。
返信遅くなりました。すいません。

>  4.拡張子から”テキストファイル”という文字列を取得する方法が解らないのでしょうか?

これです。ファイルの種類を表示したいのです。(”.txt”→”テキストファイル”)
いろいろ調べてみたのですが、拡張子かファイル名でしか表示できませんでした。
>
>リストビュー云々というのは余分な情報ですよね?

今自分が作っているプログラムで考えていました。すいません。
>
>  プログラムの初心者であっても、日本語の初心者ではない筈です(#もし海外の方であるなら主に英語圏のサイトで情報を集めた方が有益でしょう)。

質問内容が下手ですいません。
分かりやすくするように努力します。

>  貴方の真意が別のところにあることを願って止みません。

検索していろいろなサイトを調べたのですが、拡張子を文字列で表すという方法が載っていなかったので、掲示板に書き込みました。

>  尚、もし上記4の内容がお知りになりたかったのであれば SHGetFileInfo という API について調べてみて下さい。

調べてみたのですが、アイコンの取得という情報しかえられませんでした。
私の探し方がだめなのかもしれません。ごめんなさい。
よく分からなかったので、どなたかご存知の方いませんか?
先のカキコでは随分キツイ物言いをしたにも関わらず、真摯な返答をして頂けて嬉しく思います(^^)
#正直なところ、レスしては頂けないだろうと思ってました(^_^;)

> 返信遅くなりました。すいません。

 お気になさらないで下さいな。
 掲示板でのやり取りですから、二、三日のタイムラグでも十分許容範囲です。ましてや一日と経たずにご返信下さったのですもの。


>> 尚、もし上記4の内容がお知りになりたかったのであれば SHGetFileInfo という API について調べてみて下さい。
> 調べてみたのですが、アイコンの取得という情報しかえられませんでした。

 はい、アイコンの取得”も”できます。
 yamaさんがご覧になったサンプルでは uFlags ( SHGetFileInfo の第五引数 ) に SHGFI_SMALLICON などが設定されてたかと思います。
ここに SHGFI_TYPENAME ( = &H400 ) を指定すると、 SHFILEINFO 構造体の szTypeName メンバにファイルの種類が格納されてきます。
 キーワードを絞れば使用例を見つけることもできるでしょう。
#言語に拘らなければ、ですが。例えば↓(ページ中央より下より、『拡張子のタイプネームを表示する』)
http://www11.ocn.ne.jp/~ikalu/win32api/0012.html


 もし API の宣言の仕方などが判らないようでしたらその旨お知らせ下さいませ。
いえ、私の書き方がだめだったので、、、、
ご指導いただいて感謝です。vv
お早い返信ありがとうございます。

>  yamaさんがご覧になったサンプルでは uFlags ( SHGetFileInfo の第五引数 ) に SHGFI_SMALLICON などが設定されてたかと思います。
> ここに SHGFI_TYPENAME ( = &H400 ) を指定すると、 SHFILEINFO 構造体の szTypeName メンバにファイルの種類が格納されてきます。
>  キーワードを絞れば使用例を見つけることもできるでしょう。

上記のキーワードを絞っていろいろ検索してみました。サンプルが見つかったのですけれども、すごく難しくて解読に苦しんでいます。
>
>  もし API の宣言の仕方などが判らないようでしたらその旨お知らせ下さいませ。

実はAPIについては最近知ったくらいの超初心者で全く分からないのです。
宣言は難しいんですか?
ラッピングしてあるとかんたんだと聞いたのですが・・・・。
宜しかったら教えてください。
> 上記のキーワードを絞っていろいろ検索してみました。サンプルが見つかったのですけれども、すごく難しくて解読に苦しんでいます。

 一度に理解しようとせず、解らないものはヘルプの説明を見ながら一つ一つ潰していってみて下さい。
といっても、きっちり理解する必要はないですよ。なんとなく流れを追うことができれば、それを真似ることもできるでしょう。
 自分でやってみて、エラーになって、その原因を考えて、調べて‥‥大変でしょうけど頑張ってくださいな。
#老婆心ながら↓からプログラム経験自体が短いのかな?と。
> 実はAPIについては最近知ったくらいの超初心者で全く分からないのです。


> 宣言は難しいんですか?
> ラッピングしてあるとかんたんだと聞いたのですが・・・・。
> 宜しかったら教えてください。

 そんなに構える程のことではない‥‥筈。難しいことではないけど、慣れないうちは大変かも知れません。
 宣言の仕方はこの辺りを参照して下さい。

チュートリアル : Windows API の呼び出し
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vbcn7/html/vaconCallingWindowsAPIs.asp

‥‥だけだとちょっと辛いかなぁと思って検索してたら、丁度良い内容のものが見つかりました。
 C# ですけど、上記チュートリアルの内容と併せれば今回必要な宣言についてはクリアできるのではないかと。

Nagadon の C# 入門 (m00039385)
http://www.melma.com/mag/85/m00039385/a00000098.html


 ラッピングについては必要があれば、としか(^_^;)
Win32 APIを使いたくない(または使えない)ということであれば、レジストリを調べるという方法もあるでしょう。私のメールマガジンでこれらを設定する方法を紹介していますので、逆に取得することもできるでしょう。

.NETプログラミング研究 第41号
プログラムをファイルの拡張子に関連付ける
http://backno.mag2.com/reader/BackBody?id=200409140600000000104516000
深山さん、管理人さん、返信ありがとうございます。

すいません、VBというか、プログラムの経験自体が短くて分からないことが沢山あって。ごめんなさい。

深山さん、詳しい内容ありがとうございます。
記述されているサイトでAPI宣言を実行したのですが、私には難しくて・・。APIを使わない方法でやってみたいと思います。
せっかく教えて頂いたのに本当にごめんなさい。でもとても勉強になりました。

管理人さんの下記のコード見ながら今作っています。
> http://backno.mag2.com/reader/BackBody?id=200409140600000000104516000

まだ出来上がってはいませんが、とりあえずヘルプを参照しながら頑張ってみます。分からなくなったらまた書き込むと思うのでそのときは宜しかったら教えてください。本当にありがとうございます。
> すいません、VBというか、プログラムの経験自体が短くて分からないことが沢山あって。ごめんなさい。

 いや、そんなに謝って頂かなくても(^_^;)
 最初のうちは解らないことが沢山あって当然ですよ。時間と共にそれが減っていけば良いだけのことでしょう? それに、そのことで誰に迷惑を掛けた訳でもないのですから。

> 記述されているサイトでAPI宣言を実行したのですが、私には難しくて・・。APIを使わない方法でやってみたいと思います。

 了解です。レジストリからの取得、上手くいくと良いですね(^^)
こんにちは
私もファイルタイプを取得したいと思ってAPIの
SHGetFileInfo で試みたのですが
どうやっても SHFILEINFO 構造体の szTypeName が空になって
取得できませんでしたので、取り敢えずレジストリで取得しました
しかし、エクスプローラで見える日本語のファイルタイプは取れません・・・
もし英語表記でよかったらどうぞ
では

 Private Function GetFileType(ByVal extension As String) As String
      'extension には拡張子 例 ".txt"
   Dim regkey As RegistryKey = _ 
            Registry.ClassesRoot.OpenSubKey(extension)
            Return CType(regkey.GetValue(""), String)
 End Function
> Private Function GetFileType(ByVal extension As String) As String
> 'extension には拡張子 例 ".txt"
>    Dim regkey As RegistryKey = _
> Registry.ClassesRoot.OpenSubKey(extension)
> Return CType(regkey.GetValue(""), String)
> End Function


この場合だとファイルタイプ(?)が返ってきていたような・・・。
取得したファイルタイプを使ってもう一度
Registry.ClassesRoot.OpenSubKey(filetype).GetValue("")
を行えば種類(?)が返ってきました。

ちなみにregkeyはNothingをチェックしないと例外エラーが
発生します。
ihcioyさんありがとうございます

> この場合だとファイルタイプ(?)が返ってきていたような・・・。
> 取得したファイルタイプを使ってもう一度
> Registry.ClassesRoot.OpenSubKey(filetype).GetValue("")
> を行えば種類(?)が返ってきました。

こんな感じで出来ました。
Private Function GetFileType(ByVal extension As String) As String
    Try
        Dim type As String = CType(Registry.ClassesRoot.OpenSubKey(extension).GetValue(""), String)
        Return CType(Registry.ClassesRoot.OpenSubKey(type).GetValue(""), String)
    Catch ex As Exception
    End Try
End Function


> ちなみにregkeyはNothingをチェックしないと例外エラーが
> 発生します。

regkey.close
regkey = Nothing
 ってことでしょうか?
> 私もファイルタイプを取得したいと思ってAPIの
> SHGetFileInfo で試みたのですが
> どうやっても SHFILEINFO 構造体の szTypeName が空になって
> 取得できませんでした(後略)

 No6986 でも触れているように、 SHGetFileInfo の引数には拡張子ではなくファイルのフルパスが必要になります。この点は大丈夫でしょうか?

 大丈夫であれば、取得できなかった理由として次のようなものが考えられます。

  ・引数として指定したファイル名が存在しない
  ・関数もしくは構造体の宣言に誤りがある
  ・関数をコールする際の引数指定に誤りがある

 もしそのときのコードが残っているようでしたら、問題が特定できるかも知れませんが。
#レジストリからの取得に成功したようですし必要ないかな。
深山さん返信ありがとうございます

> No6986 でも触れているように、 SHGetFileInfo の引数には拡張子ではなく
> ファイルのフルパスが必要になります。
> この点は大丈夫でしょうか?
はい、確認しました

>  もしそのときのコードが残っているようでしたら、
> 問題が特定できるかも知れませんが。

お言葉に甘えて恐縮ですが、一応載せてみます

'Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential)> _
Declare Auto Function SHGetFileInfo Lib "Shell32" ( _
            ByVal pszPath As String, _
            ByVal dwFileAttributes As Integer, _
            ByRef psfi As SHFILEINFO, _
            ByVal cbFileInfo As Integer, _
            ByVal uFlags As Integer) As IntPtr

Public Structure SHFILEINFO
     Public Const NAMESIZE As Integer = 80
     Public hIcon As IntPtr
     Public iIcon As Integer
     Public dwAttributes As UInt32
     <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> _
     Public szDisplayName As String
     <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=NAMESIZE)> _
     Public szTypeName As String
End Structure

Public Const SHGFI_USEFILEATTRIBUTES As Integer = &H10
Public Const FILE_ATTRIBUTE_NORMAL As Integer = &H80
Public Const SHGFI_TYPENAME As Integer = &H400

こんな感じでした
よろしくお願いします
肝心のメソッドを書き忘れました

Public Function GetTypeName(ByVal name As String) As String
    Dim shfi As New SHFILEINFO
    Dim flags As Integer = SHGFI_TYPENAME Or SHGFI_USEFILEATTRIBUTES
    SHGetFileInfo(name, FILE_ATTRIBUTE_NORMAL, shfi, Marshal.SizeOf(shfi), flags)
    Return shfi.szTypeName
End Function

です
よろしくお願いします

>>ちなみにregkeyはNothingをチェックしないと例外エラーが
>>発生します。
>
> regkey.close
> regkey = Nothing
> ってことでしょうか?

Try Catchしてるので問題ないかもしれませんが・・・。
登録されていない拡張子の場合、regkeyはNothingとなるので
注意が必要です。
> 'Imports System.Runtime.InteropServices
> 
> <StructLayout(LayoutKind.Sequential)> _
> Declare Auto Function SHGetFileInfo Lib "Shell32" ( _
>             ByVal pszPath As String, _
>             ByVal dwFileAttributes As Integer, _
>             ByRef psfi As SHFILEINFO, _
>             ByVal cbFileInfo As Integer, _
>             ByVal uFlags As Integer) As IntPtr
> 
> Public Structure SHFILEINFO
>      Public Const NAMESIZE As Integer = 80
>      Public hIcon As IntPtr
>      Public iIcon As Integer
>      Public dwAttributes As UInt32
>      <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> _
>      Public szDisplayName As String
>      <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=NAMESIZE)> _
>      Public szTypeName As String
> End Structure

 えっと、これではコンパイルを通らないようですが‥‥(^_^;)
 取り敢えず、
  ・StructLayout 属性は構造体の宣言に付いている
  ・MAX_PATH の定義もされている
ものとして話を進めます。
#ただの転記ミスですよね?


 実行したところ、確かに取得できませんでした。どうやら文字列のマーシャリングに失敗しているようです。
 修正方法はいくつかありますが、 StructLayout 属性の CharSet フィールドを設定するのが一般的でしょうか。

> <StructLayout(LayoutKind.Sequential)> _
> Public Structure SHFILEINFO
の箇所を
  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
  Public Structure SHFILEINFO
としてみてください。
#この辺りの内容とあわせて Declare ステートメントの Ansi / Unicode / Auto に関する説明にも目を通しておくと良いかも知れません。


 以下、本題とは直接関係ないのですが。
 ファイルの種類だけ取得できれば良いのであって、ファイルの属性は必要ないのですよね?
であれば、 FILE_ATTRIBUTE_NORMAL や SHGFI_USEFILEATTRIBUTES は必要ありませんよ。
>     Dim flags As Integer = SHGFI_TYPENAME Or SHGFI_USEFILEATTRIBUTES
>     SHGetFileInfo(name, FILE_ATTRIBUTE_NORMAL, shfi, Marshal.SizeOf(shfi), flags)
の部分は
      Dim flags As Integer = SHGFI_TYPENAME
      SHGetFileInfo(name, 0, shfi, Marshal.SizeOf(shfi), flags)
でOKです。
深山さんありがとうございます

> ・StructLayout 属性は構造体の宣言に付いている
> ・MAX_PATH の定義もされている
> ものとして話を進めます。
> #ただの転記ミスですよね?
お手数かけて申し訳ございません、その通りです・・・

>   <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
>   Public Structure SHFILEINFO
> としてみてください。
> #この辺りの内容とあわせて Declare ステートメントの 
> Ansi / Unicode / Auto に関する説明にも目を通しておくと良いかも知れません。
できるならなるべくマネージドでと思いこの当たりは避けてました・・・
がんばって勉強してみようと思います!

本題ですが、指摘頂いた部分を直しても、
(私の環境では?)取得はできませんでした。
結局
>Public Function GetTypeName(ByVal name As String) As String
>    Dim shfi As New SHFILEINFO
の次に以下を追加したところ、成功しました!
shfi.szTypeName = New String(Chr(0), 80)


一応完成しましたので、「Windows APIを使用したファイルタイプの取得」
コードを掲載します

'Windows APIを使用したファイルタイプの取得
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure SHFILEINFO
    Public hIcon As IntPtr
    Public iIcon As Integer
    Public dwAttributes As Integer
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
    Public szDisplayName As String
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
    Public szTypeName As String
End Structure

Private Declare Auto Function SHGetFileInfo Lib "shell32.dll" _
        (ByVal pszPath As String, _
         ByVal dwFileAttributes As Integer, _
         ByRef psfi As SHFILEINFO, _
         ByVal cbFileInfo As Integer, _
         ByVal uFlags As Integer) As IntPtr

Public Function GetTypeName(ByVal name As String) As String
    Dim shfi As New SHFILEINFO
    shfi.szDisplayName = New String(Chr(0), 260)
    shfi.szTypeName = New String(Chr(0), 80)
    SHGetFileInfo(name, 0, shfi, Marshal.SizeOf(shfi), &H400)
    Return shfi.szTypeName
End Function


また、ihcioyさんに指摘していただいた部分を修正した
「レジストリを使用したファイルタイプの取得」も合わせて掲載します

'レジストリを使用したファイルタイプの取得
Private Function GetFileType(ByVal extension As String) As String
    Try
        Dim regKey As RegistryKey = Registry.ClassesRoot.OpenSubKey(extension)
        If regKey Is Nothing Then Return Nothing
        Dim type As String = CType(regKey.GetValue(""), String)
        Return CType(Registry.ClassesRoot.OpenSubKey(type).GetValue(""), String)
    Catch ex As Exception
    End Try
End Function

以上
長々と申し訳ございません
皆様いろいろありがとうございました
お久しぶりです。

あの後レジストリから取得して、皆様のコードを参考しながら作ってみました。
そして、なんとかレジストリからファイル種類を取得することができました。

これも皆様の貴重な意見のおかげです。
とても勉強になりました。

本当にありがとうございました。

解決しましたので、一応チェックをしておきます。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板