|
魔界の仮面弁士 さん
早速の書込みありがとうございます。
> それから、今回はセルの編集は想定されていないのでしょうか?
> セル内の文字列は、イベント中で行列指定で固定割当するのでは無く、
> DataSource からバインドしておき、e.Value ないしは e.FormattedValue で
> 取り出したデータを DrawText した方が良い気がします。
> EditingControl にまで手を加えるとか、そもそも ReadOnly である場合は
> 現状のように、CellPainting 内に文字列情報を持たせても良いですけれども。
説明不足ですみません。
図に書いた大項目〜小項目はヘッダになります。
実際は小項目の左に編集セルが入る事になります。
よってヘッダのセルはReadOnlyにしている為、固定割当を行っています。
> まずは「e.Handled = True にはするが、何も描画しないセル」があるのが問題です。
> 描画処理を記述しないセルは、e.Handled = False のままにしておく必要があります。
「e.Handled = False のまま」という事ですが、DataGridViewに慣れていない為、どのような処理を入れればよいかがよくわからず・・・。
ひとまず以下のように修正してみたのですが、今まで正しく表示されていたグリッドが変になってしまいました・・・。
Private Sub DataGridView1_CellPainting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
Dim xDgv As DataGridView = DirectCast(sender, DataGridView)
Dim xRect As Rectangle
Dim xCell As DataGridViewCell
Dim xHeaderText As String = String.Empty
' 行・列共にヘッダは処理しない
If e.RowIndex < 0 OrElse e.ColumnIndex < 0 Then
Return
End If
If e.ColumnIndex = 0 Then ' 1列目の処理
xRect = e.CellBounds
If e.RowIndex Mod 18 = 0 And e.RowIndex < 36 Then
xRect = e.CellBounds
xCell = DataGridView1(e.ColumnIndex, e.RowIndex)
'セルの高さを足す
xRect.Height += xCell.Size.Height * 17
' セルボーダーライン分矩形の位置を補正
xRect.X -= 1
xRect.Y -= 1
' 背景、セルボーダーラインを描画
e.Graphics.FillRectangle(New SolidBrush(DataGridView1.ColumnHeadersDefaultCellStyle.BackColor), xRect)
e.Graphics.DrawRectangle(New Pen(xDgv.GridColor), xRect)
If e.RowIndex = 0 Then
xHeaderText = "大項目a"
Else
xHeaderText = "大項目b"
End If
' セルの値を描画
TextRenderer.DrawText(e.Graphics, xHeaderText, e.CellStyle.Font, xRect, e.CellStyle.ForeColor, TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter)
' イベント ハンドラ内で処理を行ったことを通知
e.Handled = True
ElseIf e.RowIndex >= 36 Then
xRect = e.CellBounds
xCell = DataGridView1(e.ColumnIndex, e.RowIndex)
' セル2つ分の幅を足す
xRect.Width += xCell.Size.Width * 2
xRect.X -= 1
xRect.Y -= 1
' 背景、セルボーダーラインを描画
e.Graphics.FillRectangle(New SolidBrush(DataGridView1.ColumnHeadersDefaultCellStyle.BackColor), xRect)
e.Graphics.DrawRectangle(New Pen(xDgv.GridColor), xRect)
If e.RowIndex = 36 Then
xHeaderText = "特殊項目a"
ElseIf e.RowIndex = 37 Then
xHeaderText = "特殊項目b"
Else
xHeaderText = "特殊項目c"
End If
' セルの値を描画
TextRenderer.DrawText(e.Graphics, xHeaderText, e.CellStyle.Font, xRect, e.CellStyle.ForeColor, TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter)
' イベント ハンドラ内で処理を行ったことを通知
e.Handled = True
Else
e.Handled = False
End If
ElseIf e.ColumnIndex = 1 Then ' 2列目の結合処理
If e.RowIndex Mod 6 = 0 And e.RowIndex < 36 Then
xRect = e.CellBounds
xCell = DataGridView1(e.ColumnIndex, e.RowIndex)
'セルの高さを足す
xRect.Height += xCell.Size.Height * 6
' セルボーダーライン分矩形の位置を補正
xRect.X -= 1
xRect.Y -= 1
' 背景、セルボーダーラインを描画
e.Graphics.FillRectangle(New SolidBrush(DataGridView1.ColumnHeadersDefaultCellStyle.BackColor), xRect)
e.Graphics.DrawRectangle(New Pen(xDgv.GridColor), xRect)
If e.RowIndex = 0 Then
xHeaderText = "中項目a"
ElseIf e.RowIndex = 6 Then
xHeaderText = "中項目b"
ElseIf e.RowIndex = 12 Then
xHeaderText = "中項目c"
ElseIf e.RowIndex = 18 Then
xHeaderText = "中項目a"
ElseIf e.RowIndex = 24 Then
xHeaderText = "中項目b"
Else
xHeaderText = "中項目c"
End If
' 項目名の位置を調整
xRect.Y -= 10
' 項目名を描画
TextRenderer.DrawText(e.Graphics, xHeaderText, e.CellStyle.Font, xRect, e.CellStyle.ForeColor, TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter)
' イベント ハンドラ内で処理を行ったことを通知
e.Handled = True
Else
e.Handled = False
End If
ElseIf e.ColumnIndex = 2 Then ' 3列目の描画処理
If e.RowIndex < 36 Then
xRect = e.CellBounds
xCell = DataGridView1(e.ColumnIndex, e.RowIndex)
' セルボーダーライン分矩形の位置を補正
xRect.X -= 1
xRect.Y -= 1
' 背景、セルボーダーラインを描画
e.Graphics.FillRectangle(New SolidBrush(DataGridView1.ColumnHeadersDefaultCellStyle.BackColor), xRect)
e.Graphics.DrawRectangle(New Pen(xDgv.GridColor), xRect)
'項目名設定
If e.RowIndex Mod 6 = 0 Then
xHeaderText = "小項目a"
ElseIf e.RowIndex Mod 6 = 1 Then
xHeaderText = "小項目b"
ElseIf e.RowIndex Mod 6 = 2 Then
xHeaderText = "小項目c"
ElseIf e.RowIndex Mod 6 = 3 Then
xHeaderText = "小項目e"
ElseIf e.RowIndex Mod 6 = 4 Then
xHeaderText = "小項目f"
ElseIf e.RowIndex Mod 6 = 5 Then
xHeaderText = "小項目f"
End If
' セルの値を描画
TextRenderer.DrawText(e.Graphics, xHeaderText, e.CellStyle.Font, xRect, e.CellStyle.ForeColor, TextFormatFlags.Left Or TextFormatFlags.VerticalCenter)
' イベント ハンドラ内で処理を行ったことを通知
e.Handled = True
Else
e.Handled = False
End If
End If
End Sub
> なお、スクロール時に連結した項目のテキストが隠れてしまわないよう
>
> |−−−−|−−−−|−−−−|−|
> |大項目a |中項目a |小項目b |▲|
> | | |小項目c |−|
> | | |小項目d | |
> | | |小項目e | |
>
> のように、スクロールに応じて描画位置を変更するのか、それとも、
>
> |−−−−|−−−−|−−−−|−|
> | | |小項目b |▲|
> | | |小項目c |−|
> | | |小項目d | |
> | | |小項目e | |
>
> のように、見切れてしまって良いのかによっても、描画方法が
> 異なります。
後者を考えています。この場合は特に処理は不要という事になるのでしょうか?
> それともう一点。
>
> 現在のソースだと、ColumnIndex や RowIndex が -1 であった場合に
> 対応できていないようです。そのためこのままでは、
> xCell = DataGridView1(e.ColumnIndex, e.RowIndex)
> の処理を行うところで、インデクサが ArgumentOutOfRangeException を
> 発してしまうことになります。
> 行ヘッダ/列ヘッダを表示していないのであれば、そもそも
> -1 に対するイベントは発生しませんが、一応、対処しておくべきかと。
確かにその通りだと思います。
行ヘッダ/列ヘッダは非表示にしているのですが、
処理を入れておきます。
|