Skip to content

Commit c5f0f04

Browse files
committed
Recalculate the node position of the TreeView when DrawMode = TreeViewDrawMode.OwnerDrawText
1 parent d1bbb32 commit c5f0f04

File tree

1 file changed

+75
-5
lines changed
  • src/System.Windows.Forms/src/System/Windows/Forms/Controls/TreeView

1 file changed

+75
-5
lines changed

src/System.Windows.Forms/src/System/Windows/Forms/Controls/TreeView/TreeView.cs

+75-5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Drawing.Design;
88
using System.Runtime.InteropServices;
99
using System.Windows.Forms.Layout;
10+
using System.Windows.Forms.Primitives;
1011
using System.Windows.Forms.VisualStyles;
1112
using Windows.Win32.System.Variant;
1213
using Windows.Win32.UI.Accessibility;
@@ -2734,6 +2735,13 @@ private unsafe void CustomDraw(ref Message m)
27342735
// as background color.
27352736
if (_drawMode == TreeViewDrawMode.OwnerDrawText)
27362737
{
2738+
if (node is { IsEditing: true })
2739+
{
2740+
nmtvcd->clrText = ColorTranslator.ToWin32(BackColor);
2741+
nmtvcd->clrTextBk = ColorTranslator.ToWin32(BackColor);
2742+
goto default;
2743+
}
2744+
27372745
nmtvcd->clrText = nmtvcd->clrTextBk;
27382746
m.ResultInternal = (LRESULT)(nint)(PInvoke.CDRF_NEWFONT | PInvoke.CDRF_NOTIFYPOSTPAINT);
27392747
return;
@@ -2792,6 +2800,11 @@ private unsafe void CustomDraw(ref Message m)
27922800
nmtvcd->clrTextBk = ColorTranslator.ToWin32(riBack);
27932801
}
27942802

2803+
if (node is { IsEditing: true })
2804+
{
2805+
nmtvcd->clrTextBk = ColorTranslator.ToWin32(BackColor);
2806+
}
2807+
27952808
if (renderinfo is not null && renderinfo.Font is not null)
27962809
{
27972810
// Mess with the DC directly...
@@ -2826,8 +2839,36 @@ private unsafe void CustomDraw(ref Message m)
28262839
{
28272840
Rectangle bounds = node.Bounds;
28282841
Size textSize = TextRenderer.MeasureText(node.Text, node.TreeView!.Font);
2829-
Point textLoc = new(AppContextSwitches.MoveTreeViewTextLocationOnePixel ? bounds.X : bounds.X - 1, bounds.Y);
2830-
bounds = new Rectangle(textLoc, new Size(textSize.Width, bounds.Height));
2842+
Point textLocation = new(AppContextSwitches.MoveTreeViewTextLocationOnePixel ? bounds.X : bounds.X - 1, bounds.Y);
2843+
bounds = new Rectangle(textLocation, new Size(textSize.Width, bounds.Height));
2844+
2845+
Rectangle fillRectangle = new Rectangle(textLocation, new(textSize.Width, bounds.Height));
2846+
Rectangle focusRectangle = new Rectangle(textLocation, new(textSize.Width, bounds.Height));
2847+
2848+
if (RightToLeft == RightToLeft.Yes && RightToLeftLayout)
2849+
{
2850+
int borderWidth = BorderStyle switch
2851+
{
2852+
BorderStyle.FixedSingle => 1,
2853+
BorderStyle.Fixed3D => 2,
2854+
_ => 0
2855+
};
2856+
2857+
// Reverse the X-axis drawing coordinates of the rectangle.
2858+
int invertedX = Width - bounds.X - textSize.Width - borderWidth * 2;
2859+
2860+
// Subtract the scroll bar width when the scroll bar appears.
2861+
if (Height - borderWidth * 2 < PreferredHeight)
2862+
{
2863+
float dpiScale = (float)DeviceDpi / (float)ScaleHelper.InitialSystemDpi;
2864+
invertedX -= (int)(SystemInformation.VerticalScrollBarWidth * Math.Round(dpiScale, 2));
2865+
}
2866+
2867+
// To ensure that the right side of the fillRectangle does not
2868+
// touch the left edge of the node prefix symbol, 1 pixel is subtracted here.
2869+
fillRectangle = new Rectangle(new Point(invertedX - 1, bounds.Y), new(textSize.Width, bounds.Height));
2870+
focusRectangle = new Rectangle(new Point(invertedX, bounds.Y), new(textSize.Width, bounds.Height));
2871+
}
28312872

28322873
DrawTreeNodeEventArgs e = new(g, node, bounds, (TreeNodeStates)(nmtvcd->nmcd.uItemState));
28332874
OnDrawNode(e);
@@ -2843,14 +2884,14 @@ private unsafe void CustomDraw(ref Message m)
28432884
// Draw the actual node.
28442885
if ((curState & TreeNodeStates.Selected) == TreeNodeStates.Selected)
28452886
{
2846-
g.FillRectangle(SystemBrushes.Highlight, bounds);
2847-
ControlPaint.DrawFocusRectangle(g, bounds, color, SystemColors.Highlight);
2887+
g.FillRectangle(SystemBrushes.Highlight, fillRectangle);
2888+
ControlPaint.DrawFocusRectangle(g, focusRectangle, color, SystemColors.Highlight);
28482889
TextRenderer.DrawText(g, node.Text, font, bounds, color, TextFormatFlags.Default);
28492890
}
28502891
else
28512892
{
28522893
using var brush = BackColor.GetCachedSolidBrushScope();
2853-
g.FillRectangle(brush, bounds);
2894+
g.FillRectangle(brush, fillRectangle);
28542895

28552896
TextRenderer.DrawText(g, node.Text, font, bounds, color, TextFormatFlags.Default);
28562897
}
@@ -2870,6 +2911,35 @@ private unsafe void CustomDraw(ref Message m)
28702911
}
28712912
}
28722913

2914+
private int PreferredHeight
2915+
{
2916+
get
2917+
{
2918+
int height = 0;
2919+
foreach (TreeNode node in Nodes)
2920+
{
2921+
height += GetNodeHeight(node);
2922+
}
2923+
2924+
return height;
2925+
}
2926+
}
2927+
2928+
private int GetNodeHeight(TreeNode node)
2929+
{
2930+
int height = ItemHeight;
2931+
2932+
if (node.IsExpanded)
2933+
{
2934+
foreach (TreeNode childNode in node.Nodes)
2935+
{
2936+
height += GetNodeHeight(childNode);
2937+
}
2938+
}
2939+
2940+
return height;
2941+
}
2942+
28732943
/// <summary>
28742944
/// Generates colors for each item. This can be overridden to provide colors on a per state/per node
28752945
/// basis, rather than using the ForeColor/BackColor/NodeFont properties on TreeNode.

0 commit comments

Comments
 (0)