2014-12-10 2 views
0

ПРОБЛЕМАDraw границы элемента управления ListBox

Я пытаюсь нарисовать границу на поверхности суб-классифицироваться ListBox, я получить довольно результаты:

enter image description here

Но если Я прокручиваю контроль, это то, что происходит:

enter image description here

ВОПРОС

В C# или еще VB.Net, как я мог правильно нарисовать границу по краям управления, как картина одного?

(уточнить: не границы по каждому пункту)

КОД

Это то, что я делаю:

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

Проблема заключается в том, что метод DrawItem вызывается несколько раз, в этом случае каждый раз, когда вы прокручиваете .NET, перерисовываете элемент управления. Почему бы вам не попробовать установить свойство color color в списке. –

+2

Почему вы перерисовываете границу * control *, когда ее просят нарисовать * элемент *? Код ColorizeItems, похоже, виноват. Он также должен использовать графический объект, доступный через 'DrawItemEventArgs'. – Plutonix

+0

@Esteban Falcón WinForms ListBox не имеет свойства цвета границы, может быть, вы говорите о WPF. – ElektroStudios

ответ

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 

EDIT

Рытье еще в 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 создать регион и передать его wParam.

+0

thankyou, но он ест полосу прокрутки в первый раз, когда элемент управления отображается, пока я не прокручу вверх или вниз, у вас есть идея, как его решить? Я имею в виду, что если вы заполните список во время разработки, чтобы иметь полосу прокрутки, то после запуска проекта полоса прокрутки пуста: http://i.imgur.com/QLO2ZMY.jpg – ElektroStudios

+0

Вы должны передать MyBase.WndProc (m) для этого события. Как выяснил ОП, полосы прокрутки извлекаются из этого сообщения. Вы должны сначала называть это, затем ваш код рисования, а это значит, что у вас, вероятно, будет проблеска мерцания. – LarsTech

+0

@ElektroStudios Вы правы. Я этого не заметил. Исправлено: –