VB.NETにてDir関数を用いてメニューバーに階層状態を入れているのですが
表示は○○(本来はC:\××\××¥○○.txt)だけにするため
System.IO.Path.GetFileNameWithoutExtension()を使用しているのです。
ですが、そのファイルを開く時にパスが必要になるので
C:\××\××¥○○.txtという階層は持ったまま表示を拡張子を取った
ファイル名だけにしたいのですが、どのような手法をとれば良いでしょうか?
お願いします。
ココが参考になるかと
http://dobon.net/vb/dotnet/file/getabsolutepath.html
ありがとうございます。
教えた頂いた参考先を拝見し、試してみましたが
そのファイルより上の階層には良いのですが、
例のようにある程度まではパスが分かっており、その後どこのフォルダ
に入っているかを知るには使用できませんでした。
例
c:\
|--aaa
|---aaa.txt
|---bbb
| |---bbb.txt
|
|---ccc
|---ccc.txt
この時aaaのフォルダまでは共通ですので、どこかc:\aaa\と記憶させて
おけばよいのですが、ファイル名だけでbbb.txtを表示させようとすると
aaaのフォルダの中に無いという事で蹴られてしまいます。
フォルダは、aaaかbbbかcccかどれを選択されるかわかりません。
やはり、フォルダのパスごと表示させるしかないのでしょうか?
なるほど、単純に、絶対パスから相対パスを取得すれば大丈夫かと
思っていたのですが…。
ん〜、三徹の頭ではちょっとお役に立てそうも無いっす。
#29日納品まで、後少し…。
MenuItemの派生クラスを作ってフルパスを記憶できるようにすればどうですか?
編集 削除>>いなさん
忙しそうな中ありがとうございます。
>>.net初心者さん
確かに、addする前にListboxなりにフルパスを記憶してから
addするという事は安易なのですが、MenuItemがクリックされた時に
そのクリックされたアイテム名からそのフルパスを取得するという
作業がどうしていいものやらと悩んでおります…。
どのようにメニューを追加しているのか判らないのですが、
要するにメニューを作成した時とクリックした時にユニークな
キーがほしいと言うことですか。
メニュのHandleを使えば
1番上のメニューだけは作っておいて
Dim MenuNo(6) As Integer
Dim FllPath(6) As String
Dim myMenu(6) As MenuItem
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
Dim n As Integer
For n = 0 To 5
myMenu(n) = New MenuItem() 'メニューの追加
MenuItem1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {myMenu(n)})
myMenu(n).Text = Str(n)
MenuNo(n) = myMenu(n).Handle().ToInt32
FllPath(n) = Str(n) + "aaaa" 'ファイルのフルパスのつもり
AddHandler myMenu(n).Click, AddressOf myMenu_Click
Next
End Sub
Private Sub myMenu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim m As MenuItem
Dim n As Integer
m = DirectCast(sender, MenuItem)
For n = 0 To 5
If m.Handle.ToInt32 = MenuNo(n) Then
TextBox1.Text = FllPath(n) 'フルパスを表示
End If
Next
End Sub
結構いいかげんですがこんなことも出来るのでは。
こうするだけではないんですか?
Public Class MyMenuItem
Inherits System.Windows.Menu.MenuItem
Public FullPath As String ← フルパスを記憶させる変数
End Class
で本体でMyMenuItemとMyMenuItemのイベントハンドラーを追加してやれば
メニューがクリックされたときそのMenuItemのFullPathを参照することが
できると思うのですが
何分.netははじめたばかりなのでトンチンカンなことをいっているかも
知れません。
サンプルを書いてみました。
ボタンをクリックするとFileメニューの一番下に3つのメニューが追加されます。
追加されたメニューを選択すると設定したフルパスが表示されます。
とりあえず動作しましたが構文、思想等おかしなところがあればバンバンご指摘下さい。
自分の勉強もちょっと兼ねています。
Option Strict On
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows フォーム デザイナで生成されたコード "
Friend WithEvents myMenu1 As New MyMenuItem
Friend WithEvents myMenu2 As New MyMenuItem
Friend WithEvents myMenu3 As New MyMenuItem
Public Sub New()
MyBase.New()
' この呼び出しは Windows フォーム デザイナで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後に初期化を追加します。
myMenu1.Text = "aaaa"
myMenu1.FullPath = "C:\My Documents\aaaa\aaaa.txt"
Me.MenuItem1.MenuItems.Add(myMenu1)
AddHandler myMenu1.Click, AddressOf myMenu_Click
myMenu2.Text = "bbbb"
myMenu2.FullPath = "C:\My Documents\bbbb\bbbb.txt"
Me.MenuItem1.MenuItems.Add(myMenu2)
AddHandler myMenu2.Click, AddressOf myMenu_Click
myMenu3.Text = "cccc"
myMenu3.FullPath = "C:\My Documents\cccc\cccc.txt"
Me.MenuItem1.MenuItems.Add(myMenu3)
AddHandler myMenu3.Click, AddressOf myMenu_Click
End Sub
' Form は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
' Windows フォーム デザイナで必要です。
Private components As System.ComponentModel.IContainer
' メモ : 以下のプロシージャは、Windows フォーム デザイナで必要です。
'Windows フォーム デザイナを使って変更してください。
' コード エディタを使って変更しないでください。
Friend WithEvents MainMenu1 As System.Windows.Forms.MainMenu
Friend WithEvents MenuItem1 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem2 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem3 As System.Windows.Forms.MenuItem
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.MainMenu1 = New System.Windows.Forms.MainMenu
Me.MenuItem1 = New System.Windows.Forms.MenuItem
Me.MenuItem2 = New System.Windows.Forms.MenuItem
Me.MenuItem3 = New System.Windows.Forms.MenuItem
'
'MainMenu1
'
Me.MainMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuItem1})
'
'MenuItem1
'
Me.MenuItem1.Index = 0
Me.MenuItem1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuItem2, Me.MenuItem3})
Me.MenuItem1.Text = "File(&F)"
'
'MenuItem2
'
Me.MenuItem2.Index = 0
Me.MenuItem2.Text = "Close(&X)"
'
'MenuItem3
'
Me.MenuItem3.Index = 1
Me.MenuItem3.Text = "-"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 12)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Menu = Me.MainMenu1
Me.Name = "Form1"
Me.Text = "Form1"
End Sub
#End Region
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub myMenu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click
MsgBox(CType(sender, MyMenuItem).FullPath)
End Sub
End Class
Public Class MyMenuItem
Inherits System.Windows.Forms.MenuItem
Public FullPath As String
End Class
いきなりソースを写しまちがえました。
上のソースは無視して下さい。
以下が試したソースです。
Option Strict On
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows フォーム デザイナで生成されたコード "
Public Sub New()
MyBase.New()
' この呼び出しは Windows フォーム デザイナで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後に初期化を追加します。
End Sub
' Form は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
' Windows フォーム デザイナで必要です。
Private components As System.ComponentModel.IContainer
' メモ : 以下のプロシージャは、Windows フォーム デザイナで必要です。
'Windows フォーム デザイナを使って変更してください。
' コード エディタを使って変更しないでください。
Friend WithEvents MainMenu1 As System.Windows.Forms.MainMenu
Friend WithEvents MenuItem1 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem2 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem3 As System.Windows.Forms.MenuItem
Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.MainMenu1 = New System.Windows.Forms.MainMenu
Me.MenuItem1 = New System.Windows.Forms.MenuItem
Me.MenuItem2 = New System.Windows.Forms.MenuItem
Me.MenuItem3 = New System.Windows.Forms.MenuItem
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'MainMenu1
'
Me.MainMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuItem1})
'
'MenuItem1
'
Me.MenuItem1.Index = 0
Me.MenuItem1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuItem2, Me.MenuItem3})
Me.MenuItem1.Text = "File(&F)"
'
'MenuItem2
'
Me.MenuItem2.Index = 0
Me.MenuItem2.Text = "Close(&X)"
'
'MenuItem3
'
Me.MenuItem3.Index = 1
Me.MenuItem3.Text = "-"
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(148, 32)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(100, 48)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 12)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.Button1)
Me.Menu = Me.MainMenu1
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
'追加したメニューのイベントハンドラー
Private Sub myMenu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
MsgBox(CType(sender, MyMenuItem).FullPath)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'ボタンをクリックされた時の処理
Dim myMenu1 As MyMenuItem
'File→Closeメニュの下に3つのメニューを追加
myMenu1 = New MyMenuItem
myMenu1.Text = "aaaa"
myMenu1.FullPath = "C:\My Documents\aaaa\aaaa.txt"
Me.MenuItem1.MenuItems.Add(myMenu1)
AddHandler myMenu1.Click, AddressOf myMenu_Click
myMenu1 = New MyMenuItem
myMenu1.Text = "bbbb"
myMenu1.FullPath = "C:\My Documents\bbbb\bbbb.txt"
Me.MenuItem1.MenuItems.Add(myMenu1)
AddHandler myMenu1.Click, AddressOf myMenu_Click
myMenu1 = New MyMenuItem
myMenu1.Text = "cccc"
myMenu1.FullPath = "C:\My Documents\cccc\cccc.txt"
Me.MenuItem1.MenuItems.Add(myMenu1)
AddHandler myMenu1.Click, AddressOf myMenu_Click
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
End Class
'MenuItemの派生クラス(FullPathを追加しただけ)
Public Class MyMenuItem
Inherits System.Windows.Forms.MenuItem
Public FullPath As String
End Class
横からすみません。
FullPath を 変数にするのではなく、プロパティとし、
セットされたときにTextプロパティも併せてセットするようにすれば、
TextとFullPathを両方設定する必要はなくなるので、
間違いがないような気がします。
また、AddHandler した後に Add したほうが
流れ的にすっきりしてると思います。
(動きに違いはないのでどちらでもかまいませんが)
前者のは以下のような感じで。
Public Class MenuItemEx
Inherits MenuItem
Private m_FullPath As String = String.Empty
Public Property FullPath() As String
Get
Return Me.m_FullPath
End Get
Set(ByVal Value As String)
Me.m_FullPath = Value
Me.Text = GetFileNameWithoutExtension(Value)
End Set
End Property
End Class
.net初心者さん、ありがとうございます。
他のDir関数を止め、他のBBSに似たような物がありましたので
そこに組み込んで見ましたが、どうもうまくいきません。
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim TopMenu As New MenuItem
Call CreateMenu(TopMenu, "C:\test")
MainMenu1.MenuItems.Add(TopMenu)
End Sub
Public Sub CreateMenu(ByRef ParentMenu As MenuItem, ByVal Path As String)
Dim addMenu As MenuItem = Nothing
Dim addpath As MenuItem = Nothing
Dim text As String = String.Empty
For Each subDir As String In System.IO.Directory.GetDirectories(Path)
text = String.Empty
text = subDir.Substring(System.IO.Path.GetDirectoryName(subDir).Length)
If text.StartsWith("\") = True Then text = text.Substring(1)
addMenu = New MenuItem
addMenu.Text = text
AddHandler addMenu.Click, AddressOf MenuItem_Select
CreateMenu(addMenu, subDir)
Me.MenuItem1.MenuItems.Add(addMenu.CloneMenu)
addMenu.Dispose()
addMenu = Nothing
Next
For Each dirFile As String In System.IO.Directory.GetFiles(Path)
text = String.Empty
text = dirFile.Substring(System.IO.Path.GetDirectoryName(dirFile).Length)
If text.StartsWith("\") = True Then text = text.Substring(1)
addMenu = New MenuItem
addMenu.Text = text
AddHandler addMenu.Click, AddressOf MenuItem_Select
Me.MenuItem1.MenuItems.Add(addMenu.CloneMenu)
addMenu.Dispose()
addMenu = Nothing
Next
End Sub
Private Sub MenuItem_Select(ByVal sender As System.Object, ByVal e As System.EventArgs)
TextBox1.Text = DirectCast(sender, MenuItem).Text
MsgBox(CType(sender, MyMenuItem).FullPath)
End Sub
End Class
Public Class MyMenuItem
Inherits System.Windows.Forms.MenuItem
Public FullPath As String
End Class
addMenu.FullPathも使えず、このまま実行させてもフォルダ構造が
が表示されず、全てのファイルが1つの行に一覧されてしまいます。
丸写ししたはいいんですけど、もう少し作者の意図を理解されてはどうでしょうか?
CreateMenu(ByRef ParentMenu As MenuItem, ByVal Path As String)
としているのは親メニューの下に子メニューを追加する意図があるんじゃないのですか?
なのにCreateMenu内ではParentMenuは一つも使われていませんよ
なぜParentMenuが引数で渡されているのか考えれば問題も解けるかも。
>聖 羅樹さん
ご指摘ありがとうございます。
>また、AddHandler した後に Add したほうが
>流れ的にすっきりしてると思います。
確かに不完全なメニューを先に追加するのは思想的にちょっとおかしいかもですね。
.netはいままでVB6で実現しようと思うとかなり苦労することが結構簡単にできる
ので期待しながら勉強中です。
おせっかいかも知れませんがサンプルを作ってみました。
Option Strict On
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows フォーム デザイナで生成されたコード "
Public Sub New()
MyBase.New()
' この呼び出しは Windows フォーム デザイナで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後に初期化を追加します。
End Sub
' Form は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
' Windows フォーム デザイナで必要です。
Private components As System.ComponentModel.IContainer
' メモ : 以下のプロシージャは、Windows フォーム デザイナで必要です。
'Windows フォーム デザイナを使って変更してください。
' コード エディタを使って変更しないでください。
Friend WithEvents MainMenu1 As System.Windows.Forms.MainMenu
Friend WithEvents MenuItem1 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem2 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem3 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem4 As System.Windows.Forms.MenuItem
Friend WithEvents FolderBrowserDialog1 As System.Windows.Forms.FolderBrowserDialog
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.MainMenu1 = New System.Windows.Forms.MainMenu
Me.MenuItem1 = New System.Windows.Forms.MenuItem
Me.MenuItem3 = New System.Windows.Forms.MenuItem
Me.MenuItem4 = New System.Windows.Forms.MenuItem
Me.MenuItem2 = New System.Windows.Forms.MenuItem
Me.FolderBrowserDialog1 = New System.Windows.Forms.FolderBrowserDialog
'
'MainMenu1
'
Me.MainMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuItem1})
'
'MenuItem1
'
Me.MenuItem1.Index = 0
Me.MenuItem1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuItem2, Me.MenuItem3, Me.MenuItem4})
Me.MenuItem1.Text = "File(&F)"
'
'MenuItem2
'
Me.MenuItem2.Index = 0
Me.MenuItem2.Text = "Select Folder(&S)"
'
'MenuItem3
'
Me.MenuItem3.Index = 1
Me.MenuItem3.Text = "-"
'
'MenuItem4
'
Me.MenuItem4.Index = 2
Me.MenuItem4.Text = "Close(&X)"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 12)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Menu = Me.MainMenu1
Me.Name = "Form1"
Me.Text = "Form1"
End Sub
#End Region
Public Sub CreateMenu(ByRef ParentMenu As MyMenuItem)
Dim addMenu As MyMenuItem = Nothing
'サブディレクトリをメニューに追加
For Each subDir As String In System.IO.Directory.GetDirectories(ParentMenu.FullPath)
addMenu = New MyMenuItem
addMenu.FullPath = subDir
'ディレクトリはイベントハンドラーはいらない?
CreateMenu(addMenu) 'サブディレクトリ内のフォルダ及びファイルをメニューに追加する再帰処理
ParentMenu.MenuItems.Add(addMenu)
Next
For Each dirFile As String In System.IO.Directory.GetFiles(ParentMenu.FullPath)
addMenu = New MyMenuItem
addMenu.FullPath = dirFile
AddHandler addMenu.Click, AddressOf addPath_Click
ParentMenu.MenuItems.Add(addMenu)
Next
End Sub
'追加したメニューのイベントハンドラー
Private Sub addPath_Click(ByVal sender As Object, ByVal e As System.EventArgs)
'選択されたファイルのフルパスの表示
MsgBox(CType(sender, MyMenuItem).FullPath)
End Sub
'SelectFolderの処理
Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click
FolderBrowserDialog1.SelectedPath = ""
FolderBrowserDialog1.ShowDialog()
If FolderBrowserDialog1.SelectedPath <> "" Then
Dim TopMenu As New MyMenuItem
TopMenu.FullPath = FolderBrowserDialog1.SelectedPath
CreateMenu(TopMenu)
MainMenu1.MenuItems.Add(TopMenu)
End If
End Sub
'Closeメニュー
Private Sub MenuItem4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem4.Click
Me.Close()
End Sub
End Class
'MenuItemの派生クラス
Public Class MyMenuItem
Inherits System.Windows.Forms.MenuItem
Private m_FullPath As String
Public Property FullPath() As String
Get
Return m_FullPath
End Get
Set(ByVal Value As String)
'フルパスをセットしたときはTextの内容をファイル名(拡張子無し)にする
m_FullPath = Value
Me.Text = System.IO.Path.GetFileNameWithoutExtension(Value)
End Set
End Property
End Class
> sagahiroさん
ソースを見る限り私が『.NETでいきまっしょい!』のBBSに
書き込んだもののような気がしますが、それを参考にされたのでしたら、
もう一度ソースをきちんと見てください。
.net初心者さんが言われるように、なぜParentMenuが渡されているのかを
きちんと理解しなければ階層構造にはなりません。
> .net初心者さん
ソースを載せるときは全てを載せるのではなく、
#Region 〜
を省略したり、それ以外の必要でない部分は削ったほうが
見た側もどこが要点なのか分かりやすくていいと思います。
> .net初心者さん・聖 羅樹さん
ありがとうございました。
もう一度最初から勉強しなおしたいと思います。
最後の.net初心者さんのソースですが
Public Sub CreateMenu〜ではダメで全部貼り付けないと
ダメなんですね^^;