C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

DataGridView 再描画について

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■88032 / inTopicNo.1)  DataGridView 再描画について
  
□投稿者/ C#勉強中 (6回)-(2018/07/30(Mon) 15:28:34)

分類:[.NET 全般] 

お世話になります。

DataGridView の CellPainting イベントで、
セルクリック時に、選択セルに対して
独自に背景の塗りつぶしや文字描画をしています。
(複数選択はできないようにしています)

コードは正常に動作するのですが、
どこかのセルをクリックして選択後、
次のセルを選択すると直前の選択セルに対して
何故、コードを書かずに自動で処理をしてくれるのですか?


CellPainting イベントのコードです。

private void objDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex >= 0 && e.RowIndex >= 0
&& (e.PaintParts & DataGridViewPaintParts.Background) == DataGridViewPaintParts.Background)
{
if (objDataGridView.Rows[e.RowIndex].Selected)
{
return;
}
else
{
//セルが選択された時
e.Graphics.FillRectangle(new SolidBrush(e.CellStyle.BackColor), e.CellBounds);
if ((e.PaintParts & DataGridViewPaintParts.SelectionBackground) == DataGridViewPaintParts.SelectionBackground
&& (e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected)
{
Rectangle rec;

rec = e.CellBounds;

rec.X += 1;
rec.Y += 1;
rec.Width += -3;
rec.Height += -3;

e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(0,255,255)),rec);

//色を反転
Color c = Color.FromArgb(e.CellStyle.ForeColor.ToArgb() ^ 0xffffff);
TextFormatFlags txtflag = GetTextFormatFlags(e.CellStyle.Alignment);

TextRenderer.DrawText(e.Graphics, e.Value.ToString(), e.CellStyle.Font, rec, c, txtflag);

e.Handled = true;
}
}
}
}




引用返信 編集キー/
■88035 / inTopicNo.2)  Re[1]: DataGridView 再描画について
□投稿者/ グッディ (2回)-(2018/07/30(Mon) 15:36:33)
CellPaintingイベントは、任意のセルの再描画が必要になったときに
自動的に呼び出されます。
グリッドをスクロールする時とか(スクロールで位置や表示の変わったセルを描画)、
別のセルを選択した時とか(選択状態を描画)。

質問の意図に沿った答えになっていますでしょうか?
引用返信 編集キー/
■88036 / inTopicNo.3)  Re[1]: DataGridView 再描画について
□投稿者/ Hongliang (664回)-(2018/07/30(Mon) 15:38:35)
DataGridViewのセル描画処理がこんな感じになってるからでは?

var e = new DataGridViewCellPaintingEventArgs(...);
this.CellPainting(this, e); // objDataGridView_CellPaintingが呼び出される
if (! e.Handled) {
  this.PaintCellDefault(e);
}

引用返信 編集キー/
■88037 / inTopicNo.4)  Re[1]: DataGridView 再描画について
□投稿者/ 魔界の仮面弁士 (1750回)-(2018/07/30(Mon) 15:43:51)
No88032 (C#勉強中 さん) に返信
> どこかのセルをクリックして選択後、
> 次のセルを選択すると直前の選択セルに対して
> 何故、コードを書かずに自動で処理をしてくれるのですか?

選択解除されたからでは無いでしょうか?

CellPainting が呼ばれるたびに、「e.ColumnIndex」「e.RowIndex」「e.State」の内容を
Debug.WriteLine(foo); あるいは listBox1.Items.Insert(0, foo); などを使って、
記録してみると、理由が見えてくるかもしれません。



> CellPainting イベントのコードです。

『e.Handled = true;』が指定されなかった場合には、既定の描画処理が行われますね。
そして CellPainting が呼ばれる要因としては、たとえばこのような物があります。(他にもありますが)

・セルがフォーカスを持った
・セルのフォーカスが喪失した
・セルが選択状態になった
・セルの選択が解除された
・水平/垂直スクロールによって、セルの表示されている領域が増えた
・自身または自分以外の、行または列のサイズの増減により、セルの表示されている領域が増えた
・InvalidateCell メソッドが呼び出された
引用返信 編集キー/
■88039 / inTopicNo.5)  Re[2]: DataGridView 再描画について
□投稿者/ C#勉強中 (8回)-(2018/07/30(Mon) 17:18:29)
グッディ さん、Hongliang さん、魔界の仮面弁士 さん
ご返信ありがとうございます。

Hongliang さん、上に貼り付けてくれたコードはどこで確認できますか?



本題の件については、最終的に魔界の仮面弁士さんのやり方で 
CellPainting に デバッグコードを埋め込んで確認し、
以下のようなログを得ることができ大まかな流れは分かったのですが、
これって一度、行単位で選択している?という意味ですか?

>C = -1, R = 0, State = Displayed, Visible

よろしくおねがいします。


実際に確認したログも貼り付けます。

クリック前セル位置 [0,0]
クリック後セル位置 [2,4]

<ログ>
C = e.ColumnIndex、R = e.RowIndex, State = e.State

MouseDown
C = 0, R = 0, State = Displayed, Selected, Visible
C = 0, R = 0, State = Displayed, Selected, Visible
MouseUp
C = 0, R = 0, State = Displayed, Selected, Visible
C = 0, R = 0, State = Displayed, Selected, Visible
MouseDown
C = -1, R = 0, State = Displayed, Visible
C = 0, R = 0, State = Displayed, Visible
C = 1, R = 0, State = Displayed, Visible
C = 2, R = 0, State = Displayed, Visible
C = -1, R = 1, State = Displayed, Visible
C = 0, R = 1, State = Displayed, Visible
C = 1, R = 1, State = Displayed, Visible
C = 2, R = 1, State = Displayed, Visible
C = -1, R = 2, State = Displayed, Visible
C = 0, R = 2, State = Displayed, Visible
C = 1, R = 2, State = Displayed, Visible
C = 2, R = 2, State = Displayed, Visible
C = -1, R = 3, State = Displayed, Visible
C = 0, R = 3, State = Displayed, Visible
C = 1, R = 3, State = Displayed, Visible
C = 2, R = 3, State = Displayed, Visible
C = -1, R = 4, State = Displayed, Visible
C = 0, R = 4, State = Displayed, Visible
C = 1, R = 4, State = Displayed, Visible
C = 2, R = 4, State = Displayed, Selected, Visible
C = 2, R = 4, State = Displayed, Selected, Visible
MouseUp
C = 2, R = 4, State = Displayed, Selected, Visible
C = 2, R = 4, State = Displayed, Selected, Visible


引用返信 編集キー/
■88042 / inTopicNo.6)  Re[3]: DataGridView 再描画について
□投稿者/ Hongliang (665回)-(2018/07/30(Mon) 17:30:10)
> Hongliang さん、上に貼り付けてくれたコードはどこで確認できますか?

仮想コードです。あくまで私の想像です。
具体的にはもっと複雑だったりするでしょう。
実際のコードは
http://referencesource.microsoft.com/
辺り見れば多分載っています。

RowIndexやColumnIndexが-1なのは、ヘッダセルを意味します。
引用返信 編集キー/
■88044 / inTopicNo.7)  Re[4]: DataGridView 再描画について
□投稿者/ C#勉強中 (9回)-(2018/07/30(Mon) 17:48:05)
Hongliang さん
ソースコードありがとうございました。
私の知識不足で理解できないと思いますが、
少しずつ確認してみます。

回答していただいた方々ありがとうございました。
解決済みにチェックを入れておきます。



解決済み
引用返信 編集キー/
■88045 / inTopicNo.8)  Re[4]: DataGridView 再描画について
□投稿者/ 魔界の仮面弁士 (1755回)-(2018/07/30(Mon) 17:48:05)
No88042 (Hongliang さん) に返信
> 実際のコードは
> http://referencesource.microsoft.com/
> 辺り見れば多分載っています。

具体的には、このあたりでしょうね。
https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/DataGridViewCell.cs#4387

※現時点では、.NET Framework 4.7.2 の DataGridViewCell.cs のソースが表示されるはず。



> var e = new DataGridViewCellPaintingEventArgs(...);

上記は 4374 行目に相当。
DataGridViewCellPaintingEventArgs dgvcpe = dataGridView.CellPaintingEventArgs;


> this.CellPainting(this, e); // objDataGridView_CellPaintingが呼び出される
上記は 4387 行目に相当。
 dataGridView.OnCellPainting(dgvcpe);


> if (! e.Handled) {
>  this.PaintCellDefault(e);
> }
上記は 4388〜4403 行目に相当。
 if (dgvcpe.Handled)
 {
  return;
 }
 
 Paint(graphics,
    clipBounds,
    cellBounds,
    rowIndex,
    cellState,
    value,
    formattedValue,
    errorText,
    cellStyle,
    advancedBorderStyle,
    paintParts);
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ