Hallo,
offensichtlich hast du ja alle Figuren LBehälter. Im OnPaint-Ereignis des Fensters gehst du dann ja sicher diese Liste durch, um die Figuren zu zeichnen.
Wenn du die Maus über das Fenster bewegst, wird - wie du auch sicher weist - immer ein OnMouseMove-Ereignis ausgelöst. Dabei wird die aktuelle X- und Y-Koordinale ter Maus übergeben. Hier musst du herausfinden, innerhalb welcher Figuren (in LBehälter) sich diese Koordinate befindet.
Wenn du einfache Rechtecke hast, geht das mit der Funktion PtInRect. Bei komplizierteren Formen musst du halt die Geometrie bemühen . Am saubersten verpasst du deinem Figur-Objekt eine Methode, die für den Objekttyp und die Instanz eben prüft, ob ein gegebener Punkt in der Figur liegt, also zB.
function TViereck.isPointInFigure(P:TPoint):Boolean;
var
R:TRect;
begin
R := Rect(X,Y,X+Breite,Y+Hoehe); // das musst du natürlich so
// setzen, wie du die Position
// und Größe von TViereck
// definiert hast
Result := PtInRect(P, R);
end;
Für einen Kreis mit Mittelpunkt (X|Y) und Radius R könnte die Methode dann so aussehen:
function TKreis.isPointInFigure(P:TPoint):Boolean;
begin
Result := ((X-P.X)^2 + (Y-P.Y)^2)
Im OnMouse-Move-Ereignishandler gehst du dann einfach die LBehälter-Liste durch und prüft jede dort abgelegte Figur. Ist der Rückgabewert Wahr, dann hast du die Figur identifiziert. Wenn du "von hinten nach vorne" suchst, findest du die zuletzt hinzugefügte, also "obere" Figur zuerst:
P := Point(X,Y);
for i := LBehälter.Count-1 downto 0 do
if TViereck(LBehälter[i]).isPointInFigure(P) then
begin
// gefunden! mach was damit!
Break; // nicht mehr weitersuchen; wir sind fertig.
end;
So, du willst die selektierte Figur "markieren". Dazu würde ich die Nummer der Figur irgendwie sichern und in der Paint-Methode, wo alle Figuren gezeichnet werden, abfragen, ob die zu zeichnende Figur die "markierte" ist und sie entsprechend anders zeichnen.
Ich schlage mal vor (es gibt 1001 andere Möglichkeiten!), den Index der selektierten Figur in LBehälter in einer Integer-Variable des Formulars zu speichern. Nennen wir sie "Selected".
Im Mouse-Move-Handler setzt du Selected := i, wenn du die Figur gefunden hast. Wurde keine gefunden, kannst du Selected auf -1 setzen. Um nicht immer alles neu zeichnen zu müssen, wenn sich die Selektion nicht ändert, solltest du die vorige Selektion zwischenspeichern und prüfen. Alles in allem könnte das so aussehen:
oldSelected := Selected;
Selected := -1;
P := Point(X,Y);
for i := LBehälter.Count-1 downto 0 do
if TViereck(LBehälter[i]).isPointInFigure(P) then
begin
Selected := i;
Break;
end;
if oldSelected Selected then Repaint;
Im OnMouseDown-Handler kannst du dann ebenfalls anhand des Wertes von Selected das entsprechende Objekt aus LBehälter löschen und den ganzen Ramsch neu zeichnen:
if Selected \>= 0 then // nur, wenn auch wirklich was selektiert ist
begin
LBehälter.Delete(Selected);
Selected := -1;
Repaint;
end;
Damit solltest du klarkommen...
VG
Jochen
PS: Man könnte im Formular eine "SelectFigureAt"-Methode schreiben, die genau das macht, was ich oben im MouseMove-Handler geschrieben habe. Diese Methode könnte man dann im MouseMove-Handler aufrufen und außerdem im ButtonDown-Handler nach dem Löschen, um sofort die nächste Figur unter dem mauszeiger auszuwählen.
PPS: Die ganze Sache eignet sich schön für eine Virtualisierung. Man kann eine abstrakte "TFigur"-Klasse definieren, mit virtuellen Methoden fürs Erstellen, Zeichnen und für die Prüfung, ob eine Koordinate in der Figur ist. Diese Methoden kann man dann in abgeleiteten Klassen wie TViereck, TKreis, TDreieck usw. überschreiben. Woimmer in Formular dann auf ein LBehälter-Objekt zugegriffen wird, fasst man es als TFigur-Instanz auf, womit dann automatisch dir korrekte virtuelle, überschriebene Methode für das betreffende Objekt verwendet wird.