|
Die Textfarbe der Knoten können Sie beim TreeView-Steuerelement
der Microsoft Common Controls ab Version 6 über die
Eigenschaft ForeColor für jeden Knoten einzeln beliebig festlegen.
Beim TreeView-Steuerelement der Version 5 und früher
fehlt diese Eigenschaft noch - und damit überhaupt die
Möglichkeit, die Textfarben der Knoten zu beeinflussen. Allerdings
können Sie in der Version 5 über die Nachricht TVM_SETTEXTCOLOR
die Textfarbe aller Knoten auf einmal setzen. Der Versuch, dies
wiederum auch beim TreeView-Steuerelement der Version 6
zu erreichen, schlägt jedoch fehl, da das Steuerelement die
Textfarben offensichtlich eigenständig für jeden Knoten einzeln
verwaltet.
Befassen wir uns zunächst mit dem recht einfachen Setzen der
Textfarbe für alle Knoten bei einem TreeView-Steuerelement der Version
5. Wie bereits erwähnt, senden Sie die Nachricht
TVM_SETTEXTCOLOR an das Steuerelement und übergeben dabei der
API-Funktion SendMessage
im Parameter lParam den neuen RGB-Farbwert. Damit Sie auch die
Konstanten der Systemfarben problemlos verwenden können, wird dem
Aufruf noch die API-Funktion OleTranslateColor
vorgeschaltet, die eine Systemfarben-Konstante gegebenenfalls in
einen RGB-Farbwert übersetzt (siehe "Systemfarben-Dolmetscher").
Den Aufruf der beiden API-Funktionen verpacken wir in die handliche
Hilfsfunktion TreeViewSetForeColor5, die als kleines Extra noch den
zuvor aktuellen Farbwert zurückgibt.
Private Declare Function OleTranslateColor Lib "oleaut32.dll" _
(ByVal lOleColor As Long, ByVal lHPalette As Long, _
ByRef lColorRef As Long) As Long
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
Public Function TreeViewSetForeColor5(TreeView As TreeView, _
ByVal ForeColor As OLE_COLOR) As OLE_COLOR
Const TVM_SETTEXTCOLOR = &H111E
OleTranslateColor ForeColor, 0&, ForeColor
TreeViewSetForeColor5 = SendMessage(TreeView.hwnd, _
TVM_SETTEXTCOLOR, 0&, ByVal ForeColor)
End Function
Das das TreeView-Steuerelement der Version 6 nicht
auf die Nachricht TVM_SETTEXTCOLOR reagiert, bleibt Ihnen nichts
anderes übrig, als in einer Schleife jedem Knoten die neue Farbe
einzeln zuzuweisen. Damit das Steuerelement bei einer größeren
Anzahl sichtbarer Knoten nicht flackert (die Darstellung wird jedes
Mal aktualisiert), wird die Aktualisierung mit dem Aufruf der
API-Funktion LockWindowUpdate
vor dem Beginn der Schleife aus- und anschließend wieder
eingeschaltet. Auch dies verpacken wir wieder in eine Hilfsprozedur,
die wir zur Unterscheidung TreeViewSetForeColor6 nennen.
Private Declare Function LockWindowUpdate Lib "user32" _
(ByVal hwndLock As Long) As Long
Public Sub TreeViewSetForeColor6(TreeView As TreeView, _
ByVal ForeColor As OLE_COLOR)
Dim nNode As Node
With TreeView
LockWindowUpdate .hwnd
For Each nNode In .Nodes
nNode.ForeColor = ForeColor
Next
LockWindowUpdate 0&
End With
End Sub
Falls Sie gerne eine Hilfsfunktion hätten, die beide
TreeView-Versionen "verarzten" kann - kein Problem. Die
Hilfsfunktion TreeViewSetForeColor prüft zunächst anhand des
Vorhandenseins der Eigenschaft CheckBoxes (die ja erst ab Version
6 zur Verfügung steht), um welche Version es sich handelt,
und ruft dementsprechend eine der zuvor beschriebenen Funktionen
auf.
Public Function TreeViewSetForeColor(TreeView As TreeView, _
ByVal ForeColor As OLE_COLOR) As OLE_COLOR
Dim nTest As Boolean
Dim nForeColor As Long
On Error Resume Next
nTest = TreeView.Checkboxes
If Err.Number Then
On Error GoTo 0
TreeViewSetForeColor5 TreeView, ForeColor
Else
On Error GoTo 0
TreeViewSetForeColor6 TreeView, ForeColor
End If
End Function
Bezüglich des TreeView-Steuerelements der Version 5
können Sie nun glücklich und zufrieden sein. Doch die Lösung für
die Version 6 ist ein wenig rabiat und daher
unbefriedigend. Denn das Ändern der Textfarbe bei sämtlichen
Knoten bügelt schließlich auch für einzelne Knoten bereits
individuell vergebene Textfarben weg. Außerdem hat sie den
Nachteil, dass Sie die Prozedur erst nach dem Einfügen von Knoten
verwenden können - denn: ohne Knoten keine Änderung. Und Sie
müssen die gewünschte Standard-Textfarbe separat in einer
Variablen ablegen, um jeden später neu hinzugefügten Knoten in
dieser Farbe einfärben zu können. Bei der Version 5
stellt beides kein Problem dar: Wenn Sie die Farbe für ein leeres
TreeView-Steuerelement einmal gesetzt haben, nimmt jeder danach
eingefügte Knoten automatisch diese Textfarbe an.
Um zu einer einigermaßen praktikablen und komfortablen Lösung
für die Version 6 zu gelangen, müssen wir ein wenig
mehr Aufwand treiben. Da Sie unter Umständen für mehrere
TreeView-Steuerelemente unterschiedliche Textfarben verwalten
wollen, ist der Einsatz einer Klasse naheliegend. Einer Instanz
dieser Klasse (wir nennen sie TvwForeColors) übergeben Sie einmal
in der Init-Methode ein bestimmtes TreeView-Steuerelement und
optional eine Standard-Textfarbe (die auf die Systemfarbe
vbWindowText voreingestellt ist). Im letzten, ebenfalls optionalen
Parameter der Init-Methode (ValidateByNode) geben Sie an, ob für
jeden Knoten vor dem Ändern seiner Textfarbe ein Ereignis
ausgelöst werden soll, bei dem Sie die Änderung für den
jeweiligen Knoten unterdrücken können.
Private pForeColor As Long
Private pTreeView As TreeView
Private pValidateByNode As Boolean
Private Sub Class_Initialize()
pForeColor = vbWindowText
End Sub
Public Sub Init(TreeView As TreeView, _
Optional ByVal ForeColor As OLE_COLOR = vbWindowText, _
Optional ByVal ValidateByNode As Boolean)
Set pTreeView = TreeView
pForeColor = ForeColor
pValidateByNode = ValidateByNode
End Sub
Private Sub Class_Terminate()
Set pTreeView = Nothing
End Sub
Das übergebene TreeView-Element können Sie über die
Eigenschaft TreeView auslesen. So brauchen Sie gegebenenfalls nur
die Instanz der Klasse in Ihrem Projekt mitzuführen, da Sie das
Steuerelement selbst jederzeit über diese Eigenschaft ansprechen
können:
Public Property Get TreeView() As TreeView
Set TreeView = pTreeView
End Property
Auch die gesetzte TextFarbe können Sie über eine Eigenschaft
auslesen:
Public Property Get ForeColor() As OLE_COLOR
ForeColor = pForeColor
End Property
Nun schauen wir uns noch kurz das erwähnte Ereignis ValidateNode
an. Es ist wie folgt deklariert:
Public Event ValidateNode(Node As Node, _
ByVal NewForeColor As OLE_COLOR, NoChange As Boolean)
Hier wird der Knoten übergeben, dessen Textfarbe in die im
zweiten Parameter übergeben neue Textfarbe geändert werden soll.
Setzen Sie den Rückgabe-Parameter NoChange auf True, unterbleibt
die Änderung für diesen Knoten. Sie können die Auslösung des
Ereignisses jederzeit über die Eigenschaft ValidateByNode ein- und
ausschalten:
Public Property Get ValidateByNode() As Boolean
ValidateByNode = pValidateByNode
End Property
Public Property Let ValidateByNode( _
ByVal New_ValidateByNode As Boolean)
pValidateByNode = New_ValidateByNode
End Property
Damit Sie die Textfarbe nicht für jeden neu hinzugefügten
Knoten selbst einzeln setzen müssen, können Sie neue Knoten über
die Methode Add hinzufügen. Die Parameter sind die gleichen wie bei
der originalen Add-Methode der Nodes-Collection des
TreeView-Steuerelements. Hinzugekommen ist lediglich der optionale
Parameter ForeColor, in dem Sie eine für den Knoten spezifische
Textfarbe angeben können. Lassen Sie den Parameter weg, erhält der
Knoten automatisch die für das ganze Steuerelement gesetzte
Textfarbe. Als Rückgabewert der Funktion erhalten Sie den neu
einfügten Knoten.
Public Function Add(Optional Relative As Variant, _
Optional Relationship As Variant, Optional Key As Variant, _
Optional Text As Variant, Optional Image As Variant, _
Optional SelectedImage As Variant, _
Optional ForeColor As Variant) As Node
Dim nNode As Node
On Error GoTo Add_Error
With pTreeView
Set nNode = .Nodes.Add(Relative, Relationship, Key, Text, _
Image, SelectedImage)
If Not (nNode Is Nothing) Then
If IsMissing(ForeColor) Then
nNode.ForeColor = pForeColor
Else
nNode.ForeColor = ForeColor
End If
End If
End With
Set Add = nNode
Exit Function
Add_Error:
Err.Raise Err.Number, "TvwForeColors.Add", Err.Description
End Function
Kommen wir nun zum nachträglichen Ändern der Textfarbe(n).
Zum einen können Sie die allgemeine Textfarbe über die Methode
SetForeColor setzen (sie ist ausnahmsweise nicht als Property
Let-Prozedur angelegt, da Sie einen zusätzlichen Parameter
benötigt). Sie übergeben die neue Textfarbe und geben im
optionalen Parameter SetMode an, ob der neue Wert der Textfarbe nur
in die interne Variable pForeColor übernommen werden soll und ob
die Knoten vorläufig unverändert bleiben sollen (Enumerationswert
tfcSetModeNone), oder ob nur die Knoten die neue Textfarbe erhalten
sollen, die zurzeit die alte Textfarbe haben (Enumerationswert
tfcSetModeCorresponding; die Methode Replacecolor wird weiter unten
beschrieben), oder ob alle Knoten die neue Textfarbe unbeachtet
ihrer aktuellen Textfarbe erhalten sollen (Enumerationswert
tfcSetAll).
Private Declare Function LockWindowUpdate Lib "user32" _
(ByVal hwndLock As Long) As Long
Public Enum TvwForeColorsSetModeConstants
tfcSetModeNone
tfcSetModeCorresponding
tfcSetAll
End Enum
Public Sub SetForeColor(ByVal New_ForeColor As OLE_COLOR, _
Optional SetMode As TvwForeColorsSetModeConstants = tfcSetAll)
Dim nNode As Node
Dim nNoChange As Boolean
Select Case SetMode
Case tfcSetModeNone
pForeColor = New_ForeColor
Case tfcSetModeCorresponding
ReplaceForeColor , New_ForeColor, True
Case tfcSetAll
pForeColor = New_ForeColor
With pTreeView
LockWindowUpdate .hwnd
If pValidateByNode Then
For Each nNode In .Nodes
nNoChange = False
RaiseEvent ValidateNode(nNode, pForeColor, nNoChange)
If Not nNoChange Then
nNode.ForeColor = pForeColor
End If
Next
Else
For Each nNode In .Nodes
nNode.ForeColor = pForeColor
Next
End If
LockWindowUpdate 0&
End With
End Select
End Sub
Die Methode ReplaceColor ermöglicht eine selektive Änderung der
Textfarbe. Alle Knoten einer bestimmten Farbe erhalten eine neue
Farbe. Hier übergeben Sie optional die zu ändernde Textfarbe
(OldForeColor) und ebenfalls optional die neue Textfarbe
(NewForeColor). Lassen Sie versehentlich beide Parameter weg, wird
ein Fehler ausgelöst (tfcErrNoArguments). Lassen Sie den ersten
Parameter weg, wird die Textfarbe bei den Knoten geändert, die
aktuell die allgemeine als Eigenschaft eingestellte Textfarbe haben.
Wenn Sie dann im letzten optionalen Parameter SetNewForeColor den
Wert True übergeben, wird die neue Farbe als künftige allgemeine
Textfarbe, also als Wert der Eigenschaft ForeColor übernommen.
Lassen Sie die neue Farbe weg, wird als neue Farbe die eingestellte
allgemeine Textfarbe übernommen. Sollten nun beide Farben identisch
sein, wird der Fehler tfcErrSameColors ausgelöst, und es erfolgt
keine Änderung.
Public Enum TvwForeColorsErrorConstants
tfcErrNoArguments = vbObjectError + 10001
tfcErrSameColors = vbObjectError + 10002
End Enum
Public Sub ReplaceForeColor(Optional ByVal OldForeColor As Variant, _
Optional ByVal NewForeColor As Variant, _
Optional ByVal SetNewForeColor As Boolean)
Dim nOldForeColor As Long
Dim nNewForeColor As Long
Dim nNode As Node
Dim nNoChange As Boolean
If IsMissing(OldForeColor) And IsMissing(NewForeColor) Then
Err.Raise tfcErrNoArguments, "TvwForeColors.ReplaceForeColor"
Else
If IsMissing(OldForeColor) Then
nOldForeColor = pForeColor
Else
nOldForeColor = OldForeColor
End If
If IsMissing(NewForeColor) Then
nNewForeColor = pForeColor
Else
nNewForeColor = NewForeColor
If SetNewForeColor Then
pForeColor = NewForeColor
End If
End If
If nOldForeColor = nNewForeColor Then
Err.Raise tfcErrSameColors, "TvwForeColors.ReplaceForeColor"
Else
With pTreeView
LockWindowUpdate .hwnd
If pValidateByNode Then
For Each nNode In .Nodes
nNoChange = False
With nNode
If .ForeColor = nOldForeColor Then
RaiseEvent _
ValidateNode(nNode, nNewForeColor, nNoChange)
If Not nNoChange Then
.ForeColor = nNewForeColor
End If
End If
End With
Next
Else
For Each nNode In .Nodes
With nNode
If .ForeColor = nOldForeColor Then
.ForeColor = nNewForeColor
End If
End With
Next
End If
LockWindowUpdate 0&
End With
End If
End If
End Sub
Da diese letzte Prozedur auch sonst für ein
TreeView-Steuerelement der Version 6 ganz praktisch
sein kann, ist sie auch noch einmal als eigenständige Variante
unter dem Namen TreeViewReplaceForeColor im Modul modTvwSetForeColor
enthalten. Sie unterscheidet sich dadurch von der Methode der
Klasse, dass es dort zum einen keine voreingestellte allgemeine
Textfarbe gibt, und zum anderen das Validierungs-Ereignis für jeden
Knoten entfällt:
Public Sub TreeViewReplaceForeColor(TreeView As TreeView, _
ByVal OldForeColor As Variant, _
ByVal NewForeColor As Variant)
Dim nNode As Node
If OldForeColor = NewForeColor Then
Exit Sub
Else
With TreeView
LockWindowUpdate .hwnd
For Each nNode In .Nodes
With nNode
If .ForeColor = OldForeColor Then
.ForeColor = NewForeColor
End If
End With
Next
LockWindowUpdate 0&
End With
End If
End Sub
|