Try&Error 付箋アプリを作ってみる stickies (5)

TMemoのオーナードローの話の続きです。

チビ目標
・ちらつき低減
・奇偶行背景色色変え
・強調表示(これは欲張りすぎ。でも、ゲットしたサンプルはこのためのサンプルなんです。これが。)

ちらつきからやっつけます。

Developing with Graphics - Free Pascal wiki:[2012/05/04]
GDI Graphics in Delphi - 7/9:Four Ways To Kill Flicker [2012/05/04]
constructor TMemoEx.Create(AOwner: TComponent);
begin
Self.DoubleBuffered := True;
Self.ControlStyle := Self.ControlStyle + [csOpaque];
inherited Create(AOwner);
end;

あんまり効かない。
procedure TMemoEx.WMErasbkgnd(var Message: TWMEraseBkgnd);
begin
Message.Result := 1;
end;

激効き。

4つめの、Off-Screen Bitmaps を試すまもなく、とりあえずヨシです。そうか、もともとWM_PAINTの中を全部書いてる(というサンプルを使ってる)から、背景消去(?)を完全に殺しても影響ないんだろね。

あれ? ひょっとしてこのサンプルって何にもできてないのかも。テスト用にコメントアウトしまくっても画面表示が全然変わらないの。
どういうこと?

原因わかりました。WM_PAINTの処理関数の末尾にinheritedが書いてあることでした。それで全部上書きされてた。じゃぁってんで、1行目に書いたら、選択したり色々した時に変になる。でも、inheritedしないのも怖すぎ。色々やってるだろうし。どうしよか。

How to create a TMemo with alternating colours to paint the lines:[2012/05/04]

ここによると、inherited書いてない。なしでもありかも。なしでやってみてもカーソルはちゃんと書いてくれてる。前回の画像みたいな、一番下の行だけ色違いというのもないし、枠が若干黒っぽいのもなくなった。
なしでしばらくやってみます。

そうすると別の問題が出てきました。
カーソルが少しだけ文字に刺さってます。TextOutする時のX座標を x:=2; と決め打ちしているのが原因です。じゃぁどういう数字が妥当かというと何だろ。5でもなし、6とか7とかっぽいけど、もっとバチッと決まらんもんかと思うわけで。

プログラミングの覚え書き: TMemo:[2012/05/04]
ここに、「Memoで左右のマージンを設定する」サンプルがあります。

Memo1.Perform(EM_SETMARGINS, EC_LEFTMARGIN or EC_RIGHTMARGIN, MAKELONG(10, 20));


その逆も是非ともあって欲しいということで、久しぶりに本棚から出してみます。
Amazon.co.jp: Delphi Win32 Graphics APIリファレンス (Ascii books): ジョン アイレス, マイク トビン, ラリー ディエル, ケネス ハリソン, オヴァイス レサ, デヴィッド ボウデン, フィル ドーカス, ロッド マス, John Ayres, Rod Mathes, Mike Tobin, Larry Diehl, Kenneth Harrison, Ovais Reza, David Bowden, Phil Dorcas, 光田 秀: 本:[2012/05/04]

載ってなかったのでGoogleで、EM_GETMARGINSで検索してみた。

EM_GETMARGINS:[2012/05/04]
Delphi Tips - メモコンポーネントとメッセージ:[2012/05/04]

あ。別のばっちりっぽいサンプルが出てきました。
HighlightedMemo.pas - tool commonly used mathematical calculat - Source Codes Reader - HackChina.com :[2012/05/04]

そのままじゃコンパイル通らないので、エラーのでる箇所を直して今まで使ってた改造TMemoと差し替えてみました。

その2つのサイトをもう一度貼っておきます。

SwissDelphiCenter.ch:[2012/05/05]
HackChina.com:[2012/05/05]

以降、呼ぶ必要があれば、SwissとChinaと呼ぶことにします。

Swiss

China


文字列を選択状態にした時の挙動が改善します。というか解決します。と言いつつ、初っ端の画面表示が難有りなんですけど、この2つのユニットのいいところを合体させてうまく行きそうな気がしてきました。

でも、今回の記事の冒頭でやったちらつき防止の滅WMErasbkgndがないにもかかわらず全然ちらつかないのは何故。constructorを見てみると

ControlStyle:=ControlStyle - [csOpaque];


引いてる。4つの冴えたやり方のページは足してたのに。確かに、この行をコメントアウトすると一気にちらつきが増します。引くのが正解か? もうよくわからんです。まぁいいか。

あと、そもそもEM_GETMARGINSで検索に引っかかっただけあって、カーソルが文字に刺さることもなくとてもいいかんじです。

それに、WM_PAINTハンドラ内のinherited問題も

Brush.Style := bsClear;
inherited;
Brush.Style := bsSolid;


放置するわけでなく、描画が意味なしになるようなでもinheritedはするという正しいかどうかは別として精神的に安心する方法をとっています。採用で。

***

えーと。なぜTMemoにオーナードローをする話になったんでしたっけ?

読みなおしてみると、TSynEditの日本語排斥運動に我慢ができなくなって、TMemoしかなさそうかってなって、行間調整できないなぁってなって、メイリオ使えばそうでもないなってなって、オーナードローいらんなってなってないのが不思議。
でも、TSynEditの編集機能を諦める仕返しに、TMemoをもっと良い感じにしたい復讐心がそうさせてるようにも読めます。

多分それでいいんだと思います。それに、2つもほぼ答えの書いてあるソースコードまで見つけてもう少しやってみたくなってますのが全てか。

***

やっぱり、ブラウザ上に直接書くよりもApsalyで書くと圧倒的に書きやすいからどんどん書けます。無駄口も増えてます。快適。
この程度の快適さを是非実現したいところです。

Refresh、Update、Invalidateメソッドの違い: .NET Tips: C#, VB.NET:[2012/05/04]

***

やろうとしているのは、ChinaをベースにSwissを混ぜ込んで、よりしっくりくるように頑張ることなんですけど、Chinaの特徴として「指定した行をハイライト表示し続ける」ようになっています。
残念ながらこのことそのものにはあまり意義を感じません。どういうときに使うのかもよくわかりません。でも、特定の1行の背景を塗りつぶす処理は、1行ごとに背景色を変えたいときの参考にできそうです。
ただ、ほぼソースをいじってない状態で、特定行をハイライト表示している時に、選択範囲にその行が含まれると、ハイライト表示が消えてしまいます。
まぁそれ以前に、起動直後に背景色自前描画が働いてないという問題も解決してないんですけど。

China-起動直後

China-キーを押すなどして再描画された状態(5行目がハイライト表示対象)

China-ハイライト行を含めて選択したところ


3番目の状態から、再描画が何らかの動作でかかると改めてハイライト表示されます。ほんのちょっとしたズレのようです。こういうの直すの一番しんどい可能性高いです。

今は、ソースを混ぜながら気に入らないメソッド名とか変えつつ何が書いてあるかを把握しているところです。だらだらしてるのでもう終わってないとおかしいぐらい時間使ってますが、そこはそれ。仕事じゃないので気楽なもんです。

さぁってんで、メインディッシュのWM_PAINTハンドラをちょっと真面目に見てみます。

あら。ハイライト表示してない時の描画は、TMemo標準の描画ルーチンそのままじゃないの。今までハイライト表示なんてほとんどしてなかったので、ちらつくとか云々なんてほとんどChinaの特徴じゃないやん。もうなんて言うか、こういうあれれ感が楽しめます。最初に見とけよとも言います。

あーあやっぱり。せっかくちらつかないなぁって思ってたのに、ハイライト表示の行を増やすと=自前で描画する範囲を大きくするとちらつきが悪化しました。
でもなぁ自分でもっといい方法を思いつくわけもなく。China+Swissにすがるしかないのでこのまま行きます。

いくらでも問題出てきた。ハイライト表示部分(自前描画部分)が結局カーソルが文字に刺さってる。それにChinaとSwissの評価も間違ってたかも。Swissの方が奥まで突っ込んでるみたい。と言うことは...選択した時の描画ができない。ソース見てみても、選択されてるかどうか判断してる感じがしない。

整理してみると

Chinaがうまく入ってたように見えたのは、そもそもTMemoに全て描画させた後に、特定の行だけハイライトさせるために改めて塗りつぶしてたからでした。最初のテストの時は、ハイライト行を指定していなかったから、TMemoが書いていたのが全てで、自前では何も書いてない状態。背景色だけ黄色にしてみたので、それだけは選択しようが何しようがうまくいってますが、全部自前で書いた時にどうなるかはまだわかりません。

Swissの方は、一切合切自前で描画してるので、選択した時に描画がおかしくなるのも含めて、今から立ち向かわなければならない問題を見せてくれてるんですけど、やりたいのはこっち側でした。

もう、ウロウロしすぎ。楽し。
関連記事
スポンサーサイト