HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0727
とあるプログラマ内容のサイズが動的なコントロールの描画7未解決


とあるプログラマ

リンク

2020/7/27(Mon) 00:59:32|NO.91075

懲りずにいまだ自作コントロール作成について研究しています。
今回は内容のサイズが動的なコントロールの描画です。


リストボックス、エディットコントロール、ブラウザ(IEコンポーネント)といった内容が動的に変化するコントロール(即ちスクロールバーが発生するコントロール)は初期化の段階で内容の大きさを知ることは不可能です。
しかしウィンドウは初期化時点で最大サイズが固定されるため初期化時以上の大きさにすることはできません。
つまりウィンドウを子ウィンドウ化して基盤にしてそこに内容を描画してやり、その子ウィンドウをさらにコントロールの内側に貼り付けてスクロール といったことは不可能です。


ではどう描画するか。仕方がないのでコントロールに直接描画していくしかありません。
ですがコントロールをスクロールしたときに全てをいちいち描画しているようではCPUとメモリを大量に使用してしまいます。スクロールバーのスクロール(サム)位置を取得し表示領域の範囲のみを描画するにせよ内容が多い場合はそのぶん計算や内容値の取得で余計な手間がかかり、これまたCPUの無駄な消費に繋がります。

例えばエディットコントロールであればスクロール位置から 何行目から何行目を描画するか決めてさらにその行分の内容を取得し…と作業が多くなってしまいます。ですがあらかじめ広い領域に描画しておきそれをスクロールするという方式ではこの手間は無くなります。
またIEコンポーネントのようなページを表示するものであればさらにその中身のコントロールもまた置きなおしなんてことに…


なのでこういった内容のサイズが動的なスクロールを含むコントロールはどのように描画するのが良いのでしょうか。
特に既存のこういったコントロールはどのようにして描画を行う仕組みなのでしょうか。


かなりイレギュラーな質問だとは思いますが、ちょっとした知識や方法をご存じであれば是非ともご教授お願い致します。

それと本題とは少しずれますが、こういった自作コントロールのあれこれ または既存のコントロールの仕組み等 GUI開発について解説しているサイトや本がありましたらそちらでも是非お教えいただきたいです。



この記事に返信する


siki__

リンク

2020/7/27(Mon) 19:14:13|NO.91079

にわか素人プログラマーの見解

・データサイズが決まってなければメモリのオーバーフローが起きるのではないか
・予め予想できる最大値を使う方法しか思い付かない
・データを一枚の絵として認識して、詳細はメモリが許すかぎり計算するとか
・解決不能な問題かな
・画面表示にも限りがある(解像度とか文字の大きさとか
・パソコンに自己修復と進化の機能があれば・・・

ふと、こんなこと思ってしまいました。
まああまり問題を理解してないので流してください。



あらや

リンク

2020/7/27(Mon) 19:42:56|NO.91080

同じく何がしたいのかがよくわかっていませんが。。。

とあるプログラマさんは
毎フレールコントロールを再描画するような事をしたいのでしょうか?

基本的にコントロールは新規読み込み時などの場合に
一括で全体を描画し、stopかループで操作されるのを待って
操作されたときには割り込み処理で操作に対応押した反応を返す
というのが一般的かと思います。

描画は読み込み時や再読み込み時など内容が変化する時だけで、
スクロールしたときの反応はOSが自動でやってくれているような感覚です。



ベイン

リンク

2020/7/27(Mon) 21:51:13|NO.91082

参考になるかは分かりませんが、とりあえず
ブラウザのレンダリング (描画) に関する記事を貼っておきます。

[ブラウザレンダリング入門〜知ることで見える世界〜]
(https://qiita.com/codemafia0000/items/caed57ec30d638e40728)

[Let's build a browser engine! Part 1\: Getting started]
(https://limpet.net/mbrubeck/2014/08/08/toy-layout-engine-1.html)

オープンソースの UI ツールキットのソースコードを読んでみるのもよいと思います。

----

> 例えばエディットコントロールであれば
> スクロール位置から何行目から何行目を描画するか決めて
> さらにその行分の内容を取得し…と作業が多くなってしまいます。

再描画に必要な情報を可能なかぎり事前に計算しておくのが基本戦略だと思います。

例えばエディットコントロールの場合、
スクロールしても各行がどの位置で折り返されるかは変化しないので、
あらかじめ行を分割しておくことが考えられます。
そうすればスクロール位置が変化した後に
描画すべき行や列の範囲を X, Y 座標から高速に逆算できるはずです。

----

これはただの思いつきですが、
事前に描画しておくにしても可視領域の ±300px ぐらいだけで十分な気がします。
スクロール位置が1フレームで大幅に変化することは頻繁にはないからです。



とあるプログラマ

リンク

2020/7/27(Mon) 22:05:07|NO.91083

>>あらやさん

分かりにくくて申し訳ありません… 説明下手なのでどうかお許しを。

もう少し具体的に言いますと、今現在はリストビューに近いようなコントロールを作成したいと思っています。さらに言うと複数行のリストビューのようなものです。

文字だけでは分かりにくいと思うので画像を用意しました。
1:https://i.imgur.com/qEg6RH1.png
2:https://i.imgur.com/olyflv7.png
この画像のコントロールはクリックした際のヒット範囲や管理の範囲は1アイテムごとになります。(すなわちアイコン部をクリックしても内容(文字列)部をクリックしても扱いは同じになる)

以下はこの画像のコントロールを想定としての話で進めていきます。


>>毎フレールコントロールを再描画するような事をしたいのでしょうか?
常に描画をし続けるのではなくスクロールしたときやアイテムを追加・削除したときといった再描画が必要な場合のみの再描画です。

しかしアイテム数が不定(今のところ上限はない・もしくは1024個など巨大な値)でありかつコントロールを置いた後にもアイテムを追加・削除するという性質上、描画に必要なエリアを初期化時点で把握するのは無理です。
また コントロールはウィンドウのサイズ変更に合わせてコントロール自体の大きさも変更する予定です。

ですが初期化時点で最大となるような大きさでA2Dのイメージを作成してはメモリの消費量がとても大きくなってしまうのです。(例えば1920x1080のイメージだと1枚につき8MB近くもメモリを消費してしまいます)


このコントロールの元であるWindowsのリストビューコントロールは万を超えるようなかなり多くのアイテムを追加してもスクロールして描画できると思います。
理想としてはこのリストビューコントロールのように、数多くのアイテムを追加してもスクロールやコントロールのリサイズ時で描画できることです。

自作コントロールという性質上描画はすべて自分だけで描画しなければなりません。
本当はリストビューやエディットボックスなどがどうやって描画処理を行っているのかを詳しい1つ1つの処理レベルで知ることができれば本望ですが、ネット上を検索してもこの手順については全くヒットしないのでどうしても行き詰ってしまっています。

自作コントロールについて知識があれば是非ともご教授お願い致します。



MillkeyStars

リンク

2020/7/27(Mon) 22:23:35|NO.91084

>>ですがあらかじめ広い領域に描画しておきそれをスクロールするという方式ではこの手間は無くなります。
この部分に関しては、HSP で言うと groll です。
WindowsAPI の gdi32 だと、SetWindowOrgEx 及び SetViewportOrgEx があります。

親ウィンドウのサイズと同期しコントロールの位置を変更する場合は、DeferWindowPos (user32.dll)があります。
この命令は、コントロール単体ではなく登録されたコントロールを一括で位置・サイズを設定する関数です。

このような方法は、基本的にググるしかないです。「やりたいこと C++」と検索すると出てきます。



X

リンク

2020/7/28(Tue) 00:32:20|NO.91085

抜粋で、リストビューの仮想リストビューのイメージが思われている考え方に近いかと思います。
メモリも考えると更に面倒ですがリストボックスの方だと32APIのSystemParametersInfoを使い
スムーズスクロールを切ることで動的ではありませんがストレスのない動作が見込めることもあります。
視点を変えるといった感じでしょうか。
自前実装は大変ではありますがmod_GUIOBJというモジュールを作られている方もいらっしゃいます。
32APIコントロールを完全に再現されているわけではありませんがとても参考になるかと思います。
https://dev.onionsoft.net/seed/info.ax?id=760



とあるプログラマ

リンク

2020/7/28(Tue) 22:51:52|NO.91093

>>MillkeyStarsさん
どれも自分の知らなかった関数でした…
自分なりには結構調べていたはずなのに、調べ方が悪いのかまだまだ見つかっていないものが多そうですね… (「独自コントロール C++」などで調べていましたが)

別サイトの名前が出てしまいますが、やろうとしていること的にはどちらかというとHSPTVよりもteratailのようなQ&Aサイトのほうが良いのでしょうかね…


>>Xさん
仮想リストビューなんてものがあるのですね。これも知りませんでした…
ひとまず調べてみましたが複雑そうで理解するには少し時間がかかってしまうと思うので、それに関しての返答は今は置いておこうかと思います。

GUIOBJも拝見させていただきました。
軽く内容を調べてみた感じ、こちらのリストボックスは可視範囲内のみをスクロール時毎に描画するといった感じでしたね。参考になります。



ONION software Copyright 1997-2023(c) All rights reserved.