- 題名: リストビューにファイルの種類を表示する。
- 日時: 2004/10/25 12:23:36
- ID: 6980
- この記事の返信元:
- (なし)
- この記事への返信:
- [6986] Re[1]: リストビューにファイルの種類を表示する。2004/10/25 20:50:22
- [7011] Re[1]: リストビューにファイルの種類を表示する。2004/10/27 4:03:37
- ツリーを表示
こんにちは
私もファイルタイプを取得したいと思って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
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
ってことでしょうか?
深山さん返信ありがとうございます
> 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
です
よろしくお願いします
> '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
以上
長々と申し訳ございません
皆様いろいろありがとうございました
分類:[.NET]
こんにちわ。
VB初心者です。
リストビューにファイルを表示する際に、ファイルの種類の表示で、
”.txt”と、拡張子の表示でなく”テキストファイル”などというふ
うに表示したいのですがうまくいきません。
だれかよろしかったら教えてください。
お願いします。