表示だけファイル名にするには?

解決


sagahiro  2004-12-28 08:13:25  No: 118534

VB.NETにてDir関数を用いてメニューバーに階層状態を入れているのですが
表示は○○(本来はC:\××\××¥○○.txt)だけにするため
System.IO.Path.GetFileNameWithoutExtension()を使用しているのです。

ですが、そのファイルを開く時にパスが必要になるので
C:\××\××¥○○.txtという階層は持ったまま表示を拡張子を取った
ファイル名だけにしたいのですが、どのような手法をとれば良いでしょうか?

お願いします。


いな  2004-12-28 08:42:55  No: 118535

ココが参考になるかと

http://dobon.net/vb/dotnet/file/getabsolutepath.html


sagahiro  2004-12-28 09:58:35  No: 118536

ありがとうございます。

教えた頂いた参考先を拝見し、試してみましたが
そのファイルより上の階層には良いのですが、
例のようにある程度まではパスが分かっており、その後どこのフォルダ
に入っているかを知るには使用できませんでした。


c:\
 |--aaa
     |---aaa.txt
     |---bbb
     |    |---bbb.txt
     |
     |---ccc
          |---ccc.txt

この時aaaのフォルダまでは共通ですので、どこかc:\aaa\と記憶させて
おけばよいのですが、ファイル名だけでbbb.txtを表示させようとすると
aaaのフォルダの中に無いという事で蹴られてしまいます。
フォルダは、aaaかbbbかcccかどれを選択されるかわかりません。

やはり、フォルダのパスごと表示させるしかないのでしょうか?


いな  2004-12-28 10:09:59  No: 118537

なるほど、単純に、絶対パスから相対パスを取得すれば大丈夫かと
思っていたのですが…。

ん〜、三徹の頭ではちょっとお役に立てそうも無いっす。

#29日納品まで、後少し…。


.net初心者  2004-12-28 10:25:25  No: 118538

MenuItemの派生クラスを作ってフルパスを記憶できるようにすればどうですか?


sagahiro  2004-12-28 11:00:03  No: 118539

>>いなさん
忙しそうな中ありがとうございます。

>>.net初心者さん
確かに、addする前にListboxなりにフルパスを記憶してから
addするという事は安易なのですが、MenuItemがクリックされた時に
そのクリックされたアイテム名からそのフルパスを取得するという
作業がどうしていいものやらと悩んでおります…。


ねろ  2004-12-28 18:51:42  No: 118540

どのようにメニューを追加しているのか判らないのですが、
要するにメニューを作成した時とクリックした時にユニークな
キーがほしいと言うことですか。
メニュの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
結構いいかげんですがこんなことも出来るのでは。


.net初心者  2004-12-28 21:21:10  No: 118541

こうするだけではないんですか?

Public Class MyMenuItem
 Inherits System.Windows.Menu.MenuItem

 Public FullPath As String  ←  フルパスを記憶させる変数

End Class

で本体でMyMenuItemとMyMenuItemのイベントハンドラーを追加してやれば
メニューがクリックされたときそのMenuItemのFullPathを参照することが
できると思うのですが

何分.netははじめたばかりなのでトンチンカンなことをいっているかも
知れません。


.net初心者  2004-12-29 00:19:59  No: 118542

サンプルを書いてみました。
ボタンをクリックすると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


.net初心者  2004-12-29 00:23:10  No: 118543

いきなりソースを写しまちがえました。
上のソースは無視して下さい。
以下が試したソースです。

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


聖 羅樹  URL  2004-12-29 01:49:57  No: 118544

横からすみません。

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


sagahiro  2004-12-29 08:17:53  No: 118545

.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つの行に一覧されてしまいます。


.net初心者  2004-12-29 11:08:28  No: 118546

丸写ししたはいいんですけど、もう少し作者の意図を理解されてはどうでしょうか?

CreateMenu(ByRef ParentMenu As MenuItem, ByVal Path As String)

としているのは親メニューの下に子メニューを追加する意図があるんじゃないのですか?
なのにCreateMenu内ではParentMenuは一つも使われていませんよ

なぜParentMenuが引数で渡されているのか考えれば問題も解けるかも。


.net初心者  2004-12-29 11:12:36  No: 118547

>聖  羅樹さん
ご指摘ありがとうございます。
>また、AddHandler した後に Add したほうが
>流れ的にすっきりしてると思います。
確かに不完全なメニューを先に追加するのは思想的にちょっとおかしいかもですね。
.netはいままでVB6で実現しようと思うとかなり苦労することが結構簡単にできる
ので期待しながら勉強中です。


.net初心者  2004-12-29 12:32:06  No: 118548

おせっかいかも知れませんがサンプルを作ってみました。
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


聖 羅樹  URL  2004-12-29 16:41:30  No: 118549

> sagahiroさん
ソースを見る限り私が『.NETでいきまっしょい!』のBBSに
書き込んだもののような気がしますが、それを参考にされたのでしたら、
もう一度ソースをきちんと見てください。
.net初心者さんが言われるように、なぜParentMenuが渡されているのかを
きちんと理解しなければ階層構造にはなりません。

> .net初心者さん
ソースを載せるときは全てを載せるのではなく、
#Region 〜
を省略したり、それ以外の必要でない部分は削ったほうが
見た側もどこが要点なのか分かりやすくていいと思います。


sagahiro  2004-12-29 22:19:41  No: 118550

> .net初心者さん・聖  羅樹さん
ありがとうございました。
もう一度最初から勉強しなおしたいと思います。

最後の.net初心者さんのソースですが
Public Sub CreateMenu〜ではダメで全部貼り付けないと
ダメなんですね^^;


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加