Schieberegler DGV Farbe ändern

  • VB.NET

Es gibt 51 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    @-Franky- Genau.
    @Peter329 Hier ist alles ohne Extra-Aufwand drinne:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Imaging
    2. Imports System.Runtime.InteropServices
    3. Friend Class ColorizedDGV : Inherits DataGridView
    4. Private Const WM_CTLCOLORSCROLLBAR As Integer = &H137
    5. <DllImport("gdi32.dll", EntryPoint:="CreatePatternBrush")> Private Shared Function CreatePatternBrush(ByVal hBitmap As IntPtr) As IntPtr : End Function
    6. <DllImport("gdi32.dll", EntryPoint:="CreateSolidBrush")> Private Shared Function CreateSolidBrush(ByVal crColor As Integer) As IntPtr : End Function
    7. <DllImport("gdi32.dll", EntryPoint:="DeleteObject")> Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Integer : End Function
    8. Private ReadOnly hBmp As IntPtr = IntPtr.Zero
    9. Private ReadOnly hBrush As IntPtr = IntPtr.Zero
    10. Private ReadOnly hBmpBrush As IntPtr = IntPtr.Zero
    11. Private ReadOnly Bmp As Bitmap = Nothing
    12. Public Sub New()
    13. hBrush = CreateSolidBrush(&HFF00FF&)
    14. Bmp = New Bitmap(4, 4, PixelFormat.Format24bppRgb)
    15. Using G As Graphics = Graphics.FromImage(Bmp)
    16. G.FillRectangle(Brushes.Yellow, 0, 0, 2, 2)
    17. G.FillRectangle(Brushes.Red, 2, 2, 2, 2)
    18. End Using
    19. hBmp = Bmp.GetHbitmap
    20. hBmpBrush = CreatePatternBrush(hBmp)
    21. End Sub
    22. Protected Overrides Sub WndProc(ByRef m As Message)
    23. If m.Msg = WM_CTLCOLORSCROLLBAR Then
    24. Select Case m.LParam
    25. Case Controls(0).Handle '<-- das 1. Control im DGV ist die horizontale ScrollBar
    26. If Not Equals(hBrush, IntPtr.Zero) Then
    27. m.Result = hBrush
    28. End If
    29. Return
    30. Case Controls(1).Handle '<-- das 2. Control im DGV ist die vertikale ScrollBar
    31. If Not Equals(hBrush, IntPtr.Zero) Then
    32. m.Result = hBrush
    33. End If
    34. Return
    35. End Select
    36. End If
    37. MyBase.WndProc(m)
    38. End Sub
    39. Protected Overrides Sub Dispose(disposing As Boolean)
    40. If Not Equals(hBrush, IntPtr.Zero) Then DeleteObject(hBrush)
    41. If Not Equals(hBmpBrush, IntPtr.Zero) Then DeleteObject(hBmpBrush)
    42. If Not Equals(hBmp, IntPtr.Zero) Then DeleteObject(hBmp)
    43. Bmp.Dispose()
    44. MyBase.Dispose(disposing)
    45. End Sub
    46. End Class
    @'BitBrösel' Eine DLL lohnt sich erst bei mehreren Controls.
    Hier ist das kompakt in einer einzigen Datei, die lässt sich leicht überall einfügen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Okie dokie ... damit ist die Sache final gelöst. Und die korrekte Lösung steht auch hier im Thread. Ich bin mir ziemlich sicher, da werden sich noch sehr viele andere VB Programmierer drüber freuen. :)

    Ganz herzlichen Dank an alle Ratgeber, ohne deren Hilfe ich die Kiste nicht hinbekommen hätte. Daumen hoch und Problem gelöst.

    LG
    Peter
    @Peter329

    Ohne zusätzliche Klasse, man man, da musste ich jetzt aber auch überlegen und probieren. Muss man aber noch aufräumen, also den Brush wieder freigeben. Ich habe ja bereits erwähnt den Brush im Konstruktor zu erstellen, -Franky- hatte das auch erwähnt, aber auch Dispose zum aufräumen, solltest du unbedingt machen.

    Also Perter329, ich täte die abgeleitete DGV vorziehen, aber dein Ding, so geht es ohne:

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. Const GWL_WNDPROC As Integer = -4
    4. Const WM_CTLCOLORSCROLLBAR As Integer = &H137
    5. <System.Runtime.InteropServices.DllImport("user32.dll")>
    6. Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, nIndex As Integer, ByVal dwNewLong As MyWindowProc) As IntPtr
    7. End Function
    8. <DllImport("gdi32.dll", EntryPoint:="CreateSolidBrush")>
    9. Private Shared Function CreateSolidBrush(ByVal crColor As Integer) As IntPtr
    10. End Function
    11. <DllImport("user32.dll")>
    12. Private Shared Function CallWindowProc(ByVal wndproc As IntPtr, ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    13. End Function
    14. <DllImport("gdi32.dll")>
    15. Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Integer
    16. End Function
    17. Private Delegate Function MyWindowProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    18. Private WindowProc As MyWindowProc
    19. Private GDIBrush As IntPtr = IntPtr.Zero
    20. Private ProcHandle As IntPtr
    21. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    22. For i = 0 To 100
    23. DataGridView1.Rows.Add(i.ToString())
    24. Next
    25. GDIBrush = CreateSolidBrush(&HFF)
    26. WindowProc = New MyWindowProc(AddressOf DGV_WindowProc)
    27. ProcHandle = SetWindowLong(DataGridView1.Handle, GWL_WNDPROC, WindowProc)
    28. End Sub
    29. Private Function DGV_WindowProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    30. If uMsg = WM_CTLCOLORSCROLLBAR Then
    31. Return GDIBrush
    32. End If
    33. Return CallWindowProc(ProcHandle, hWnd, uMsg, wParam, lParam)
    34. End Function
    35. Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
    36. DeleteObject(GDIBrush)
    37. End Sub
    38. End Class

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „BitBrösel“ ()

    @BitBrösel Wo wird Dein GDIBrush aufgeräumt?
    Da üblicherweise ein Form-Code etwas umfangreicher ist, sehe ich in Deinem Code keinerlei Vorteil gegenüber einer separaten Klasse.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ich hab ma RFGs Lösung an einigen Stellen vereinfacht, und den Dispose-Pattern korrigiert:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Imaging
    2. Imports System.Runtime.InteropServices
    3. Friend Class ColorizedDGV : Inherits DataGridView
    4. Private Const WM_CTLCOLORSCROLLBAR As Integer = &H137
    5. <DllImport("gdi32.dll", EntryPoint:="CreatePatternBrush")> Private Shared Function CreatePatternBrush(ByVal hBitmap As IntPtr) As IntPtr : End Function
    6. <DllImport("gdi32.dll", EntryPoint:="CreateSolidBrush")> Private Shared Function CreateSolidBrush(ByVal crColor As Integer) As IntPtr : End Function
    7. <DllImport("gdi32.dll", EntryPoint:="DeleteObject")> Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Integer : End Function
    8. Private ReadOnly hBmp As IntPtr = IntPtr.Zero
    9. Private ReadOnly hBrush As IntPtr = IntPtr.Zero
    10. Private ReadOnly hBmpBrush As IntPtr = IntPtr.Zero
    11. Private Bmp As Bitmap = Nothing
    12. Public Sub New()
    13. hBrush = CreateSolidBrush(&HFF00FF&)
    14. Bmp = New Bitmap(4, 4, PixelFormat.Format24bppRgb)
    15. Using G As Graphics = Graphics.FromImage(Bmp)
    16. G.FillRectangle(Brushes.Yellow, 0, 0, 2, 2)
    17. G.FillRectangle(Brushes.Red, 2, 2, 2, 2)
    18. End Using
    19. hBmp = Bmp.GetHbitmap
    20. hBmpBrush = CreatePatternBrush(hBmp)
    21. End Sub
    22. Protected Overrides Sub WndProc(ByRef m As Message)
    23. If m.Msg = WM_CTLCOLORSCROLLBAR Then
    24. Select Case m.LParam
    25. Case Controls(0).Handle, Controls(1).Handle '<-- das 1. Control im DGV ist die horizontale ScrollBar '<-- das 2. Control im DGV ist die vertikale ScrollBar
    26. m.Result = hBrush
    27. Return
    28. End Select
    29. End If
    30. MyBase.WndProc(m)
    31. End Sub
    32. Protected Overrides Sub Dispose(disposing As Boolean)
    33. If Bmp Is Nothing Then Return ' mehrfach-Aufruf abwehren
    34. For Each hwnd In {hBrush, hBmpBrush, hBmp} : DeleteObject(hwnd) : Next ' unmanaged Resources freigeben
    35. If disposing Then Bmp.Dispose() ' managed Resources freigeben
    36. Bmp = Nothing
    37. MyBase.Dispose(disposing)
    38. End Sub
    39. End Class
    aber gibt noch mehr Fragen: Wozu sind eiglich Bmp und hBmpBrush ühaupt gut? Kann man den Select Case nicht ganz weglassen, und bei m.Msg = WM_CTLCOLORSCROLLBAR immer hBrush ins Result schreiben?



    BitBrösel schrieb:

    Ohne zusätzliche Klasse, man man..., ich täte die abgeleitete DGV vorziehen, aber dein Ding...
    Das hat natürlich nur Sinn, wenn man die Logik in einem Behavior ansiedelt, was mit einer Zeile zu- (und weg-?)schaltbar ist.
    Das ganze Gedöhns in jeder Form neu aufschreiben wäre ja Irrsinn.
    Übrigens heisst dieses Verfahren mit SetWindowLong(), CallWindowProc() "Subclassing".
    Und habich immer schlechte Erfahrungen mit gemacht, wenn ich debuggen wollte, mit Haltepunkt und so.
    Also auch wenn ich an ganz anderer Stelle debugt hab, fuhr da gerne mal son WinApi-Calllback dazwischen und das VS flog als ganzes raus.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Da muss ich das korrigierte Dispose-Pattern auch noch mal korrigieren:

    VB.NET-Quellcode

    1. Protected Overrides Sub Dispose(disposing As Boolean)
    2. If Bmp Is Nothing Then Return ' mehrfach-Aufruf abwehren
    3. For Each hwnd In {hBrush, hBmpBrush, hBmp} : DeleteObject(hwnd) : Next ' unmanaged Resources freigeben
    4. If disposing Then
    5. Bmp.Dispose() ' managed Resources freigeben
    6. Bmp = Nothing
    7. End If
    8. MyBase.Dispose(disposing)
    9. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @BitBrösel

    Wow ... das ist ja genau das was ich gesucht hatte ! Damit kann ich den Hintergrund der DGV Schieberegler einfärben, OHNE die DGV durch eine "Colorized DGV" zu ersetzen ! Ich hab den Code ein bissl ergänzt um ZWEI DGVs zu behandeln. Ich hoffe, dass ich deine Routine richtig verstanden habe und nicht zuviel Unsinn verzapft habe.

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. Const GWL_WNDPROC As Integer = -4
    4. Const WM_CTLCOLORSCROLLBAR As Integer = &H137
    5. <DllImport("user32.dll")>
    6. Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, nIndex As Integer, ByVal dwNewLong As MyWindowProc) As IntPtr
    7. End Function
    8. <DllImport("gdi32.dll", EntryPoint:="CreateSolidBrush")>
    9. Private Shared Function CreateSolidBrush(ByVal crColor As Integer) As IntPtr
    10. End Function
    11. <DllImport("user32.dll")>
    12. Private Shared Function CallWindowProc(ByVal wndproc As IntPtr, ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    13. End Function
    14. <DllImport("gdi32.dll")>
    15. Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Integer
    16. End Function
    17. Private Delegate Function MyWindowProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    18. Private GDIBrush As IntPtr = IntPtr.Zero
    19. Private WindowProc1 As MyWindowProc
    20. Private ProcHandle1 As IntPtr
    21. Private WindowProc2 As MyWindowProc
    22. Private ProcHandle2 As IntPtr
    23. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    24. For i = 0 To 100
    25. DataGridView1.Rows.Add(i.ToString(), "A", "B")
    26. DataGridView2.Rows.Add(i.ToString(), "C", "D")
    27. Next
    28. GDIBrush = CreateSolidBrush(&H4010)
    29. WindowProc1 = New MyWindowProc(AddressOf DGV_WindowProc1)
    30. ProcHandle1 = SetWindowLong(DataGridView1.Handle, GWL_WNDPROC, WindowProc1)
    31. WindowProc2 = New MyWindowProc(AddressOf DGV_WindowProc2)
    32. ProcHandle2 = SetWindowLong(DataGridView2.Handle, GWL_WNDPROC, WindowProc2)
    33. End Sub
    34. Private Function DGV_WindowProc1(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    35. If uMsg = WM_CTLCOLORSCROLLBAR Then
    36. Return GDIBrush
    37. End If
    38. Return CallWindowProc(ProcHandle1, hWnd, uMsg, wParam, lParam)
    39. End Function
    40. Private Function DGV_WindowProc2(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    41. If uMsg = WM_CTLCOLORSCROLLBAR Then
    42. Return GDIBrush
    43. End If
    44. Return CallWindowProc(ProcHandle2, hWnd, uMsg, wParam, lParam)
    45. End Function
    46. Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
    47. DeleteObject(GDIBrush)
    48. End Sub
    49. End Class


    @All

    Warum ist das so wichtig für mich, OHNE die Ersetzung der DGV auszukommen? Na sehr einfach: ich habe KEIN Problem damit eine Klassendefinition für die "Colorized DGV" in ein Projekt hineinzukopieren. Das ist ruck zuck erledigt. Aber ....

    .... aber das Ersetzen der "DGV" durch eine gleichartige "Colorized DGV" ist u.U. ein "abendfüllendes" Vorhaben ! Ich muss die Eigenschaften der DGV übernehmen (Size, Back/Foreground Colors, SelectionMode, DefaultCellStyle, etc. etc.) und dann muss ich möglicherweise ein Dutzend Spalten kopieren (Header, Designname, ReadOnly, Alignment, Format, SortMode, Width, etc. etc.) Für EINE DGV geht das ja gerade noch ... aber im dümmsten Fall sind das DUTZENDE von DGVs im Projekt ... Und dann hört der Spaß endgültig auf !

    Und das Ersetzen der Hintergrundfarbe ist für einige meiner DGVs eigentlich unerlässlich - mein Dictionary hat Tausende von Einträgen, mein HexEditor kann Files bis zu 2 GB verarbeiten, da habe ich mehr als 100.000 Segmente. Wenn der Schieberegeler in diesen Fällen nicht gut sichtbar ist, dann ist das Arbeiten damit sehr erschwert ! Meist nutze ich das Mouse-Wheel, um zu scrollen. Die Navigation mit dem Mouse-Wheel ist bei sehr großem Datenvolumen aber keine wirkliche Option !

    Deshalb bin ich von @BitBrösel's Lösung begeistert ! Recht herzlichen Dank für deine Mühe, du kennst dich in der Materie offensichtlich hervorragend aus !

    LG
    Peter

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()

    @Peter329
    Weil ich gerade langeweile hatte. ;)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Imports System.Runtime.InteropServices
    4. Public Class Form1
    5. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    6. ColorizedDGV1.ScrollBarColor = Color.BlueViolet
    7. Dim Data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    8. For k = 1 To 10
    9. For i = 0 To Data.Length - 1
    10. Dim digit = Data.Substring(i, 1)
    11. ColorizedDGV1.Rows.Add(digit)
    12. Next
    13. Next
    14. End Sub
    15. End Class
    16. Public Class ColorizedDGV : Inherits DataGridView
    17. Private Const WM_CTLCOLORSCROLLBAR As Integer = &H137
    18. <DllImport("gdi32.dll", EntryPoint:="CreateSolidBrush")> Private Shared Function CreateSolidBrush(ByVal crColor As Integer) As IntPtr : End Function
    19. <DllImport("gdi32.dll", EntryPoint:="DeleteObject")> Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Integer : End Function
    20. Private m_hBrush As IntPtr = IntPtr.Zero
    21. Private m_ScrollBarColor As Color = SystemColors.ScrollBar
    22. Public Sub New()
    23. m_hBrush = CreateSolidBrush(m_ScrollBarColor.ToArgb And Not &HFF000000)
    24. End Sub
    25. Protected Overrides Sub Dispose(disposing As Boolean)
    26. If Not Equals(m_hBrush, IntPtr.Zero) Then DeleteObject(m_hBrush)
    27. MyBase.Dispose(disposing)
    28. End Sub
    29. Public Property ScrollBarColor As Color
    30. Get
    31. Return m_ScrollBarColor
    32. End Get
    33. Set(value As Color)
    34. m_ScrollBarColor = value
    35. If Not Equals(m_hBrush, IntPtr.Zero) Then
    36. DeleteObject(m_hBrush)
    37. m_hBrush = CreateSolidBrush(m_ScrollBarColor.ToArgb And Not &HFF000000)
    38. End If
    39. End Set
    40. End Property
    41. Protected Overrides Sub WndProc(ByRef m As Message)
    42. If m.Msg = WM_CTLCOLORSCROLLBAR Then
    43. If Not Equals(m_hBrush, IntPtr.Zero) Then m.Result = m_hBrush
    44. Else
    45. MyBase.WndProc(m)
    46. End If
    47. End Sub
    48. End Class

    Mfg -Franky-
    @Peter329 Das hWnd das reinkommt, ist das der DataGridView, kannst also testen welche DGV betroffen ist. Kannst also das gleiche Callback für alle DGV's nutzen. SetWindowLong gibt dir ja das alte WndProc(In diesem Fall), also das eigentliche der DGV's, daher brauchst du davon alle, die du aber wie erwähnt mit dem selben Callback verwenden kannst.

    VB.NET-Quellcode

    1. Const GWL_WNDPROC As Integer = -4
    2. Const WM_CTLCOLORSCROLLBAR As Integer = &H137
    3. <System.Runtime.InteropServices.DllImport("user32.dll")>
    4. Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, nIndex As Integer, ByVal dwNewLong As MyWindowProc) As IntPtr
    5. End Function
    6. <DllImport("gdi32.dll", EntryPoint:="CreateSolidBrush")>
    7. Private Shared Function CreateSolidBrush(ByVal crColor As Integer) As IntPtr
    8. End Function
    9. <DllImport("user32.dll")>
    10. Private Shared Function CallWindowProc(ByVal wndproc As IntPtr, ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    11. End Function
    12. <DllImport("gdi32.dll")>
    13. Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Integer
    14. End Function
    15. Private Delegate Function MyWindowProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    16. Private WindowProc As MyWindowProc
    17. Private GDIBrush As IntPtr = IntPtr.Zero
    18. Private ProcHandle As IntPtr
    19. Private ProcHandle1 As IntPtr
    20. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    21. For i = 0 To 100
    22. DataGridView1.Rows.Add(i.ToString())
    23. DataGridView2.Rows.Add(i.ToString())
    24. Next
    25. GDIBrush = CreateSolidBrush(&HFF)
    26. WindowProc = New MyWindowProc(AddressOf DGV_WindowProc)
    27. ProcHandle = SetWindowLong(DataGridView1.Handle, GWL_WNDPROC, WindowProc)
    28. ProcHandle1 = SetWindowLong(DataGridView2.Handle, GWL_WNDPROC, WindowProc)
    29. End Sub
    30. Private Function DGV_WindowProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    31. If uMsg = WM_CTLCOLORSCROLLBAR Then
    32. Return GDIBrush
    33. End If
    34. Select Case hWnd
    35. Case DataGridView1.Handle
    36. Return CallWindowProc(ProcHandle, hWnd, uMsg, wParam, lParam)
    37. Case DataGridView2.Handle
    38. Return CallWindowProc(ProcHandle1, hWnd, uMsg, wParam, lParam)
    39. End Select
    40. End Function
    41. Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
    42. DeleteObject(GDIBrush)
    43. End Sub


    Peter329 schrieb:

    Recht herzlichen Dank für deine Mühe, du kennst dich in der Materie offensichtlich hervorragend aus !


    Habe mich reichlich mit WndProc in C++ rumgeärgert, in C++ muss das eine statische Funktion sein, versuch mal mit C++ von einer statischen Funktion auf was nicht statisches zuzugreifen. Das ist richtig kompliziert(musste GWL_USERDATA nutzen), aber das gehört jetzt nicht hier rein. Daher habe ich da Kenntnisse, aber könnte besser.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „BitBrösel“ ()

    Jetzt sind wir doch wieder in der Form gelandet. ;(
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich weiß nicht. Ein mal Unordnung immer Unordnung.
    Wenn ich ein älteres Projekt übernehme, räume ich zunächst auf.
    Und wenn das zwei Wochen dauert, danach habe ich einen recht guten Überblick über das Projekt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Peter329 schrieb:

    .... aber das Ersetzen der "DGV" durch eine gleichartige "Colorized DGV" ist u.U. ein "abendfüllendes" Vorhaben !

    Nicht unbedingt, ich täte einfach ein backup anlegen und in der Designerdatei die Standart-DGV's durch ColorizedDGV erstzen, so bleiben händisch veränderte Properties unverändert und das geht sogar schneller als überall meinen Code einzubauen ;)
    Ok ... dann braucht es also nur EINE DGV_WindowProc - das macht die Sache ein bissl übersichtlicher. Danke für den Hinweis.

    Zitiat "BitBrösel":

    "Nicht unbedingt, ich täte einfach ein backup anlegen und in der Designerdatei die Standart-DGV's durch ColorizedDGV erstzen"

    Das hab ich versucht - auch wenn mir bei solchen Sachen immer ein bissl mulmig wird, denn an der Form1.Designer.vb sollte man ja nicht unbedingt hemmungslos herumfummeln.

    Ich habe also neben der ColorizedDGV1 und ColorizedDGV2 noch die DataGridView3 und DatagridView4 angelegt.

    Sodann habe ich in der "Form1.Design.vb" den String "DataGridView3" durch "ColorizedDGV3" ersetzt und das Projekt neu geöffnet.


    Das Control hat jetzt den Namen "ColorizedDGV3" erhalten (wie gewünscht) ... aber im Designer wird das Dingens nach wie vor als "SystemWindows.Forms.DATAGRIDVIEW" angezeigt ! Das ist wohl nicht im Sinne des Erfinders.

    Man muss also noch folgende Änderung vornehmen:

    VB.NET-Quellcode

    1. 'Me.ColorizedDGV3 = New System.Windows.Forms.DataGridView()
    2. Me.ColorizedDGV3 = New TestColorScrollBar.ColorizedDGV()


    Dann funktioniert die Sache !

    Dieser Lösungsweg gefällt mir jetzt sehr gut. Eine KLASSE anlegen (wie RFG es anmanhnt) und dann im
    Designer mit geringem Aufwand die gewünschten DGVs in ColorizedDGVs umwandeln .... da scheint der Aufwand vertretbar zu sein.

    LG
    Peter

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Peter329“ ()

    Peter329 schrieb:

    .... aber das Ersetzen der "DGV" durch eine gleichartige "Colorized DGV" ist u.U. ein "abendfüllendes" Vorhaben ! Ich muss die Eigenschaften der DGV übernehmen (Size, Back/Foreground Colors, SelectionMode, DefaultCellStyle, etc. etc.) und dann muss ich möglicherweise ein Dutzend Spalten kopieren (Header, Designname, ReadOnly, Alignment, Format, SortMode, Width, etc. etc.) Für EINE DGV geht das ja gerade noch ... aber im dümmsten Fall sind das DUTZENDE von DGVs im Projekt ... Und dann hört der Spaß endgültig auf !
    nö.
    Du kannst einfacch im DesignerCode die Deklaration As DatagridView austauschen durch die Deklaration As ColoredDatagridview (oder wie das heisst).
    gerne vorher Backup machen, und sicherstellen, dass das Backup sich auch wieder restaurieren lässt.
    @Peter329 Natürlich mit Deinem Projekt-NameSpace, so vorhanden, nicht aber System.Windows.Forms.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Jau, das habe ich ja auch verstanden. Ich habe inzwischen auf diese Weise eine ganze Reihe von Projekten umgestellt und das hat problemlos funktioniert ! Ich bin wirklich allen Ratgebern sehr dankbar - das ist eine Klasse Lösung !

    Jetzt würde ich das ganz gern noch für den Schieberegler einer Multiselect TEXTBOX verwenden. Dann sollten alle wesentlichen Controls abgehandelt sein. (s. Anhang)

    Die Struktur der Lösung könnte ja ganz ähnlich aussehen:

    1. Erstellen der Klassendefinition "ColorizedTBX" (analog zu ColorizedDGV)

    VB.NET-Quellcode

    1. Friend Class ColorizedTBX : Inherits TextBox
    2. Private Const WM_CTLCOLORSCROLLBAR As Integer = ?
    3. ...


    2. In der Designer.vb das Control austauschen:

    Me.TextBox1 = New System.Windows.Forms.TextBox() ersetzen durch
    Me.TextBox1 = ColorizedTBX()

    3. Und dann natürlich noch die WndProc auf das Textbox Control ausrichten:


    VB.NET-Quellcode

    1. Protected Overrides Sub WndProc(ByRef m As Message)
    2. If m.Msg = WM_CTLCOLORSCROLLBAR Then
    3. Select Case ...
    4. m.Result = hBrush
    5. Return
    6. End Select
    7. End If
    8. MyBase.WndProc(m)
    9. End Sub


    Das Lösungsschema ist klar ... nur fehlen mir die Details. Kann mir jemand weiterhelfen ?

    LG
    Peter
    Bilder
    • s 2022-08-30 20-22-137.jpg

      29,63 kB, 192×341, 14 mal angesehen
    Hi

    Zunächst: Der Wert für die Konstante WM_CTLCOLORSCROLLBAR ist immer gleich.

    Aber. Die MS Doku sagt auch: Die WM_CTLCOLORSCROLLBAR Nachricht wird nur von untergeordneten Bildlaufleistensteuerelementen verwendet. Bildlaufleisten, die an ein Fenster angefügt sind (WS_SCROLL und WS_VSCROLL), generieren diese Meldung nicht.

    Meine Vermutung ist das die Textbox eben mit diesen WS_xxx Konstanten erstellt wird (ungeprüft) und daher die Message WM_CTLCOLORSCROLLBAR nicht gefeuert wird.
    Mfg -Franky-