🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: japan.comp.lang.delphi
Article #15

Re: 画面モード切替後のグラフィックパフォーマンスの低下

#15
From: K.Takaoka
Date: Wed, 29 Dec 1999 00:00
125 lines
5104 bytes
える@海豚ぞな

林 知紀 wrote:
>>> Bitmap.Assign(Bitmap2);
>>> PaintBox1.Canvas.Draw(0,0,Bitmap);
>>> と若干冗長なコードが必要なのが面倒くさいところです。
>> これはちょっと意味がわからないです. 何をしたいのでしょうか ?
> 今まで場合によって
> Image1.Canvas.Draw(0,0,Bitmap);や
> Image1.Canvas.Draw(0,0,Bitmap2);
> と使い分けていたのですが
> TPaintBoxは自動更新してくれないので
> PaintBox1.OnPaintイベントに
> PaintBox1.Canvas.Draw(0,0,Bitmap);
> としなければならなくなりました。
> ということで今まで書いたソースの中から
> Bitmap2を駆逐していかなければならない状況です。

旧)
 Image1.Canvas.Draw(0,0,Bitmap);
 Image1.Canvas.Draw(0,0,Bitmap2);

新)
  Form1 の Private に

   bufferBitmap: TBitmap

  Form1.OnCreate

   bufferBitmap := TBitmap.Create;
   bufferBitmap.*** := ****;

  Form1.OnDestroy

   FreeAndNil(bufferBitmap);

 Image1.Canvas.Draw(0,0,Bitmap);

 → bufferedBitmap.Canvas.Draw(....

 Image1.Canvas.Draw(0,0,Bitmap2);

 → bufferedBitmap.Canvas.Draw(....


として、 PaintBox1.OnPaint で bufferedBitmap を描画する。

ですね ?

>       PaintBox1.Invalidate;
>       sleep(120);

> とすると途中経過なしにいきなりBmp2の画像を表示しました。
> どうもPaintBox1.Invalidateで再び有効になるのは
> プロシージャを抜け出してウインドウズに制御が戻ってからのようです。

別にループするのが悪いわけではないでしょうけど、ウィンドウズのプログ
ラムでは、全てのイベントは短い時間で終了するのが望ましいです。

中には、瞬時に内容を判断して即座に結果を戻さないとウィンドウズが狂っ
たようになってしまうイベントもあります。

しかも、この Sleep() な状態だと、ウィンドウズが「応答なし」と判断し
ユーザから見て異常な状態に見えてしまいます。

Sleep() ではなく Application.ProcessMessages() を使って待機するとい
うのが、この場で有効な手段ですが、これはオススメできません。

Application.ProcessMessages() は本当にどうしようもなくなった場合の
最後の手段であり、非常に危険なものです。
タイミングによってはアプリケーションが誤動作したり、一般保護違反を
発生させる原因になります。( 詳しくは delphi-ml の過去の記事を )

このようなアニメーションを行う場合は、1度のイベントでは1枚だけを描画
すべきだと思います。また CPU 速度などに依存しないようにするなら、もっ
と考慮すべき点はあると思います。

Sleep() 程度の精度でよいのであれば、Form1 の Private などで

iImage: Integer;

と、 for i := 0 to 34 do の i の値を保存しておく場所を持っておいて
OnPaint で、

  for j := 0 to 8 do
  begin
    k := iImage*18 + j*16 - 130;
      if (k > 1) AND (k < 481) then
      begin
        VRect := rect(0,k-2,640,k);
        PaintBox1.Canvas.CopyRect(VRect,Bmp2.Canvas,VRect);
      end;
  end;

を、実行することにし、

TTimer などを利用して、

procedure TForm1Timer1Timer(Sender: TObject);
begin
   Inc(iImage);
   PaintBox1.Invalidate;
end;

などとします。

こうすれば

・何時でも応答できる正常な状態を保ちつつ
・指定ミリ秒以上経過したら次へと表示を進め
・アニメーション的にパラパラと内容が変わる途中で、他のウィンドウなどで
  隠れたりしても、正常に OnPaint が現在の内容を復旧できる

となります。

ps.
  Screen という変数名は Delphi も使っていますから、混乱を避けるため
  には使わないほうがいいと思います.

  個人でやっているうちはどうでもいいといえば、どうでもいいんですが、
  他人に見せたり多人数で作業するプロダクトであったり、後から自分で
  見て混乱しないためにも、Screen といえば Delphi が用意している
  TScreen のグローバルインスタンスである状態にしておくのがいいかと(^^;

# 私も個人で休日などにちょろっと触ってるだけなんですけどね > Delphi
Technical Details
Message-ID: <3869F6A5.A18F2492@din.or.jp>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <83ou3d$jvv$1@nw041.infoweb.ne.jp> <3860CAFB.E16988D7@po.teleway.ne.jp> <83u3iq$i92$1@nw041.infoweb.ne.jp> <842u63$fpk@www.net0726.or.jp> <8451vt$ojp$1@nw042.infoweb.ne.jp> <38661455.CECA03D4@din.or.jp> <845ji4$1l$1@nw042.infoweb.ne.jp> <3866712B.F98B267D@din.or.jp> <84ci6p$57i$1@nw042.infoweb.ne.jp>

Show Full Headers
Complete Article Headers
X-Google-Language: Japanese,JIS
X-Google-Thread: 110a07,f2bd283c630b1b34
X-Google-Attributes: gid110a07,public
X-Google-Thread: fecfa,f2bd283c630b1b34
X-Google-Attributes: gidfecfa,public
X-Google-Thread: feb2e,f2bd283c630b1b34
X-Google-Attributes: gidfeb2e,public
From: "K.Takaoka" <saepro@din.or.jp>
Subject: Re: 画面モード切替後のグラフィックパフォーマンスの低下
Date: 1999/12/29
Message-ID: <3869F6A5.A18F2492@din.or.jp>
X-Deja-AN: 566075702
Content-Transfer-Encoding: 7bit
References: <83ou3d$jvv$1@nw041.infoweb.ne.jp> <3860CAFB.E16988D7@po.teleway.ne.jp> <83u3iq$i92$1@nw041.infoweb.ne.jp> <842u63$fpk@www.net0726.or.jp> <8451vt$ojp$1@nw042.infoweb.ne.jp> <38661455.CECA03D4@din.or.jp> <845ji4$1l$1@nw042.infoweb.ne.jp> <3866712B.F98B267D@din.or.jp> <84ci6p$57i$1@nw042.infoweb.ne.jp>
X-Accept-Language: ja,en
Content-Type: text/plain; charset=iso-2022-jp
Organization: DOLPHIN INTERNET, Tokyo, Japan.
Mime-Version: 1.0
Newsgroups: japan.comp.lang.delphi,fj.comp.lang.pascal,fj.os.ms-windows.programming