|
これまで要素データ関連について考えてきましたが、画面でのテスト表示などかなり混み入ってきて拡大表示等も行いたくなってきましたので、この辺りで画面操作関連について、考えてみようと思います。
まずは少しまとめてみます。
| 単位 | X | Y |
画面サイズ | ドット | ScrX | ScrY |
画面中央点 | ドット | CenX | CenY |
mm→ドット
座標変換係数 | − | mm_dot | mm_dot |
画面左下点 | mm | WndX1 | WndY1 |
画面右上点 | mm | WndX2 | WndY2 |
用紙領域(※) | mm | CData.zp.x | CData.zp.y |
(※用紙サイズが横置きの場合はX>Y、縦置きの場合はX<Yとなります)
これらの変数と値は整合性を持っていないといけません。画面操作はこれらの変数の値を操作することで実現できますが、
// 用紙mm座標→画面ドット座標
procedure Z2D(var ix,iy:integer;x,y:double);
begin
ix := Trunc( (x - WndX1)*mm_dot) ;
iy := Trunc(-(y - WndY2)*mm_dot) ;
end; |
と行っているように、特に重要なのは、WndX1,WndY2,mm_dot の各値となりますが、上記変数値は、反映させるべきものはちゃんと計算させる、さもないと他のどこに影響するか分からない→バグを発生させてしまう?という事を念頭に置く必要があるでしょう。例えば、WndX2,WndY1は不要だろうから算出しない、という事をすると、クリッピング処理で不具合が生じて画面表示がおかしくなるかもしれません。
用紙領域 CData.zp.x、CData.zp.yの値は、用紙サイズを変更する場合にのみ値変更を行いますので、通常の画面操作では値を変更してはいけません。
画面サイズの値は、画面(Form)をリサイズした時や、新しい画面を表示させてその中に表示したい(※但し、変数内容は1つしか保持できませんので複数画面を使いたい場合には別途、バックアップ用の変数を用意する等を行う必要があります)、という場合に操作します。そこから画面中央点・変換係数・画面左下点・画面右上点を計算します。
画面移動表示処理は、mm→ドット座標変換係数 mm_dot の値はそのままで、画面左下点・画面右上点の値を変更する事で可能になります。この際は勿論、WndX1の増減量とWndX2の増減量は同じでなければなりません。WndY1・WndY2も同様です。
画面拡大表示処理は、mm→ドット座標変換係数 mm_dot の値を大きくします。そして画面左下点・画面右上点を計算します。画面縮小表示処理は、mm→ドット座標変換係数 mm_dot の値を逆に小さくします。そして画面左下点・画面右上点を計算します。
まず、基準表示画面を決めます。この状態を倍率100%とします。
本システムでは、用紙領域が画面にちょうど収まる状態を基準表示画面としていますが、例えば、mm_dot値が「1」の状態を基準表示画面としても構いませんし、画面に定規を当てたら同じ状態になるという画面を基準表示画面としても構いません。その場合は、例えば15インチ4:3のディスプレイだとすると、横長さは 約305mmになりますが、解像度が 1024×768の場合、mm_dot値は、ドット値÷mm値ですから、1024÷305=3.357…となります。つまりディスプレイの大きさと解像度による設定をしておかないといけません。
↓ 用紙サイズを「B6」にして[描画]
↓ [定規表示]をクリック
シンボル(カラフルな□と三角の図)の横幅を定規で測ると
そのシンボルの大きさ=20mmになります
// [定規表示]
procedure TForm1.Button14Click(Sender: TObject);
var
xdot : integer ;
xmm,xx,yy : double ;
begin
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
ZInit; // 関連する各変数の初期化
xdot := Screen.Width ; // モニタの横幅ドット数
xmm := 478.0; // 20.5 ワイドディスプレイでの横幅目分量です
mm_dot := xdot/xmm ;
// 画面中央を基準として拡大縮小します
xx := (WndX1+WndX2)/2.0 ;
yy := (WndY1+WndY2)/2.0 ;
WndX1 := xx - ScrX/mm_dot/2.0 ;
WndX2 := xx + ScrX/mm_dot/2.0 ;
WndY1 := yy - ScrY/mm_dot/2.0 ;
WndY2 := yy + ScrY/mm_dot/2.0 ;
DisplayAll ;
end; |
上記の xmm値を使用モニタに合わせて指定すればOKです。マルチモニタ時、サブモニタの方に表示する場合には、それに合わせたコーディングを行う必要があります。
次に、2倍拡大表示、1/2倍縮小表示を付けてみます。
// [2倍拡大表示]
procedure TForm1.Button15Click(Sender: TObject);
var
xx,yy : double ;
begin
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
CenX := ScrX div 2; // 画面中央
CenY := ScrY div 2;
mm_dot := 2.0 * mm_dot ;
// 画面中央を基準として拡大縮小します
xx := (WndX1+WndX2)/2.0 ;
yy := (WndY1+WndY2)/2.0 ;
WndX1 := xx - ScrX/mm_dot/2.0 ;
WndX2 := xx + ScrX/mm_dot/2.0 ;
WndY1 := yy - ScrY/mm_dot/2.0 ;
WndY2 := yy + ScrY/mm_dot/2.0 ;
DisplayAll ;
end;
// [1/2倍縮小表示]
procedure TForm1.Button16Click(Sender: TObject);
var
xx,yy : double ;
begin
・・・(同上)
mm_dot := 0.5 * mm_dot ;
・・・(同上)
end; |
↓ [2倍拡大] ↑[1/2倍縮小]
↓ [2倍拡大] ↑[1/2倍縮小]
実行すると、ある程度の拡大表示限度、縮小表示限度、が必要になるということがすぐに分かると思います。
次に画面移動です。
拡大表示を行うと、少し横に移動してみたい、という事がよくあります。ここでは取り合えず、画面の1/4分ずつ上下左右に画面移動表示を行うようにしてみます。移動表示の場合は、mm_dot値はそのままで、画面左下点・画面右上点の値を変更するようにします。[C]ボタンをクリックすると中央に戻します。
// [↑移動表示]
procedure TForm1.Button17Click(Sender: TObject);
var
l : double ;
begin
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
CenX := ScrX div 2; // 画面中央
CenY := ScrY div 2;
l := Abs(WndY2-WndY1)/4.0 ;
WndY1 := WndY1 + l ;
WndY2 := WndY2 + l ;
DisplayAll ;
end;
// [←移動表示]
procedure TForm1.Button18Click(Sender: TObject);
var
l : double ;
begin
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
CenX := ScrX div 2; // 画面中央
CenY := ScrY div 2;
l := Abs(WndX2-WndX1)/4.0 ;
WndX1 := WndX1 - l ;
WndX2 := WndX2 - l ;
DisplayAll ;
end;
// [→移動表示]
procedure TForm1.Button19Click(Sender: TObject);
var
l : double ;
begin
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
CenX := ScrX div 2; // 画面中央
CenY := ScrY div 2;
l := Abs(WndX2-WndX1)/4.0 ;
WndX1 := WndX1 + l ;
WndX2 := WndX2 + l ;
DisplayAll ;
end;
// [↓移動表示]
procedure TForm1.Button20Click(Sender: TObject);
var
l : double ;
begin
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
CenX := ScrX div 2; // 画面中央
CenY := ScrY div 2;
l := Abs(WndY2-WndY1)/4.0 ;
WndY1 := WndY1 - l ;
WndY2 := WndY2 - l ;
DisplayAll ;
end;
// [C(中央)移動表示]
procedure TForm1.Button21Click(Sender: TObject);
var
m,xx,yy : double ;
begin
m := mm_dot ;
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
ZInit; // 関連する各変数の初期化
mm_dot := m ;
xx := (WndX1+WndX2)/2.0 ;
yy := (WndY1+WndY2)/2.0 ;
WndX1 := xx - ScrX/mm_dot/2.0 ;
WndX2 := xx + ScrX/mm_dot/2.0 ;
WndY1 := yy - ScrY/mm_dot/2.0 ;
WndY2 := yy + ScrY/mm_dot/2.0 ;
DisplayAll ;
end; |
ScrX,ScrY,CenX,CenYの値をいちいち指定していますが、これは現在、画面リサイズした場合にこれら値を変更していないので(※現在、リサイズ用のイベントハンドラは作成していません)各所で指定するようにしていますが、画面リサイズ時の処理を追加すれば、ここまで指定する必要はありません。
拡大縮小移動の各ボタンをキーボード操作で行いたい場合は、OnKeyDownイベントにて記述しますが、上記のようにボタン等があると、フォームそのものでキーを受け付ける必要性が出てきます。その場合は、Form1 の KeyPreview プロパティを「True」にして、Form1 のOnKeyDownイベントにて記述します。しかし、Tab、BackTab、矢印キーなどの移動用キーは,キーボードイベントを発生させないので KeyPreview の影響を受けず、矢印キーを押しても Form1 のOnKeyDownイベントは実行されず、ボタン間のフォーカス移動となってしまいます。
おそらくは、TLabelやTSpeedButtonのようなフォーカスを持たないコンポーネントだけで画面構成すれば、矢印キーでのフォーカス移動というものも無くなるため、矢印キーを押しての画面移動処理が可能になると思われます。
仮に可能な場合には、
// キー操作
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key = VK_HOME) then begin
// 基準描画
Button9Click(Sender);
Key := 0 ;
end
else if (Key = VK_PRIOR) then begin
// PageUp:2倍拡大表示
Button15Click(Sender);
Key := 0 ;
end
else if (Key = VK_NEXT) then begin
// PageDown:1/2倍縮小表示
Button16Click(Sender);
Key := 0 ;
end
else if (Key = VK_UP) then begin
// ↑
Button17Click(Sender);
Key := 0 ;
end
else if (Key = VK_LEFT) then begin
// ←
Button18Click(Sender);
Key := 0 ;
end
else if (Key = VK_RIGHT) then begin
// →
Button19Click(Sender);
Key := 0 ;
end
else if (Key = VK_DOWN) then begin
// ↓
Button20Click(Sender);
Key := 0 ;
end
else if (Key = VK_END) then begin
// C
Button21Click(Sender);
Key := 0 ;
end;
end; |
のようになるでしょう。
取り合えず動作を見るために、Edit1 を配置し、その OnKeyDownイベントを記述するようにしてみます。この Edit1 にフォーカスを置いた状態でのみ動作できます。
なお、Button14 を少し変更しておきます。
// [定規倍率表示]
procedure TForm1.Button14Click(Sender: TObject);
var
xdot : integer ;
xmm,xx,yy : double ;
begin
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
CenX := ScrX div 2; // 画面中央
CenY := ScrY div 2;
xdot := Screen.Width ; // モニタの横幅ドット数
xmm := 478.0; // 20.5 ワイドディスプレイでの横幅目分量です
mm_dot := xdot/xmm ;
// 画面中央を基準として拡大縮小します
xx := (WndX1+WndX2)/2.0 ;
yy := (WndY1+WndY2)/2.0 ;
WndX1 := xx - ScrX/mm_dot/2.0 ;
WndX2 := xx + ScrX/mm_dot/2.0 ;
WndY1 := yy - ScrY/mm_dot/2.0 ;
WndY2 := yy + ScrY/mm_dot/2.0 ;
DisplayAll ;
end; |
ついでに、基準画面に対する倍率表示も行うようにしてみます。
// 基準表示に対する倍率表示
procedure TForm1.Button22Click(Sender: TObject);
var
n,xx,yy : double ;
begin
n := SDbl(Edit2.Text);
if (n < 0.000001) then n := 0.000001 ;
if (n > 100000.0) then n := 100000.0 ;
xx := (WndX1+WndX2)/2.0 ;
yy := (WndY1+WndY2)/2.0 ;
ScrX := PaintBox1.Width;
ScrY := PaintBox1.Height;
ZInit ;
mm_dot := n * mm_dot ;
// 画面中央を基準として拡大縮小します
WndX1 := xx - ScrX/mm_dot/2.0 ;
WndX2 := xx + ScrX/mm_dot/2.0 ;
WndY1 := yy - ScrY/mm_dot/2.0 ;
WndY2 := yy + ScrY/mm_dot/2.0 ;
DisplayAll ;
end;
procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
begin
if (Key = #13) then begin
Button22Click(Sender);
Key := #0 ;
end;
end; |
Edit2 にて倍率入力を行うようにします。Edit2 で数値入力後に[Enter]キーを押したら倍率表示を行うようにしています。その際、OnKeyDowmイベントで記述するとビープ音がうるさいので、OnKeyPressイベントにて処理を行うようにしています。
それでは、ここまでのテストプログラムです。実行ファイル、gdiplus.dll、gdipフォルダは入っていません。ソースのみです。
|
|
CAD装置(1)
CAD装置(2)
メディア
AutoCADの
DIESELマクロ
CSV
DXF
PCES
IGES
STEP
数学とCAD
CAD作ろ!
CADを考える
▲PREV
▼NEXT
M7
Jw_cad
|