所以有几个已回答的问题,但我仍然不明白我的意思。就像我怎么能基本上使我的Listview非常自定义。
我试图让它看起来像是:
正如你所看到的那样HEAVILLY定制 - 如果你想知道我在Photoshop中制作了这个,我现在不需要定制的Scrollbar或者现在的Hover-Highlight效果,但是在未来我需要一种方法来做到这一点
我是如何实现这一目标的?
编辑:我能得到的最接近的是:
但是有一个“FEW”问题 - 我不能让文本对齐/位置看起来正确,因为我需要在文本之前放置2个空格以使其实际上看起来不错,“MIGHT”在将来尝试获取时会给我带来问题点击动作。接下来,由于某种原因,没有选择使用边框/网格,这样就无法在第一张图像中删除在Boxes周围稍微变暗的灰色边框。任何想法的家伙?
编辑2:重新编辑:好的,我想我得到了突出显示颜色排序,但它似乎不像我使用FillRectangle,但无论我如何放置界限(这是正确的)它似乎留下额外像1px白色的边界在刷新前消失了大约1-2秒。无论如何要解决这个问题?
编辑3:我正在使用的http://www.vbforums.com/showthread.php?599375-ListBox-with-custom-items-(colors-images-text-alignment) ListBox在我“完成”它完成后不会对我有用,因为它不稳定 - 如果我在设计模式下制作ColorListBox后编辑任何内容它将只是不工作,给我错误,这是令人讨厌的。它还有“SelectedItem”参数,因为它不再是一个破坏我代码一半的Object。除此之外,如果那些2是可修复的,我想它会起作用,但我不知道如何解决它:(
所以我现在只使用文本恢复到非常基本的ListBox,直到你们可以帮助找到一种方法来定制它,就像上面的第一张图片一样。
答案 0 :(得分:3)
完全不清楚你想要什么。 Like how can I basically make my Listview very customized
模糊且非常广泛(为什么你没有得到你喜欢的答案)。
图片很不错,但描述所需外观的字会更好。鉴于要仔细检查的图片,没有办法知道什么是重要的,什么是正确的......因为。我假设每个细节都很重要,基于very customized
。另外:
Listview/Listbox
选择一个:它们是非常不同的控件。ListView
非常有问题,所以我抓了LV 1 。ListBox
/ ListView
项通常不会亮起(当HotTracking
为真时LV可以亮,但仅当鼠标在Item
之上时才会亮子项(多个))。HotLight
和Selected
着色通常由操作系统(==操作系统)处理,尊重用户的主题和颜色选择。这个小工具是否应该忽略这些,或者你的主题使用一些灰色阴影来突出显示?我仔细测量了第一张图片中的元素以获得一些指标,然后对上述答案进行了猜测。
使用按钮。由于用户可能会点击其中一个来选择所需的频道,因此Button
比ListView
更有意义(更多)。您可以在Button
上显示图像以及文本,并使用FlatAppearance
属性根据需要设置样式。使用Tag
跟踪通道ID或集合中相关通道的索引。
最后,使用MouseHover
和MouseLeave
事件来操纵FlatAppearance.BorderSize
和FlatAppearance.BorderColor
以非常接近问题中的第一张图片:
它们位于滚动Panel
中。面板宽度比控件宽一点,以避免水平滚动条。至于按钮,HotLight
边框(???)围绕整个控件而不仅仅是文本。不是你想要的图片,但另一方面,除了一些标准属性和一些小事件处理代码(5-6行)之外没有任何其他内容。
ownerdraw ListBox会让你更接近你想要的东西,但最终这只会使它看起来像ListBox
里面有Buttons
。
在表单上放置一个ListBox ,并设置这些属性:
- DrawMode = OwnerDrawFixed
- IntegralHeight = False
- 物品高度= 64(这是基于第一张图像中图像为60x60的事实)
- 根据需要将BackColor设置为ControlLight
或{233,233,233}
以获得精确的灰色阴影。
如上所述,ListBox
项目通常不会在鼠标悬停时点亮,因此我们需要一些代码来跟踪它(如Button
):
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
更新了,通过重新绘制更改的项目来最大限度地减少闪烁。
我没有使用MouseHover
事件,因为它会在稍后触发,导致提到的延迟很小(但没有接近一秒)。 MouseMove
还可以更轻松地获取鼠标位置。
<强> IImageItem
根据评论,您希望根据应用中的其他一些数据自动生成项目。而不是假设该类看起来是什么,并使其易于实现并适用于任何类,这将使用一个接口:
Public Interface IImageItem
Property ID As String ' ???
Property ItemImage As Image
Property Text As String
End Interface
绘图代码将要求实现界面,以便它可以使用这些属性来绘制您的项目。 Id
是一个额外的选项,允许用于链接从集合中选择或单击的ListBox
项目(仅在向ListBox
添加项目时才需要 - 不推荐)。它可以扩展为包含Enabled
属性,以便在需要时以不同方式绘制它们。您可以在集合项类上实现此接口:
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
注意: ChannelItem
是您用于跟踪频道的任何课程的我的演示版。只需在您的课程上键入Implements IImageItem
,按Enter键,IDE就会添加属性,在将项目添加到您的收藏集之前进行设置。
DrawItem代码
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
同样,目前还不清楚是否有更深的灰色框,用于&#34; FOX&#34;代表SelectedItem ,
HotLight` / Hover项目,甚至禁用。该代码显示了前两种情况下如何/在哪里打包文本。根据需要修改。
<强>用法
' 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"))
...
这一切都非常简单,只需将您的班级替换为ChannelItem
(必须实施IImageItem
)。您可以将该集合用作DataSource
:
lbChannels.DataSource = channels
SelectedValue
将ChannelItem
对象设为System.Object
,然后将其强制转换为 所有 相关数据,例如作为网址或正在播放文字。
结果:
在这种情况下,所选项目有一个SystemColor.Hightlight
框(在我的情况下为蓝色),鼠标所在的项目有一个灰色框。在原始图像中,每个项目之间甚至会出现小的2px间隙。这是图像高度略小于ItemHeight
使用的结果。
在事物上设置边框会使鼠标无法突出显示。
如果你想(几乎)完全控制这些伪按钮的显示方式,你应该建立一个UserControl
。使用Label
和PictureBox
以及正常事件,您可以使用它来完成您想要的任何操作。你可以在大约20分钟内拍一张:
Channel
UserControls包含在自动滚动Panel
中。它们基本上是一个自定义按钮,但允许您对布局,行为和外观进行大量控制。最重要的是,每个人都有自己独特的Click
事件。
1 原因 LV或LB中的项目之间没有间隙是为了让用户更容易选择项目。沟槽或间隙打开了用户可以点击那里并且没有结果的机会。或者根据实现情况,您的代码将使用错误索引崩溃。