Categorize Listbox items by Color

2019-01-29 03:51发布

问题:

So I'm trying to make a listbox with 2 buttons. Listbox is supposed to display files from a specific folder (I get back to this) And the two buttons are supposed to be called "Set.." (As in set directory) and Update (As the list will be refreshed (Something I do every time the Windows Form Runs.

So as of now, when I start my application, and go to the form with the listbox, the listbox is empty. When pressing "Update", the List box picks up files from an address located on my Harddrive (So this is a static address located in my code).

It also finds 7 different extensions (Filetypes), and lists all of them correctly.

My problem is as follows, I want the set Button to open a File Dialog for the user on First-Time Runtime, so the user himself can choose what folder the program "Indexes or Searches" if you will. And then when he runs the application again, and finds the listbox, he can only press Update, and the listbox shows the content of the folder he choose last time.

The Set - button doesn't do anything in my code right now.

Second up, I want each filetype to be labeled or colored with a specific color.

Like; .txt should be blue, .jpg is red, ect..

Running Visual Studio 2013 if that helps.

Also, when checking my code, if you have any suggestions too, how I can improve the code, make it easier, shorter, and just to change things to avoid duplicate codes, please let me know.

Here is from the Design in VS2013

Code:

Private Sub Form_Load(sender As Object, e As EventArgs) Handles Me.Load

FolderBrowserDialog1.SelectedPath = "xxx\xxx\xxx\xxx"
        System.IO.Directory.GetCurrentDirectory()

 Private Sub updateButtonGame_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles updateButtonGame.Click
        If FolderBrowserDialog1.SelectedPath = "xxx\xxx\xxx\xxx" Then

            ListFiles(FolderBrowserDialog1.SelectedPath)

        End If
    End Sub

    Private Sub ListFiles(ByVal folderPath As String)
        filesListBox.Items.Clear()

        Dim fi = From f In New IO.DirectoryInfo(FolderBrowserDialog1.SelectedPath).GetFiles().Cast(Of IO.FileInfo)() _
                  Where f.Extension = ".z64" OrElse f.Extension = ".nds" OrElse f.Extension = ".BIN" OrElse f.Extension = ".smc" OrElse f.Extension = ".ISO" OrElse f.Extension = ".nes" OrElse f.Extension = ".gb"
                  Order By f.Extension
                  Select f

        For Each fileInfo As System.IO.FileInfo In fi
            filesListBox.Items.Add(fileInfo.Name)
        Next

    End Sub

Another thing, this is more optional..

My list is completely black, so I choose to have the "Items" in the Listbox turn Light gray.

I played around with something called e.Graphics in hope to achieve Coloring a specific filetype, and it turned ALL items either Black, Red, or whatever I put it to. But after removing the code, all Items turns into the same color as the Background color of the Listbox. So I can no longer see the elements actually being there, other than the Scroll-bar popping up on the side (Since its many Items in the folder I picked)

Also, I am not that good with coding/visual studio yet, as I started around 1 week ago to date. Started with VB 2010 and then went to VS2013 to see if I managed to fix some issues, also related to List Box.

If I explained rather poorly, let me know and I'll update with better info. Project was also first created in VB 2010, and then "Migrated" or opened in VS 2013.

回答1:

A much, much better way to do this is with a ListView and an ImageList with some standard images for Text, Image, PDF etc in the list, then just set the image key for each item when you add them to the list.

Alternatively, you could emulate the same thing in a listbox (using OwnerDrawFixed) to draw a specified image to indicate the file type. A really good way to implement this is as an ExtenderProvider using code similar to that below as a starting point. As an EP, you can link any cbo or listbox to an image list to provide image cues very much like the ListView works:

The reason you do not see your colored item idiom very often is that whatever colors you pick will not look right on all systems. The more colors, the more likely and more often they wont have enough contrast, be readable etc with the user's color scheme. You also dont need a "Legend" to explain what the colors mean - an image is self explanatory. That said, the DrawItem code would be something like this:

NB: Listbox control is set to OwnerDrawFixed, ItemHeight = 16

Private Sub lb_DrawItem(sender As Object, 
           e As DrawItemEventArgs) Handles lb.DrawItem

    Dim TXT As Color = Color.Black
    Dim JPG As Color = Color.Green
    Dim PDF As Color = Color.Blue
    Dim EXE As Color = Color.Gray
    Dim SEL As Color = SystemColors.HighlightText
    Dim thisColor As Color = Color.Orange

    Dim ndx As Integer = e.Index

    ' isolate ext ans text to draw
    Dim text As String = lb.Items(ndx).ToString()
    Dim ext As String = System.IO.Path.GetExtension(text).ToLowerInvariant

    ' dont do anything if no item being drawn
    If ndx = -1 Then Exit Sub

    ' default
    e.DrawBackground()

    ' color selector
    Select Case ext
        Case ".jpg"
            thisColor = JPG
        Case ".txt"
            thisColor = TXT
        Case ".exe"
            thisColor = EXE
        Case ".pdf"
            thisColor = PDF
    End Select

    ' override color to use default when selected
    If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
        thisColor = SEL
    End If

    ' render the text
    TextRenderer.DrawText(e.Graphics, text, lb.Font, e.Bounds, 
               thisColor, TextFormatFlags.Left)

    ' default
    e.DrawFocusRectangle()

End Sub

Result:

Works on My SystemTM