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

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

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

Re[5]: エディタのスムーズスクロールのテクニック


(過去ログ 22 を表示中)

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

■9623 / inTopicNo.1)  エディタのスムーズスクロールのテクニック
  
□投稿者/ y4yama (32回)-(2007/11/01(Thu) 09:00:15)

分類:[.NET 全般] 

質問いたします
VB2005の勉強を兼ねて、エディタを作ってみたいのです
行末の改行マークとかを入れるので、文字も全てBitmapに描画します

例として、VB2005の開発環境で、ソースコードをマウス中ボタンで押さえたまま上下に動かすと
とてもスムーズに(縦の1文字分でなくピクセル毎に)スクロールします
これは、どのようなテクニックを使うのが最も良いのでしょうか?
スピード(描画更新速度)を重視したいです。(エディタに限らず地図の一部表示のスクロールでも同じだと気づきました)
勉強のためですので、ソースのないDLLとかは除外したいです

単純には、2ピクセル毎にでもDrawStringで位置を変えながら全画面を書き直す
または、中央のほとんどはコピー(BitBlt的に)で移動させて上(か下)の1行のみを書き込むとかは
思いつくのですが、もっと画期的なテクがあるのでは?と思いまして
何かヒントがあれば、キーワードをご教授下さいますようお願いします

引用返信 編集キー/
■9624 / inTopicNo.2)  Re[1]: エディタのスムーズスクロールのテクニック
□投稿者/ 渋木宏明(ひどり) (506回)-(2007/11/01(Thu) 10:06:55)
渋木宏明(ひどり) さんの Web サイト
> 単純には、2ピクセル毎にでもDrawStringで位置を変えながら全画面を書き直す

毎回全画面描きなおしは遅くなると思います。

原則は

> または、中央のほとんどはコピー(BitBlt的に)で移動させて上(か下)の1行のみを書き込むとかは
> 思いつくのですが、

でしょう。

> もっと画期的なテクがあるのでは?と思いまして

↑の応用で、比較的効果が出そうなパターンは

・オフスクリーン用の Bitmap は表示サイズ+前後1行分の大きさのものを準備
・1行分のスクロールは↑の Bitmap を1〜数ピクセルずらして BitBlt することで対応
・オフスクリーンに1行分描画して次のスクロールに備える

なんてあたりでしょう。

その上で

・1行単位で Bitmap をキャッシュしておく
・アイドル時に表示範囲の近傍の行を先行して Bitmap 化&キャッシュしておく

なんてことも考えられますが、ミスヒットした時にスクロールがガタつく可能性もありますね。

引用返信 編集キー/
■9640 / inTopicNo.3)  Re[1]: エディタのスムーズスクロールのテクニック
□投稿者/ シャノン (219回)-(2007/11/01(Thu) 14:35:30)
No9623 (y4yama さん) に返信
> 質問いたします
> VB2005の勉強を兼ねて、エディタを作ってみたいのです
> 行末の改行マークとかを入れるので、文字も全てBitmapに描画します
>
> 例として、VB2005の開発環境で、ソースコードをマウス中ボタンで押さえたまま上下に動かすと
> とてもスムーズに(縦の1文字分でなくピクセル毎に)スクロールします
> これは、どのようなテクニックを使うのが最も良いのでしょうか?
> スピード(描画更新速度)を重視したいです。(エディタに限らず地図の一部表示のスクロールでも同じだと気づきました)
> 勉強のためですので、ソースのないDLLとかは除外したいです
>
> 単純には、2ピクセル毎にでもDrawStringで位置を変えながら全画面を書き直す
> または、中央のほとんどはコピー(BitBlt的に)で移動させて上(か下)の1行のみを書き込むとかは
> 思いつくのですが、もっと画期的なテクがあるのでは?と思いまして
> 何かヒントがあれば、キーワードをご教授下さいますようお願いします

SDKならScrollWindowExとかいうちょー便利なAPIがあるんですけどねw
引用返信 編集キー/
■9650 / inTopicNo.4)  Re[2]: エディタのスムーズスクロールのテクニック
□投稿者/ y4yama (33回)-(2007/11/01(Thu) 16:58:15)
貴重なhintをいただきまして、大変ありがとうございます
早速あしたから、テストをしてみて、何らかの報告をさせていただきます
引用返信 編集キー/
■9701 / inTopicNo.5)  Re[3]: エディタのスムーズスクロールのテクニック
□投稿者/ y4yama (34回)-(2007/11/02(Fri) 15:43:35)
報告をさせていただきます
毎秒50回くらいの更新でどの位CPU%となるか、で判断しました
1行に1回のDrawStringで位置を変えながら全画面を書き直す  -->CPU 2%位でOK
1行を文字数分のDrawStringで書き、全画面を書き直す -->CPU 50%とか100
以下は1つのBitmapだけでのテストです
CopyFromScreenで中央のほとんどはコピー -->CPU 50%とか
Marshal.Copyで中央のほとんどはコピー  -->CPU 2%位
Marshal.Copyの凄さが理解できました。
            Dim bmpData As Imaging.BitmapData _
                = bmp1.LockBits(rect, ImageLockMode.ReadWrite, bmp1.PixelFormat)
            Dim ptr As IntPtr = bmpData.Scan0
            Dim bytes0 As Integer = bmp1.Width * bmp1.Height * 4
            Dim bytes2 As Integer = bmp1.Width * 4 * pH
            Dim rgbValues(bytes0 - 1) As Byte 
            Dim cp_byte = bytes0 - bytes2
                System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes0)
                System.Runtime.InteropServices.Marshal.Copy(rgbValues, bytes2, ptr, cp_byte)
            bmp1.UnlockBits(bmpData)
こちらの過去ログを参考に、このようにしてみましたが、気になることがあります
一度、rgbValues()に引取ることは、なんとなくイヤなのです
もし、bmpDataの中で直接copyできる方法がありましたら、ご教授の程よろしくおねがいします

引用返信 編集キー/
■9737 / inTopicNo.6)  Re[4]: エディタのスムーズスクロールのテクニック
□投稿者/ 渋木宏明(ひどり) (507回)-(2007/11/03(Sat) 00:10:32)
渋木宏明(ひどり) さんの Web サイト
2007/11/03(Sat) 01:08:51 編集(投稿者)

> 一度、rgbValues()に引取ることは、なんとなくイヤなのです
> もし、bmpDataの中で直接copyできる方法がありましたら、ご教授の程よろしくおねがいします

Masrhal.Copy には IntPtr to IntPtr の転送が用意されてないようなんで、標準ライブラリの範囲では出来なさそうです。

とすると、unsafe にして自分でループ回してコピーって方向もありそうだけど、あまり目覚ましいパフォーマンス向上は無いんじゃないかなぁ。
実測とかしてないんで、「勘」ですけど。

ちゅーか、現状でもまだチューニングの余地があるんじゃないかと。
どうせビットマップデータは4バイト境界に整列しているので、byte 配列としてコピーするのではなく、long 配列としてコピーした方が速くなるんじゃないかな。

引用返信 編集キー/
■9803 / inTopicNo.7)  Re[5]: エディタのスムーズスクロールのテクニック
□投稿者/ y4yama (35回)-(2007/11/05(Mon) 08:15:31)
No9737 (渋木宏明(ひどり) さん) に返信

> どうせビットマップデータは4バイト境界に整列しているので、byte 配列としてコピーするのではなく、long 配列としてコピーした方が速くなるんじゃないかな。

渋木宏明(ひどり) さん, ご指摘をありがとうございました
long でやってみます。
ひとりで思い悩むよりも収穫がありました。皆様、ありがとうございました。これにて、解決済みといたします
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -