VB.NET-自定义Listview/Listbox

VB.NET-自定义Listview/Listbox,.net,vb.net,listbox,.net,Vb.net,Listbox,所以有几个问题得到了回答,但我还是不明白我该做什么。比如我怎样才能基本上使我的Listview非常定制 我想让它看起来像是: 正如你所看到的,它是高度定制的——如果你想知道的话,我是在Photoshop中制作的,我现在不需要定制滚动条或悬停高亮效果,但将来需要一种方法来实现 有什么办法可以做到这一点吗 编辑:我能找到的最接近的东西是: 但是有一些“问题”-我无法使文本对齐/位置看起来正确,因为我需要在文本前留出两个空格,使其看起来真实得体,这“可能”会在将来尝试单击时给我带来问题。接下来,由于

所以有几个问题得到了回答,但我还是不明白我该做什么。比如我怎样才能基本上使我的Listview非常定制

我想让它看起来像是:

正如你所看到的,它是高度定制的——如果你想知道的话,我是在Photoshop中制作的,我现在不需要定制滚动条或悬停高亮效果,但将来需要一种方法来实现

有什么办法可以做到这一点吗

编辑:我能找到的最接近的东西是: 但是有一些“问题”-我无法使文本对齐/位置看起来正确,因为我需要在文本前留出两个空格,使其看起来真实得体,这“可能”会在将来尝试单击时给我带来问题。接下来,由于某些原因,没有使用边框/网格的选项,这会消除在第一幅图像中框周围使用稍微暗一点的灰色边框的能力。有什么想法吗,伙计们

(我以前是这样做的:)

编辑2:重新编辑:好的,我想我已经对高光颜色进行了排序,但它看起来不像我使用的FillRectangle,但无论我如何设置边界(这是正确的),在刷新和消失之前,它似乎会留下额外的1px白色边界约1-2秒。怎么解决这个问题

编辑3:我“几乎”完成的列表框对我来说不起作用,因为它不稳定-如果我在设计模式下编辑ColorListBox后编辑任何内容,它将不起作用,并给我错误,这很烦人。它也有“SelectedItem”参数,因为它不再是破坏我一半代码的对象。另外,如果这两个是可修复的,我想它会工作,但我不知道如何修复它:(


因此,我现在恢复到一个非常基本的列表框,只包含文本,直到你们能够找到一种方法来定制它,就像上面的第一张图片一样。

根本不清楚你们到底想要什么。
比如我如何基本上使我的列表视图非常定制。
是模糊的,非常广泛的(以及为什么你们没有得到一个你们喜欢的答案)

图片很好,但描述所需外观的文字会更好。如果要仔细查看图片,就无法知道什么是重要的,什么是重要的……因为。我假设每个细节都是基于非常定制的
而重要的。此外:

  • Listview/Listbox
    选择一个:它们是非常不同的控件
  • 对于
    列表视图
    ,项目之间的小2像素边距将非常有问题,因此我划伤了LV1
  • 为什么第一幅图像中的所有项目都是灰色的?这通常表示已禁用,因此可以禁用项目(例如,当给定频道没有节目数据时)
  • “FOX”上的灰色框代表什么?它是所选项目吗?它是HotLight/MouseHover项目吗?
    ListBox
    /
    ListView
    项目通常不会在鼠标经过时亮起(当
    HotTracking
    为真时,LV可以亮起,但只有当鼠标位于
    项目
    而不是子项目上时才亮起)
  • 框矩形的深灰色是绝对颜色吗?
    HotLight
    Selected
    的颜色通常由操作系统(=操作系统)根据用户的主题和颜色选择来处理。这个小工具应该忽略这些吗,还是您的主题使用一些灰色作为突出显示
我仔细测量了第一张图片中的元素,以获得一些指标,然后对上面的答案进行了猜测

无代码解决方案 使用按钮。由于用户可能会单击其中一个按钮来选择所需频道,
按钮
列表视图
更有意义(更多)。您可以在
按钮上显示图像和文本,并使用
FlatAppearance
属性设置所需样式。使用
标记可以跟踪频道ID或集合中相关频道的索引

最后,使用
MouseHover
MouseLeave
事件操纵
FlatAppearance.BorderSize
FlatAppearance.BorderColor
以非常接近问题中的第一幅图像:

它们位于滚动的
面板中
。面板宽度比控件略宽,以避免水平滚动条。至于按钮,
热灯
边框(?)它围绕着整个控件,而不仅仅是文本。这不是您的图片所显示的内容,但另一方面,除了一些标准属性和一些事件处理代码(5-6行)之外,它不涉及任何内容


图像列表框 ownerdraw列表框将使您更接近所需内容,但最终这只会使它看起来像一个带有按钮的
列表框

在表单上放置一个列表框,并设置以下属性:
-DrawMode=OwnerDrawFixed
-积分高度=假
-Itemheight=64(这是基于第一个图像中的图像为60x60这一事实)
-将背景色设置为
ControlLight
{233233}
,以获得所需的确切灰度

如前所述,
ListBox
项目在鼠标悬停时通常不会亮起,因此我们需要一些代码来跟踪它们(如
按钮
):

绘制代码需要实现该接口,以便它可以使用这些属性绘制项目。
Id
是一个额外的接口,用于链接从集合中选择或单击的
列表框
项目(仅当您将项目添加到
列表框
时才需要此接口,不推荐使用)。如果需要,可以将其扩展为包含一个启用的
属性,以便以不同的方式绘制这些属性。您可以在collection items类上实现此接口
Private mouseItem As Int32 = -1
Private Sub lbChannels_MouseMove(sender As Object,
                                 e As MouseEventArgs) Handles lbChannels.MouseMove

    Dim ndx = lbChannels.IndexFromPoint(e.Location)
    ' test to avoid millions of paints
    If ndx <> mouseItem Then
        If mouseItem <> -1 Then
            ' invalidate/redraw the OLD itemrect 
            lbChannels.Invalidate(lbChannels.GetItemRectangle(mouseItem))
        End If
        mouseItem = ndx
        ' invalidate/redraw the NEW itemrect 
        lbChannels.Invalidate(lbChannels.GetItemRectangle(mouseItem))
    End If

End Sub

Private Sub lbChannels_MouseLeave(sender As Object,
                                  e As EventArgs) Handles lbChannels.MouseLeave
    If mouseItem <> -1 Then
        ' get rect for what wont be the hot item in a tick
        Dim rect = lbChannels.GetItemRectangle(mouseItem)
        'lbChannels.Invalidate()
        mouseItem = -1              ' no longer Hot
        lbChannels.Invalidate(rect)
    End If
End Sub
Public Interface IImageItem
    Property ID As String      ' ???
    Property ItemImage As Image
    Property Text As String
End Interface
Public Class ChannelItem
    Implements IImageItem

    Public Property ItemImage As Image Implements IImageItem.ItemImage
    Public Property Text As String Implements IImageItem.Text
    Public Property ID As String Implements IImageItem.ID
    ' + your existing properties

    Public Sub New(txt As String, img As Image, key As String)
        Text = txt
        ItemImage = img
        ID = key
    End Sub

    Public Overrides Function ToString() As String
        Return Text
    End Function
End Class
Private Sub lbChannels_DrawItem(sender As Object,
                                e As DrawItemEventArgs) Handles lbChannels.DrawItem
    Dim lb As ListBox = lbChannels
    If e.Index < 0 Then
        TextRenderer.DrawText(e.Graphics, "", lb.Font, e.Bounds, lb.ForeColor)
        Return
    End If

    Dim iItem As IImageItem
    If TypeOf (lb.Items(e.Index)) Is IImageItem Then
        iItem = DirectCast(lb.Items(e.Index), IImageItem)
    Else
        TextRenderer.DrawText(e.Graphics, lb.Items(e.Index).ToString,
                              lb.Font, e.Bounds, lb.ForeColor)
        Return
    End If

    Dim imgRect As Rectangle = Rectangle.Empty
    Dim txtRect As Rectangle

    ' calc 
    If iItem.ItemImage IsNot Nothing Then
        imgRect = New Rectangle(e.Bounds.X + 1, e.Bounds.Y + 1,
                                 iItem.ItemImage.Width + 2, iItem.ItemImage.Height + 2)
    End If

    ' GetTextExtent
    Dim sz = TextRenderer.MeasureText("   " & iItem.Text, lb.Font)
    txtRect = New Rectangle(iItem.ItemImage.Width + 4, e.Bounds.Y + 1,
                         (e.Bounds.Width - iItem.ItemImage.Width) - 8,
                          e.Bounds.Height - 2)

    ' Draw Big Box around the text portion
    If e.Index = mouseItem Then
        Using pR As New Pen(SystemColors.ControlDark, 2), 
                brB As New SolidBrush(SystemColors.Window)
            e.Graphics.DrawRectangle(pR, txtRect)
            txtRect.Inflate(-1, -1)
            e.Graphics.FillRectangle(brB, txtRect)
        End Using
    ElseIf (e.State.HasFlag(DrawItemState.Selected)) Then
        ' ToDo: modify for whatever is desired for the selected item
        '        this is a guess/example
        Using pR As New Pen(SystemColors.Highlight, 2), 
                       brB As New SolidBrush(SystemColors.Window)
            e.Graphics.DrawRectangle(pR, txtRect)
            txtRect.Inflate(-1, -1)
            e.Graphics.FillRectangle(brB, txtRect)
        End Using
    Else
       ' could use a channel specific color for each BG
       ' just extend IImageItem
        e.DrawBackground()
    End If

    If iItem.ItemImage IsNot Nothing Then
        e.Graphics.DrawImage(iItem.ItemImage, imgRect)
    End If

    ' recalc TR for where the text really goes
    txtRect = New Rectangle(iItem.ItemImage.Width + 4, e.Bounds.Y + 1,
                         sz.Width + 2, e.Bounds.Height - 0)
    TextRenderer.DrawText(e.Graphics, iItem.Text, lb.Font, txtRect, lb.ForeColor)
End Sub
' a collection of ChannelItem objects (which implement IImageItem)
Dim channels As New List(Of ChannelItem)

' my fake data
channels.Add(New ChannelItem("More 4", My.Resources.SO_LVImg01, "M4"))
channels.Add(New ChannelItem("Channel 4", My.Resources.SO_LVImg02, "4"))
channels.Add(New ChannelItem("RTE One", My.Resources.SO_LVImg03, "RET1"))
channels.Add(New ChannelItem("FOX", My.Resources.SO_LVImg04, "Fox"))
...
lbChannels.DataSource = channels