Hi All,
1) While working with VCL themes I noticed a problem with painting full-row selection. If Explorer theme is not enabled and VT paints on its own, it does this correct except reminder on the right of the last column. If selected row is the 1st, it appears with horizontal line of white color,
see attached horz_line_on_1st_row.png screenshot. It appears that this line appears white because it's the color the TBitmap is filled its content when initialized. Because clWindow is usually also white, we didn't notice problem this before. With dark VCL themes it's highly noticeable.
The following code fixes the problem:
procedure TBaseVirtualTree.ClearNodeBackground(const PaintInfo: TVTPaintInfo; UseBackground, Floating: Boolean;
....
if (poDrawSelection in PaintOptions) and (toFullRowSelect in FOptions.FSelectionOptions) and
(vsSelected in Node.States) and not (toUseBlendedSelection in FOptions.PaintOptions) and not
(tsUseExplorerTheme in FStates) then
begin
if toShowHorzGridLines in FOptions.PaintOptions then
Dec(R.Bottom);
=>
procedure TBaseVirtualTree.ClearNodeBackground(const PaintInfo: TVTPaintInfo; UseBackground, Floating: Boolean;
....
if (poDrawSelection in PaintOptions) and (toFullRowSelect in FOptions.FSelectionOptions) and
(vsSelected in Node.States) and not (toUseBlendedSelection in FOptions.PaintOptions) and not
(tsUseExplorerTheme in FStates) then
begin
if toShowHorzGridLines in FOptions.PaintOptions then
begin
Brush.Color := BackColor;
FillRect(Rect(R.Left, R.Bottom - 1, R.Right, R.Bottom));
Dec(R.Bottom);
end;
2) Vertical lines that show the columns are painted with dotted brush of FColors.GridLineColor and FColors.BackGroundColor colors. This is good for all rows such lines intersect through, except the selected one. I propose to change FColors.BackGroundColor to to the color of selection, like shown on vert_lines.png.
This change is important for dark VCL themes and make VirtualTree looking better. Below is the fix in two small parts:
2.1) I introduced UseSelectedBkColor argument in TBaseVirtualTree.DrawDottedVLine method with False default value and changed TBaseVirtualTree.DrawDottedVLine like below:
procedure TBaseVirtualTree.DrawDottedVLine(const PaintInfo: TVTPaintInfo; Top, Bottom, Left: Integer; UseSelectedBkColor: Boolean = False);
// Draws a horizontal line with alternating pixels (this style is not supported for pens under Win9x).
var
R: TRect;
begin
with PaintInfo, Canvas do
begin
if UseSelectedBkColor then begin
if Focused or (toPopupMode in FOptions.FPaintOptions) then
Brush.Color := FColors.FocusedSelectionColor
else
Brush.Color := FColors.UnfocusedSelectionColor;
end
else
Brush.Color := FColors.BackGroundColor;
R := Rect(Left, Min(Top, Bottom), Left + 1, Max(Top, Bottom) + 1);
Windows.FillRect(Handle, R, FDottedBrush);
end;
end;
2.2) in TBaseVirtualTree.PaintTree I changed the 1st call to DrawDottedVLine method:
if (BidiMode = bdLeftToRight) or not ColumnIsEmpty(Node, Column) then
begin
Canvas.Font.Color := FColors.GridLineColor;
DrawDottedVLine(PaintInfo, CellRect.Top, CellRect.Bottom, CellRect.Right - 1);
end;
=>
if (BidiMode = bdLeftToRight) or not ColumnIsEmpty(Node, Column) then
begin
Canvas.Font.Color := FColors.GridLineColor;
UseSelectedBkColor := (poDrawSelection in PaintOptions) and (toFullRowSelect in FOptions.FSelectionOptions) and
(vsSelected in Node.States) and not (toUseBlendedSelection in FOptions.PaintOptions) and not
(tsUseExplorerTheme in FStates);
DrawDottedVLine(PaintInfo, CellRect.Top, CellRect.Bottom, CellRect.Right - 1, UseSelectedBkColor);
where UseSelectedBkColor is a new local variable
3) Third change I'd like to propose is questionable. I'm not 100% sure, but it seems not making sense to have selection painted with OS-specific theme (Explorer theme) while the rest is painted with VCL themes, especially if VCL theme is dark.
At the same time, it makes sense to have Explorer theme enabled if VCL theme is not used. For an application that changes themes in run-time, it creates problem -- I have to turn off Explorer theme flag with turning on VCL themes, and return it back
with VCL themes turning off. The following change in TBaseVirtualTree.CreateWnd makes this automatically:
if (StyleServices.Enabled and (toThemeAware in TreeOptions.PaintOptions)) or VclStyleEnabled then
begin
DoStateChange([tsUseThemes]);
if not VclStyleEnabled then
if (toUseExplorerTheme in FOptions.FPaintOptions) and IsWinVistaOrAbove then
begin
DoStateChange([tsUseExplorerTheme]);
SetWindowTheme('explorer');
end
else
DoStateChange([], [tsUseExplorerTheme]);
end
else
DoStateChange([], [tsUseThemes, tsUseExplorerTheme]);
=>
if (StyleServices.Enabled and (toThemeAware in TreeOptions.PaintOptions)) or VclStyleEnabled then
begin
DoStateChange([tsUseThemes]);
if not VclStyleEnabled and (toUseExplorerTheme in FOptions.FPaintOptions) and IsWinVistaOrAbove then
begin
DoStateChange([tsUseExplorerTheme]);
SetWindowTheme('explorer');
end
else
DoStateChange([], [tsUseExplorerTheme]);
end
else
DoStateChange([], [tsUseThemes, tsUseExplorerTheme]);
Best regards.