[Delphi:90262] Gridコンポにグラフ

205 views
Skip to first unread message

近藤

unread,
Feb 5, 2008, 10:49:49 PM2/5/08
to Del...@ml.users.gr.jp

 Gridコンポにグラフを書きたいのですがどのようにすればよいでしょうか?
 現在TCustomGridを継承したクラスに
 
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState:
TGridDrawState); override;

 としてここに書こうかと思いましたがCellだけの描画ですのでダメだと考え、
 
procedure Paint; override;


procedure TCustomHsCalendarGrid.Paint;
var
R: TRect;
H, W, Offset: Integer;
begin
inherited Paint;
FillChar(R, SizeOf(R), 0);
H := 30;
W := 100;
Offset := 50;

R.Top := 100;
R.Left := 10;

R.Right := R.Left + W;
R.Bottom := R.Top + H;
Canvas.Brush.Color := clAqua;
Canvas.FillRect(R);

R.Top := Offset+ R.Bottom;
R.Right := R.Left + W;
R.Bottom := R.Top + H;
Canvas.Brush.Color := clDkGray;
Canvas.FillRect(R);

R.Top := Offset+ R.Bottom;
R.Right := R.Left + W;
R.Bottom := R.Top + H;
Canvas.Brush.Color := clRed;
Canvas.FillRect(R);
end;

 とゆうように書きましたが、描画はされるがスクロールされると消えしまうだ
けでなくスクロールによって消えていた箇所の描画が表示されません。

 どうすればよいでしょうか?

khe00221

unread,
Feb 6, 2008, 12:53:18 AM2/6/08
to Del...@ml.users.gr.jp
TImage を Gridの上に乗せるってが、移動も出来て簡単そうだけど

こんなのはどうかな?

--------------------------------
http://khe00221.image.coocan.jp/
--------------------------------

procedure TForm2.StringGrid1DrawCell(Sender: TObject; ACol, ARow:
Integer;
ARect: TRect; State: TGridDrawState);
var
X1,X2,W,StartCol,StartRow : Integer;
XRect : TRect;
begin

X1 := 30; // 数値
X2 := 50; // 1 Col 当たりの数値
StartCol := 2; // 開始 Col
StartRow := 2; // 開始 Row

if ARow =StartRow then
begin
if ACol >= StartCol then
begin
if (ACol - StartCol) * X2 < X1 then
begin
if (X1 div X2) < (ACol-StartCol+1) then
begin
W := (ARect.Right - ARect.Left) * (X1 mod X2) div X2;
XRect := Rect(ARect.Left,ARect.Top,ARect.Left +
W,ARect.Bottom);
StringGrid1.Canvas.Brush.Color := clRed;
StringGrid1.Canvas.FillRect(XRect);
end
else
begin
if ACol = StartCol then
begin
XRect :=
Rect(ARect.Left,ARect.Top,ARect.Right+1,ARect.Bottom);
end
else
begin
XRect :=
Rect(ARect.Left-1,ARect.Top,ARect.Right+1,ARect.Bottom);
end;
StringGrid1.Canvas.Brush.Color := clRed;
StringGrid1.Canvas.FillRect(XRect);
end;
end;
end;
end;

Exit;
end;

近藤

unread,
Feb 6, 2008, 3:58:28 AM2/6/08
to Del...@ml.users.gr.jp
 近藤です。

 ソースコードのご提示ありがとうございました。
 ただ、DrawCellイベントでは、セル単位での描画を対称にしています。ぼくが
したいのはRow単位やCol単位での描画したいのです。


khe00221

unread,
Feb 6, 2008, 4:40:53 AM2/6/08
to Del...@ml.users.gr.jp
1 Col 当たりのデータを50して 120のデータを与えれば 3 Col 使用します
が?

http://khe00221.image.coocan.jp/index.php?FrontPage%2FTips2%2F%A5%B3%A5%
F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8%20-%20TStringGrid%2F%A5%B0%A5%E9%A5%D5%
A4%F2%C9%C1%B2%E8%A4%B9%A4%EB

-----Original Message-----
From: 近藤 [mailto:t_k...@hazimesoft.com]
Sent: Wednesday, February 06, 2008 5:58 PM
To: Del...@ml.users.gr.jp

近藤

unread,
Feb 6, 2008, 5:07:36 AM2/6/08
to Del...@ml.users.gr.jp
 近藤です。

 まことに申し訳ありません。いろいろとコメント感謝しております。
 おっしゃってられる意味は理解しております。

 ただ、やはりDrawCellイベントだと文字がCell単位になるのではという考えか
らDrawCellイベントでは。。。と考えています。最初に「文字も」と書いとけば
よかったと反省しています。

khe00221

unread,
Feb 6, 2008, 5:34:35 AM2/6/08
to Del...@ml.users.gr.jp
DefaultDrawing を False にして

procedure TForm2.StringGrid1DrawCell(Sender: TObject; ACol, ARow:
Integer;
ARect: TRect; State: TGridDrawState);

begin
if (ACol=3) and (ARow=3) then
begin
StringGrid1.Canvas.Brush.Color := clRed;

StringGrid1.Canvas.FillRect(Rect(ARect.Left,ARect.Top,ARect.Right*2,ARec
t.Bottom));

StringGrid1.Canvas.TextOut(ARect.Left+2,ARect.Top+1,'AAAAAAAAAAAAAAAAAAA
');
end;
end;

等とすればCELLを越えて描画できますよ?

全て自前で描画する必要はありますが

-----Original Message-----
From: 近藤 [mailto:t_k...@hazimesoft.com]
Sent: Wednesday, February 06, 2008 7:08 PM
To: Del...@ml.users.gr.jp

近藤

unread,
Feb 6, 2008, 6:18:00 AM2/6/08
to Del...@ml.users.gr.jp
 近藤です。

|DefaultDrawing を False にして
|全て自前で描画する必要はありますが

 他の描画処理を自前で書くには困難ですので、Paint;でできないか?というご
相談を申し上げているところです。

SilverWhale

unread,
Feb 8, 2008, 3:35:45 AM2/8/08
to Del...@ml.users.gr.jp
SilverWhaleです

要件があいまいなような気がしますが、
T~Gridを内部で保持したTScrollBox継承クラスを作成し、
さらに棒グラフっぽいTPanelなりTProgressBarなりを
動的に生成すれば良いのではないでしょうか?
GridではスクロールしないでScrollBoxでってことで

--
SilverWhale <Silve...@nifty.com>
Delphi5/7 Enterprise
WinXP Pro SP2


tknak...@brain-tokyo.jp

unread,
Feb 8, 2008, 9:55:04 AM2/8/08
to Del...@ml.users.gr.jp
中村@ブレーンです。

やりたいことがつかめないのですが、

■Paint は無効領域を描画するだけです。無効領域を適切に
管理しないとスクロールで表示が乱れるのは当然です。

TCustomGrid の中には InvalidateCell とか InvalidateRow とか
無効領域管理のメソッドが用意されていますのでこれらを活用しましょう。
#スクロールとは無関係に一定の場所に描きたいのでしょうか???

■DrawCellのOverride も検討すべきです。
こちらのほうが必セルの座標の取得が簡単だからです。
DefaultDarwing を OFF にして、同様の処理を DrawCellに持たせるのは
容易です。また、セルに跨って文字を描くのを複数回の DrawCell の描画に
分担させるのもそれほど難しくありません。

Quoting 近藤 <t_k...@hazimesoft.com>:

----------
(株)ブレーン 中村拓男

近藤

unread,
Feb 8, 2008, 9:47:42 PM2/8/08
to Del...@ml.users.gr.jp
 近藤です。

|やりたいことがつかめないのですが、

 理想的にはスケジューラーとして横帯の棒グラフ形状の表示及び文字列などの
表示ができればOKだと考えています。もちろんマウスで移動という処理ができれ
ば理想ですが、一足飛びや2足飛びではできませんから、現段階では表示のみで
OKです。

|■Paint は無効領域を描画するだけです。無効領域を適切に
|管理しないとスクロールで表示が乱れるのは当然です。

 で、とりあえず、以下の処理を書いてみました。表示や文字はDrawCell2で書
くことでぎりぎり合格点の可能性があるという感じです。

procedure TCustomxxxxGrid.Paint;
var
DrawInfo: TGridDrawInfo;
//このままの処理では1行に1つだけ
procedure DrawCells2(ARow: Longint; StartY, StopX, StopY: Integer);
var
CurCol, CurRow: Longint;
Where: TRect;
begin
CurRow := ARow;
Where.Top := StartY + 20;
while (Where.Top < StopY) and (CurRow < RowCount) do
begin
CurCol := 0;//ACol;
Where.Left := ColWidths[CurCol] + 1;
Where.Bottom := Where.Top + RowHeights[CurRow] - 40;
Where.Right := Where.Left - 1 + (DefaultColWidth + DrawInfo.
Vert.EffectiveLineWidth) * 4;//ColWidths[CurCol]* 3;// * (ColCount -
4));
if (Where.Right > Where.Left) and RectVisible(Canvas.Handle,
Where) then
begin
if DefaultDrawing or (csDesigning in ComponentState) then
DrawCell2(CurCol, CurRow, Where); //ここに描画コード
end;
with DrawInfo do
begin
Where.Left := Where.Right + Horz.EffectiveLineWidth;
Where.Top := Where.Bottom + Vert.EffectiveLineWidth + 40;
end;
Inc(CurRow);
end;
end;

begin
inherited Paint;
CalcDrawInfo(DrawInfo);
with DrawInfo do
DrawCells2(TopRow, Vert.FixedBoundary, Horz.FixedBoundary, Vert.
GridBoundary);
end;
 
 しかし、上記コードだと将来的な処理(マウスイベント、フォーカスイベント
など)へのコーティングが無理そうな気がしています。
 ここは、TGraphicControlあたりを継承したものをGridに載せたらよいのか
な?とも考えています。

|
|TCustomGrid の中には InvalidateCell とか InvalidateRow とか
|無効領域管理のメソッドが用意されていますのでこれらを活用しましょう。
|#スクロールとは無関係に一定の場所に描きたいのでしょうか???

 スクロールイベントなどはGridで取れますか?取れれば再描画処理でOKです。
実はスクロールイベントの取り方を知りません。
 再描画処理が使えるとバリエーションが増えます。


tknak...@brain-tokyo.jp

unread,
Feb 12, 2008, 9:02:12 PM2/12/08
to Del...@ml.users.gr.jp
中村@ブレーンです。

余り細かく見ていないのですが、WMVScroll/WMHScroll メッセージ処理メソッドで
スクロールメッセージを捕らえています。

procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;


procedure XXXGrid.WMVScroll(var Msg: TWMVScroll);
begin
inherited;
invalidate;
end;
procedure XXXGrid.WMHScroll(var Msg: TWMHScroll);
begin
inherited;
invalidate;
end;

などとするのがよいかもしれません。
#これらのメソッドでは ScrollWindow でウィンドウ内の表示イメージを転送して
#再描画を最小限に抑えているようです。
#Invalidate で再描画領域がウィンドウ全体に広がると思いますが、未試験です。

Quoting 近藤 <t_k...@hazimesoft.com>:

>  スクロールイベントなどはGridで取れますか?取れれば再描画処理でOKです。
> 実はスクロールイベントの取り方を知りません。
>  再描画処理が使えるとバリエーションが増えます。
>

----------
(株)ブレーン 中村拓男

近藤

unread,
Feb 14, 2008, 12:40:37 AM2/14/08
to Del...@ml.users.gr.jp
 近藤です。

| procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
| procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;

 これはぼくもこの質問を上げる前にチェックしてみましたが、スクロールバー
の操作のみのメッセージは取得できますが、その他のスクロールのメッセージは
取得できなかったです。

 ですから、Gridの場合のこうした処理にはPaintイベントしかダメかな?など
と考えているところです。

Reply all
Reply to author
Forward
0 new messages