在ListBox控件上绘制边框

时间:2014-12-10 20:21:31

标签: c# .net vb.net winforms user-controls

  

问题

我试图在子类别ListBox的表面上画一个边框,我得到了很好的结果:

enter image description here

但如果我滚动控件,就会发生这种情况:

enter image description here

  

问题

C# VB.Net 中,我如何才能在控件边缘上正确绘制边框,如图片1?

(澄清:不是每个项目的边框)

  

CODE

这就是我在做的事情:

public class mylistbox : inherits listbox

Public Sub New()

    MyBase.DrawMode = Windows.Forms.DrawMode.OwnerDrawVariable

End Sub

Private Sub DrawBorder(ByVal g As Graphics)

        ControlPaint.DrawBorder(g, Me.ClientRectangle, 
                                BorderColor, ButtonBorderStyle)

End Sub

Private Sub MyBase_DrawItem(ByVal sender As Object, ByVal e As DrawItemEventArgs) _
Handles MyBase.DrawItem

    Me.ColorizeItems(e)

End Sub

Private Sub ColorizeItems(ByVal e As DrawItemEventArgs)

    ' non important code here...

    Me.DrawBorder(Graphics.FromHwnd(Me.Handle))

End Sub

end class

1 个答案:

答案 0 :(得分:1)

借鉴 WM_NCPAINT(133)

//
<DllImport("User32.dll")>_
Public Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
End Function

<DllImport("user32.dll")> _
Private Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Dim HDC As IntPtr

    If m.Msg = 133 Then
        HDC = GetWindowDC(m.HWnd)

        If HDC <> IntPtr.Zero Then
            MyBase.WndProc(m) //call it to draw what it needs

            Using g As Graphics = Graphics.FromHdc(HDC)
                g.DrawRectangle(Pens.Blue, 0, 0, Me.Width - 1, Me.Height - 1)
            End Using

            ReleaseDC(m.HWnd, HDC)

            Return
        End If
    End If

    MyBase.WndProc(m)
End Sub

修改

WM_NCPAINT 中挖掘更多内容,你也可以这样做:

//
<DllImport("User32.dll")> _
Private Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
End Function

<DllImport("user32.dll")> _
Private Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

<StructLayout(LayoutKind.Sequential)> _
Private Structure RECT
    Public Left As Integer
    Public Top As Integer
    Public Right As Integer
    Public Bottom As Integer
End Structure

<DllImport("gdi32.dll")> _
Private Shared Function CreateRectRgnIndirect(ByRef lpRect As RECT) As IntPtr
End Function


Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Dim HDC As IntPtr
    Dim rgn As IntPtr
    Dim rt As RECT
    Dim pnt As Point

    If m.Msg = 133 Then
        HDC = GetWindowDC(m.HWnd)

        pnt = Me.PointToScreen(New Point(0, 0))

        rt.Left = pnt.X
        rt.Top = pnt.Y
        rt.Right = rt.Left + Me.Width - 4
        rt.Bottom = rt.Top + Me.Height - 4

        rgn = CreateRectRgnIndirect(rt)

        If HDC <> IntPtr.Zero Then
            Using g As Graphics = Graphics.FromHdc(HDC)
                g.DrawRectangle(Pens.Red, 0, 0, Me.Width - 1, Me.Height - 1)
            End Using

            m.WParam = rgn

            ReleaseDC(m.HWnd, HDC)
        End If
    End If

    MyBase.WndProc(m)
End Sub

我们正在尝试创建一个 rect ,它不包含边框包含垂直滚动条。从此 rect 创建区域并将其传递给 wParam