描画ツールでの縮小を実装するには?

解決


mon  2006-04-07 01:25:26  No: 20877

はじめまして、monと申します。
 現在、簡素なワードのような描画(印刷)ツールを作っています。
 LineやBoxのクラスを作ってリストで保存し、キャンバスを持ったコントロールクラスに随時描画しています。
 縮小、拡大を実装したいのですが、フォントのサイズなどは四捨五入するなりしても縮小した際に縮小する前の画像と相対的な位置がどうしてもズレてしまいます。
  何かいい方法はないでしょうか?
  それから、質問を重ねてしまい申し訳ないのですが、Canvas.SetClipがなぜか未定義になってしまいます。リージョンを作り、Setwindowrgnで設定してもClipRectの値が変わりません。ClipRectを設定する方法を教えていただけないでしょうか?

Delphi6 Personal  window XP(SP2)で開発しています。


Mr.XRAY  URL  2006-04-07 08:05:23  No: 20878

>画像と相対的な位置がどうしてもズレてしまいます。
もしかしたら,私が勘違いしているかもしれませんが,画面上での拡大縮小は
注意が必要です.極端な例を考えてみます.

画面上では整数値しか扱えませんから,例えば5を縮小して1/2にすると3とし
ます.これを元に戻すために2倍すると6になってしまいます.全て切り捨て
で処理しても
      5 -->  2 -->  4
となってしまいます.他の画像や文字の位置にズレが生じる原因となります.

>Canvas.SetClipがなぜか未定義になってしまいます。
私のDelphi6にはSetClipというのが見当たらないのですが...
(つまり,未定義ですね)
コード補完([Ctrl]+[Space])で表示されるのでしょうか.


デル太  2006-04-07 19:03:28  No: 20879

Mr.XRAYさん、いつもお世話になっています。

私もDelphi6ヘルプを見てみました。
SetClipはなくて、SetClipRectというメソッドがありますね。
ClipRectもあって、次の例がありました。
時間がなくて確認できずに申し訳ないですが、手がかりが含まれている感じがするので紹介いたします。
がんばってくださいね。

-----
Canvas ClipRect 例

この例では,領域を作成し,その領域を Image コンポーネントのキャンバスのクリッピング範囲として選択します。次に,キャンバスのブラシの色を赤に設定し,ClipRect を塗りつぶし領域として使って FillRect を呼び出します。最後に,nil を使って SelectClipRect を呼び出すことで ClipRect を元の値に再設定し,領域を削除します。

procedure Form1.Button1Click(Sender: TObject);
var

    MyRgn: HRGN ;

begin

    MyRgn := CreateRectRgn(100,100,200,200);
    SelectClipRgn(Image1.Canvas.Handle,MyRgn);
    Image1.Canvas.Brush.Color := clRed;
    Image1.Canvas.FillRect(Image1.Canvas.ClipRect);
    Image1.Invalidate;
    SelectClipRgn(Image1.Canvas.Handle,nil);
    DeleteObject(MyRgn);

end;


mon  2006-04-08 18:02:28  No: 20880

返事が遅くなってしまい申し訳ありません。
デル太さん、Mr.XRayさん変事ありがとうございます。
はい、Mr.XRayさんのおっしゃるとおりのことがまず一つ問題で、
もう一つは線などは割りと細かい縮小が聞きますが、フォントは1ポイントでも縮小率が高いので、相対的に位置がずれてしまうのです。
デル太さん、すみません、setcliprectでした。
ヘルプにはあるのですが、parsonalでは実装されてないのでしょうか?
SelectClipRgnというものがあるのですね。
試して見るとうまく行きました。本当にありがとうございます。

SetwindowRgnではHWNDなのでcanvasなどのHDCのハンドルを設定できない(エラーは出ません)ということですね。

縮小についてはやはり頭を悩ませています。クラスで値を保持して描画時に縮小率を使って計算すれば、戻した時の問題はない気がするのですけれど、文字(フォントサイズ)の縮小の仕方とその他の図形の縮小の仕方の違いを失くすにはどうすればよいのでしょうか?
MetaFileCanvasとStrechDrawを使って実装すると画面全体をいちいち再描画しないと行けないのでちらつきがとんでもないことになってしまいます。


デル太  2006-04-09 04:43:36  No: 20881

文面からそれっぽい情報をお知らせしただけなのですが、少しは役立ったみたいですね。よかったです。

今回も、文面から似た情報を提示するだけですが「フォントが縮小する」という情報を少し前に書籍で読んだのを思い出し探してみました。

□Delphiヴィジュアルプログラミング秘密のテクニック150
  086:コンポーネントのサイズを自動的に変更したい

の中に次の記述がありました。
-----
ScaleByメソッドを使うと、フォームのサイズに合わせて、すべてのコンポーネントのサイズを一度に変更することができます。
-----

特筆すべきは、フォントサイズなどもスケールに合わせて変更される・・とあります。
このメソッドが使えそうな気がするのですが・・ヘルプなどで調べてみてください。

もう出ないといけないため、細かい確認までできなくてすいません。


Mr.XRAY  URL  2006-04-09 09:30:13  No: 20882

開発しているのはDraw系のプログラムだと思います.
Draw系の場合,図形やフォントの情報をベクトル情報で持たないと
拡大縮小に耐えることはできません.

くどいようですが,フォントサイズ(pt)が3の時,フォントサイズは整
数のみですから(Font.Heightを使用すればある程度は耐えることが可能
ですが,限度があります)

(1) 5分の1の大きさにすると1
(2) 元に戻そうとして5倍すると5になってしまう

ベクトル情報をもつものの一つがメタファイルです.
(他のDraw系のアプリでは独自のものを使用している場合があります)
(これは他のDraw系のアプリを使ったことがあればわかると思います)

したがって,この場合はScaleByを使用しても意味ありません.
(TControlのソースコードを追ってみて下さい.MulDivの演算です)

つまり,TMetaFile等を使用することになるでしょう.
つらつきが生じてしまうということですが,これはどうしょうもありません.
つらつきが少しでも発生しない工夫をすることになります.
この手法は,この掲示板やネット上で検索して下さい.
どのようなコーディングかによってもかわってくる可能性があります.

それから,SetClipの件ですが,コード補完機能を使用すれば,
「未定義」はある程度未然に防ぐことが可能です.
(usesに必要な場合があるので,一概には言えませんが)

なお,リージョンについては,いろいろなサイトに情報があると
思いますが,以下も参考になれば幸いです.

http://homepage2.nifty.com/Mr_XRAY/Halbow/VCL01.html
http://www.asahi-net.or.jp/%7EHA3T-NKMR/DGS/index.htm


Mr.XRAY  URL  2006-04-09 17:06:41  No: 20883

>(TControlのソースコードを追ってみて下さい.MulDivの演算です)
失礼.Personal版でしたね.Personal版にはソースコードはついていません
でした.


mon  2006-04-10 21:17:44  No: 20884

デル太さん、Mr.XRAYさん、ご返答ありがとうございます。
自宅にネット環境がないため返事遅れてしまい申し訳ありませんでした。

SCaleByは試していたのですが、やはり上手くいきませんでした。

やはりMetaFileでの実装が一番現実的でしょうか。
でもベクトル情報という言葉は大きなヒントになりそうです。
部分的な再描画だけではなかなかちらつきを防ぐのは難しそうですが、
色々と工夫してやってみたいと思います。

リージョンについては実は上のサイトを見て勉強しました(笑
XRayさんのサイトはAPI関連のこと等、かなり参考にさせていただいています。

色々と調べるためのヒントや実装に必要なことについてありがたい情報を頂きました。後は自分の勉強次第と思いますのでこれで解決とさせていただきます。
まだまとまった知識やコードがないのでフィードバックが出来ず申し訳ありません。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加