私は自分の三角形が必要でしたので、私は三角形のフォームTShapeを継承し、ペイント方法をオーバーライドしました。すべて正常に動作しますが、マウスでこのシェイプを移動する必要があります。 onMouseDownイベントを処理するすべてのシェイプのメソッドを設定しました。移動作業もうまくいきます。しかし、2つの図形が重なり合っている場合(図形は実際には一部の透明領域で長方形になっています)、上部の図形の透明領域が別の図形の上にある場合、上部の図形は下の図形の代わりに移動します。デルファイの仕組みは正しいです。しかし、それはユーザーにとって直感的ではありません。それをどうすれば実現できますか?イベントキューからイベントを削除しないで、下にあるシェイプに送信する可能性はありますか?はいの場合は単純でしょうか?Delphi - オーバーラップするTShapesを移動する
6
A
答えて
0
シェイプの移動を開始する前に、マウスクリックが三角形領域内にあるかどうかをテストします。それはいくつかの数学が必要ですが、以下のように、あなたはまた、一時的な領域を形成することにより、WinAPIのPtInRegion機能を悪用できます。私のコメントあたり
function PtInPolygon(const Pt: TPoint; const Points: array of TPoint): Boolean;
var
Region: HRGN;
begin
Region := CreatePolygonRgn(Points[0], Length(Points), WINDING);
try
Result := PtInRegion(Region, Pt.X, Pt.Y);
finally
DeleteObject(Region);
end;
end;
procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
StartMove: Boolean;
begin
StartMove := PtInPolygon(Point(X, Y), [Point(100, 0), Point(200, 200),
Point(0, 200)]);
...
9
A「簡単なサンプルの再設計」は、以下。
unit Unit4;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
const
NUM_TRIANGLES = 10;
COLORS: array[0..12] of integer = (clRed, clGreen, clBlue, clYellow, clFuchsia,
clLime, clGray, clSilver, clBlack, clMaroon, clNavy, clSkyBlue, clMoneyGreen);
type
TTriangle = record
X, Y: integer; // bottom-left corner
Base, Height: integer;
Color: TColor;
end;
TTriangles = array[0..NUM_TRIANGLES - 1] of TTriangle;
TForm4 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
FTriangles: TTriangles;
FDragOffset: TPoint;
FTriangleActive: boolean;
function GetTriangleAt(AX, AY: Integer): Integer;
function IsMouseDown: boolean;
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
uses Math;
{$R *.dfm}
procedure TForm4.FormCreate(Sender: TObject);
var
i: Integer;
begin
FTriangleActive := false;
Randomize;
for i := 0 to NUM_TRIANGLES - 1 do
with FTriangles[i] do
begin
base := 40 + Random(80);
height := 40 + Random(40);
X := Random(ClientWidth - base);
Y := height + Random(ClientHeight - height);
Color := RandomFrom(COLORS);
end;
end;
procedure TForm4.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
TriangleIndex: integer;
TempTriangle: TTriangle;
i: Integer;
begin
TriangleIndex := GetTriangleAt(X, Y);
if TriangleIndex <> -1 then
begin
FDragOffset.X := X - FTriangles[TriangleIndex].X;
FDragOffset.Y := Y - FTriangles[TriangleIndex].Y;
TempTriangle := FTriangles[TriangleIndex];
for i := TriangleIndex to NUM_TRIANGLES - 2 do
FTriangles[i] := FTriangles[i + 1];
FTriangles[NUM_TRIANGLES - 1] := TempTriangle;
Invalidate;
end;
FTriangleActive := TriangleIndex <> -1;
end;
function TForm4.IsMouseDown: boolean;
begin
result := GetKeyState(VK_LBUTTON) and $8000 <> 0;
end;
procedure TForm4.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if IsMouseDown and FTriangleActive then
begin
FTriangles[high(FTriangles)].X := X - FDragOffset.X;
FTriangles[high(FTriangles)].Y := Y - FDragOffset.Y;
Invalidate;
end;
end;
procedure TForm4.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
FTriangleActive := false;
end;
procedure TForm4.FormPaint(Sender: TObject);
var
i: Integer;
Vertices: array of TPoint;
begin
SetLength(Vertices, 3);
for i := 0 to NUM_TRIANGLES - 1 do
with FTriangles[i] do
begin
Canvas.Brush.Color := Color;
Vertices[0] := Point(X, Y);
Vertices[1] := Point(X + Base, Y);
Vertices[2] := Point(X + Base div 2, Y - Height);
Canvas.Polygon(Vertices);
end;
end;
function TForm4.GetTriangleAt(AX, AY: Integer): Integer;
var
i: Integer;
begin
result := -1;
for i := NUM_TRIANGLES - 1 downto 0 do
with FTriangles[i] do
if InRange(AY, Y - Height, Y) and
InRange(AX, round(X + (Base/2) * (Y - AY)/Height),
round(X + Base - (Base/2) * (Y - AY)/Height)) then
Exit(i);
end;
end.
は、フォームのDoubleBuffered
true
に設定することを忘れないでください。
コンパイルしたサンプルのデモ:http://privat.rejbrand.se/MovingTriangles.exe
+0
あなたはこの回答を投稿してからずっと長いことを知っていますが、おそらく 'AX 'の最小/最大計算のための' InRange'を説明できますか?私の心を吹き飛ばして、私は長い間、数学や幾何学を学んだことはないと思っていました。もっと見ると、私は理解し始めたと思う。 'Y-AY'(小さな三角形の高さ)を' Height'で割って、指定された 'AY 'で潜在的な小さな三角形' Base'の半分を縮小しますか?しかし、それを両側からカットすることは、「X」がその範囲内にあることをどのようにして知っていますか?私はいくつかの描画をした、それは真実で、今私はそれを見るが、 – Raith
関連する問題
- 1. Delphiのデバッグでプログラムカウンタを移動する
- 2. Delphi - コントロールを移動して更新する方法
- 3. 幅の遷移 - divsのオーバーラップ
- 4. オーバーラップするUITableviewCell
- 5. Delphiフォームの編集時にコントロールの移動を傍受する方法
- 6. マウスが上に移動するにつれてqtウィジェットを大きく描画する(ウィジェットのオーバーラップ)
- 7. エージェントが移動ノードを移動する
- 8. Delphi 2010で動作するようにDelphi 7アプリケーションを更新する
- 9. Excel Sqlクエリ。オーバーラップする場合はサイドの代わりに下に移動する
- 10. 画像ビューを移動するパスを移動する
- 11. Graphvizがエッジラベルをオーバーラップする
- 12. MonoTouch:UITabBarがUITableViewをオーバーラップする
- 13. リストビューの行をオーバーラップする
- 14. オーバーラップを表示するツールバー
- 15. ピンチで移動して移動する
- 16. Delphiインターフェイスは推移的ですか?
- 17. Delphi - デザインモードで実行時に同様のコントロールを移動
- 18. Delphi:タブ付きの文字列グリッド間を移動
- 19. AppBarLayoutをオーバーラップするようにする
- 20. AppBarレイアウトは、遷移後にフローティングアクションボタンをオーバーラップします
- 21. プレースホルダdivを動的にオーバーラップ可能にする
- 22. ビルドサーバーをDelphi XEからDelphi XE2に移行
- 23. 1,2,3,3,1移動する
- 24. オーバーラップするdivとスペーサー
- 25. RelativeViewでオーバーラップするImageView
- 26. Infragisticsグリッド:行がオーバーラップする
- 27. UITableViewCellでオーバーラップするUILabel
- 28. ツールバーとオーバーラップするビュー
- 29. Jgraphxでオーバーラップするエッジ
- 30. Androidのフローティングウィンドウ:移動するには移動する
は、フォーム上のコントロール(でもグラフィックコントロール)を動かすことでアニメーションを描画することは悪いです。私があなただったら、カスタムデータ構造でシーンを保存して、フォームを完全に手動で描画します。その後、あなたの持ち帰りを制限するものはありません。あなたが望む任意のマウスインターフェースを実装することができます。 –