He necesitado forma propia de triángulo, heredé la clase de triángulo de TShape y anulé el método de pintura. Todo funciona bien, pero necesito mover estas formas con el mouse. Establecí el método para cada manejo de formas en el evento MoverDown. El trabajo en movimiento también está bien. Pero si dos formas se superponen (las formas son de hecho rectángulos con algunas áreas transparentes), que el área transparente de la forma superior está sobre otra, entonces la forma superior se mueve en lugar de la forma siguiente. Es correcto, así es como funciona Delphi. Pero no es intuitivo para el usuario. ¿Cómo puedo lograr eso? ¿Existe la posibilidad de no eliminar el evento de la cola del evento y enviarlo a las formas subyacentes, si es así, sería simple?Delphi - superposición de TShapes en movimiento
Respuesta
Compruebe si el clic del mouse está dentro del área del triángulo antes de iniciar el movimiento de la forma. Esto requiere un poco de matemáticas, pero también se puede hacer mal uso de la función API de Windows PtInRegion mediante la creación de una región temporal, de la siguiente manera:
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)]);
...
Un 'simple rediseño de la muestra' por mi comentario a continuación.
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.
No se olvide de establecer de DoubleBuffered
a true
la forma.
Compilado de demostración de muestra: http://privat.rejbrand.se/MovingTriangles.exe
Sé que ha pasado mucho tiempo desde que publicó esta respuesta, pero ¿tal vez podría explicar su 'InRange' para el cálculo 'min/max' de' AX'? eso me hace pensar, no he hecho matemáticas o geometría en un pensamiento de mucho tiempo. Después de mirar más, creo que comencé a entender. ¿Se reduce la mitad del triángulo pequeño potencial 'Base' con 'AY' dado al dividir 'Y-AY' (altura del triángulo pequeño) por 'Altura'? ¿Pero cómo sabes que cortar eso desde dos lados significará que 'X' está en ese rango? Hice un poco de dibujo y es verdad y ahora lo veo, pero no está tan claro cuando se hace programáticamente – Raith
- 1. Delphi - DirectX - OSD/Superposición de pantalla
- 2. Superposición de máscara en UIScrollView
- 3. Imágenes de superposición en CSS
- 4. detección de movimiento VLCj
- 5. Delphi: detecta el inicio y el final del movimiento de ventana
- 6. ¿Constructor de movimiento explícito?
- 7. CCMoveTo: velocidad de movimiento
- 8. ¿Cómo detectar la superposición de elementos (superposición) usando JavaScript?
- 9. Superposición de efecto "ocupado"
- 10. Haciendo superposición de JButtons
- 11. patrón de superposición coincide
- 12. problema de superposición jqGrid
- 13. Ventana de deshabilitación de WPF en movimiento
- 14. Eventos de movimiento de mouse en NCurses
- 15. iOS: Precisión de movimiento en 3D Space
- 16. Suave movimiento de anotación en OS 4
- 17. Animación de movimiento Cocos2d en una ruta
- 18. superficie de video SDL en movimiento
- 19. colecciones de NHibernate y objetos en movimiento
- 20. Configuración de Hanoi en un movimiento determinado
- 21. Superposición de diagramas de imshow en matplotlib
- 22. Fundido de entrada y movimiento
- 23. Cálculo de una movimiento máximo
- 24. Movimiento de 2D a 3D
- 25. "Fundamentos de Delphi" en Delphi 2009
- 26. explícitamente incumplido movimiento constructor
- 27. Multijugador suave movimiento
- 28. Superposición de radar meteorológico en MapKit
- 29. desactivar superposición de carreteras en google maps
- 30. Dibujar texto en superposición de círculo
Dibujo animaciones moviendo los controles (incluso los controles gráficos) en un formulario es malo. Si yo fuera tú, almacenaría la escena en una estructura de datos personalizada, y luego dibujaría el formulario completamente de forma manual. Entonces no hay restricciones que lo detengan: puede implementar cualquier interfaz de mouse que desee. –