配置の処理
このようなプログラミングには、当然ながら、細かい配置処理が伴います。最長の横棒と各横棒の長さの比率、最長の横棒に使用できるスペース、関連テキスト用に残すべきスペースなどを計算する必要があります。
この問題を解決するには、列のすべての値の最大値を取得する必要があります。これは親列で処理できます。親列への参照は、セルのOwningColumn
プロパティを使用して取得します。次のコードを追加します(この時点では、親列のCalcMaxValue
メンバとMaxValue
メンバは当然ながらまだ実質的な処理は行いません)。
' Get the parent column and the maximum value: Dim parent As DataGridViewBarGraphColumn = _ CType(Me.OwningColumn, DataGridViewBarGraphColumn) parent.CalcMaxValue() Dim maxValue As Long = parent.MaxValue
// Get the parent column and the maximum value: DataGridViewBarGraphColumn parent = (DataGridViewBarGraphColumn)this.OwningColumn; parent.CalcMaxValue(); long maxValue = parent.MaxValue;
ここで、列のInheritedStyle
プロパティを使用して列のフォントも取得できます。
Dim fnt As Font = parent.InheritedStyle.Font
Font fnt = parent.InheritedStyle.Font;
各セルで使用可能なスペースの量を計算するには、最大値のテキストの幅を把握しておく必要があります。この幅がわかれば、各セルの横棒の最大サイズを計算できます。必要な値はGraphics.MeasureString
メソッドで取得できるので、これらの値を計算する次のコードを追加します。
Dim maxValueSize As SizeF = _ graphics.MeasureString(maxValue.ToString, fnt) Dim availableWidth As Single = _ cellBounds.Width - maxValueSize.Width - _ SPACER - (HORIZONTALOFFSET * 2)
SizeF maxValueSize =
graphics.MeasureString(maxValue.ToString(), fnt);
float availableWidth =
cellBounds.Width - maxValueSize.Width -
SPACER - (HORIZONTALOFFSET * 2);
横棒に使用できる幅を計算したら、使用可能なスペースに収まるように、現在のセルの値と最大値の比率を使用して、現在のセルの横棒の幅(長さ)を計算できます。これを処理する次のコードを追加します。
cellValue = CDec((cellValue / maxValue) * _
availableWidth)
cellValue = Convert.ToDecimal( (Convert.ToDouble(cellValue) / maxValue) * availableWidth);
これで内容を描画する準備ができました。次のコードを追加してください。このコードでは、横棒のサイズを計算し、横棒を赤いブラシで描画します。
' Draw the bar, truncating to fit in the space ' you've got in the cell: Const VERTOFFSET As Integer = 4 Dim newRect As New RectangleF( _ cellBounds.X + HORIZONTALOFFSET, _ cellBounds.Y + VERTOFFSET, _ cellValue, _ cellBounds.Height - (VERTOFFSET * 2)) graphics.FillRectangle(Brushes.Red, newRect)
const int VERTOFFSET = 4; RectangleF newRect = new RectangleF( cellBounds.X + HORIZONTALOFFSET, cellBounds.Y + VERTOFFSET, Convert.ToSingle(cellValue), cellBounds.Height - (VERTOFFSET * 2)); graphics.FillRectangle(Brushes.Red, newRect);
次に、テキストを描画するコードを追加します。
' Get the text to draw and calculate its width: Dim cellText As String = formattedValue.ToString() Dim textSize As SizeF = _ graphics.MeasureString(cellText, fnt) ' Calculate where text would start: Dim textStart As PointF = _ New PointF( _ HORIZONTALOFFSET + cellValue + SPACER, _ (cellBounds.Height - textSize.Height) / 2) ' Calculate the correct color: Dim textColor As Color = _ parent.InheritedStyle.ForeColor If (cellState And _ DataGridViewElementStates.Selected) = _ DataGridViewElementStates.Selected Then textColor = parent.InheritedStyle.SelectionForeColor End If ' Draw the text: Using brush As New SolidBrush(textColor) graphics.DrawString(cellText, fnt, brush, _ cellBounds.X + textStart.X, _ cellBounds.Y + textStart.Y) End Using
string cellText = formattedValue.ToString(); SizeF textSize = graphics.MeasureString(cellText, fnt); // Calculate where text would start: PointF textStart = new PointF( Convert.ToSingle(HORIZONTALOFFSET + cellValue + SPACER), (cellBounds.Height - textSize.Height) / 2); // Calculate the correct color: Color textColor = parent.InheritedStyle.ForeColor; if ((cellState & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) { textColor = parent.InheritedStyle.SelectionForeColor; } // Draw the text: using (SolidBrush brush = new SolidBrush(textColor)) { graphics.DrawString(cellText, fnt, brush, cellBounds.X + textStart.X, cellBounds.Y + textStart.Y); }
このコードでは、まずテキストの開始位置の計算と新しいFontオブジェクトの作成を行っています。このコードの次の部分は、新しいフォントでのテキストの幅を計算しています。
Dim cellText As String = formattedValue.ToString() Dim textSize As SizeF = _ graphics.MeasureString(cellText, fnt)
string cellText = formattedValue.ToString();
SizeF textSize =
graphics.MeasureString(cellText, fnt);
次の部分は、テキストの先頭がセル内のどこになるかを計算しています。横棒の幅、各種オフセット、セルとテキストの高さから計算しています。
Dim textStart As PointF = _ New PointF( _ HORIZONTALOFFSET + cellValue + SPACER, _ (cellBounds.Height - textSize.Height) / 2)
PointF textStart = new PointF(
Convert.ToSingle(HORIZONTALOFFSET +
cellValue + SPACER),
(cellBounds.Height - textSize.Height) / 2);
また、選択中のセルのテキストは標準のセルとは異なる表示にするため、セルが選択されているかどうかを検出し、ふさわしいテキストカラーにする必要があります。このコードの次の部分は、cellState
パラメータを使ってこれを判別しています。
Dim textColor As Color = _ parent.InheritedStyle.ForeColor If (cellState And _ DataGridViewElementStates.Selected) = _ DataGridViewElementStates.Selected Then textColor = parent.InheritedStyle.SelectionForeColor End If
Color textColor = parent.InheritedStyle.ForeColor;
if ((cellState &
DataGridViewElementStates.Selected) ==
DataGridViewElementStates.Selected)
{
textColor = parent.InheritedStyle.SelectionForeColor;
}
cellState
パラメータは複数の値の組み合わせになっているので、このようにAnd
演算子を使用して、このパラメータに各値が設定されているかどうかを判別します。
最後に、テキストをセル内の適切な位置に描画します。
Using brush As New SolidBrush(textColor) graphics.DrawString(cellText, fnt, brush, _ cellBounds.X + textStart.X, _ cellBounds.Y + textStart.Y) End Using
using (SolidBrush brush = new SolidBrush(textColor)) { graphics.DrawString(cellText, fnt, brush, cellBounds.X + textStart.X, cellBounds.Y + textStart.Y); }