Autor Beitrag
trm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: Fr 16.12.11 04:16 
Hallo,

ich möchte gern für ein neues Projekt eine Fläche erstellen, auf welcher ich farbige Objekte erstellen kann, die ich bei Bedarf

* in der Breite/Höhe verändern kann
* an eine andere Stelle auf der Fläche verschieben kann

Wenn ich auf die Fläche mit der Maus klicke, soll eine Art Rahmen gezogen werden. Alternativ reicht ein Klick aus, um den Rahmen zu erstellen. Die Größenänderung ist aber wichtig.


Das ganze wird kein Spiel, eher eine Officeanwendung. Daher benötige ich kein DirectX/OpenGL oder sonst etwas in dieser Richtung.


Ich nutze Delphi7 und möchte weitesgehend ohne fremde Komponenten auskommen.

Hat jemand schonmal sowas gemacht und kann mir Tipps geben?

_________________
In Erfurt gibt es eine Pension, in der es gemütlich ist, Google einfach nach Pension Fiege ;)
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Fr 16.12.11 09:28 
Eine Paintbox, ein paar Mausauswertungen und ein Array oder eine Liste mit Objekten/Records welche die Beschreibung (Position, Größe, Form, Farbe etc ...) der Elemente aufnehmen, in Paint der Paintbox wird hieraus dargestellt.

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS


Zuletzt bearbeitet von bummi am Sa 17.12.11 01:23, insgesamt 1-mal bearbeitet
ub60
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 762
Erhaltene Danke: 127



BeitragVerfasst: Fr 16.12.11 21:29 
Zumindest für das Verschieben hätte ich etwas: www.delphi-treff.de/...cl/tlist/einleitung/.
Die Größenänderung sollte sich da auch reinbasteln lassen.

ub60
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Fr 16.12.11 21:59 
Wenns ums verschieben geht kannst du mal das hier angucken:
www.delphi-forum.de/....php?p=653296#653296

Größenveränderung kann man da auch noch einbauen. (Achtung: in dem Code ist ein kleiner Fehler, da das Raster sich verschiebt, wenn man das Fenster verschiebt ;) )

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
rd3
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 17.12.11 00:37 
Hi,

ich hab hier die letzte OpenSource-Version von ImageEn auf meinem Server, mit der das relativ einfach gehen sollte:
yorako1.bplaced.net/...icomps/iesrc_312.zip
rd3
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 17.12.11 00:42 
in der unit ieEnview.pas und-ioutil.pas ist das sehr gut beschrieben... du kannst da ableiten und "lernen", um die units nicht zu "usen"
trm Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: Sa 17.12.11 01:23 
Danke für die Hilfen,

ub60 das sieht gut aus. Warum Pointer verwendet werden, weiss ich leider nicht, aber so in etwa würde ich das gern umsetzen.


Xion, ein Panel zu verschieben geht noch weitaus einfacher, dafür benötigt man keine 3 verschiedene Ereignisse :)


Edit @rd3, das schau ich mir mal an :)

Edit2: @rd3: Die beiden von Dir genannten units sind im zip-Archiv nicht drin.

_________________
In Erfurt gibt es eine Pension, in der es gemütlich ist, Google einfach nach Pension Fiege ;)
rd3
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 17.12.11 02:25 
das hab ich jetzt aus dem kopf gesagt... es sind ne ganze menge units... ich hab jetzt keinen compiler hier... es war nur aus erinnerung... imageenview... imageio... die heißen doch alle so ähnlich...
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Sa 17.12.11 11:52 
Ich habe mal einen Microrumpf für so etwas für Dich aufgesetzt, vielleicht willst Du es ausbauen.
Shift + MouseDown = neues Objekt
Strg + MouseMove = Grösse ändern
Alt + MoseMove = verschieben

hier könnte man dann noch Einbauen Typ ändern, Farbe ändern etc.
Einloggen, um Attachments anzusehen!
_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
trm Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: Sa 17.12.11 16:14 
Hallo nochmal,

ich hab das hier doch wieder auf gemacht, weil da noch Fragen von meiner Seite aus bestehen ;)


Im Anhang ist ein Test von dem, was es später werden soll.

Links im 2. Panel bitte mal drauf drücken, dann in der rechten Paintbox eine Linie ziehen.

Komischerweise stimmen die TOP-Maße nicht mit den Panels überein - und ich sehe nicht, wo der Fehler ist.
Beim Panel 4 und 5 geht es, ab Panel 6 stimmt gar nix mehr und 1-3 sind verkehrt.
Einloggen, um Attachments anzusehen!
_________________
In Erfurt gibt es eine Pension, in der es gemütlich ist, Google einfach nach Pension Fiege ;)
ub60
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 762
Erhaltene Danke: 127



BeitragVerfasst: Sa 17.12.11 17:12 
Die Bezeichnung der Panels ist gruselig :roll: (Panel45, Panel51, Panel43, Panel52, ...), das nur so nebenbei. Da macht eine Fehlersuche keinen Spaß.
Davon abgesehen kannst Du den y-Wert des Rechtecks sehr einfach bestimmen. Angenommen, Deine Panelhöhe ist 41, rechnest Du X (von der Maus) div 41 und dann das Ganze mal 41. Damit erhältst Du immer den oberen Rand der Panel. Addiere dann zum Beispiel noch 5, dass sich die einzelnen Belegungsrechtecke nicht berühren.

Zur Bemerkung mit den Pointern in dem Tutorial: Die sind dort nicht sehr sinnvoll, man sollte dies besser mit einer TObjectList machen. Da kann man dann auch ganz gut löschen.

ub60
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: So 18.12.11 00:27 
so geht es ...

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  Dummy_Integer: Integer;
  a, b : Integer;
  Dummy_Panel: TPanel;
begin

  Dummy_Bool_MouseDown := (ssLeft in Shift);

  if Dummy_Bool_MouseDown then
  begin
    if Y <= (Panel_OverView_Belegung_ZeitLeiste.Top + Panel_OverView_Belegung_ZeitLeiste.Height) then
      Y := Panel45.Top + 1;

    if Y > (Panel_OverView_Belegung_ZeitLeiste.Top + Panel_OverView_Belegung_ZeitLeiste.Height) then
    begin
      for Dummy_Integer := 0 to Panel29.ControlCount - 1 do
        if Panel29.Controls[Dummy_Integer] is TPanel then
        begin
          Dummy_Panel := TPanel(Panel29.Controls[Dummy_Integer]);
          a := Dummy_Panel.Top;
          b := Dummy_Panel.Top + Dummy_Panel.Height;

          if (Y >= a) and (Y <= b) then
          begin
            Dummy_Panel.Caption := IntToStr(Y) + ': ' + IntToStr(a) + #32 + IntToStr(b);
            Y := a + 1;
            Break;
          end;
        end;
    end;

    X_Start := X;
    Y_Start := Y;
  end;

end;

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS


Zuletzt bearbeitet von bummi am So 18.12.11 09:30, insgesamt 1-mal bearbeitet
trm Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: So 18.12.11 04:41 
user profile iconub60 hat folgendes geschrieben Zum zitierten Posting springen:
Die Bezeichnung der Panels ist gruselig :roll: (Panel45, Panel51, Panel43, Panel52, ...), das nur so nebenbei.


Danke ;) Nur so nebenbei.. es sind Testobjekte. In einem fertigen Programm werden diese Flächen dynamisch erstellt.


user profile iconbummi hat folgendes geschrieben Zum zitierten Posting springen:
so geht es ...


Danke user profile iconbummi, verstehen kann ich es leider dennoch nicht. Wenn eine Variable in einer Menge erwartet wird und diese Erwartung nicht erfüllt wird, springt Delphi dennoch auf den Zug auf (Y=100; a=300; und c=350;) :/

Schönen Sonntag an euch.

_________________
In Erfurt gibt es eine Pension, in der es gemütlich ist, Google einfach nach Pension Fiege ;)
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: So 18.12.11 09:41 
Ich verstehe nicht was Du meinst ... solange Du im Bereich der Panels bist passt es, außerhalb kommt derzeit noch Y, wenn es das ist, das ließe sich so umgehen
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  var
  Dummy_Integer: Integer;
  a, b,yy : Integer;
  Dummy_Panel: TPanel;
begin

  Dummy_Bool_MouseDown := (ssLeft in Shift);
  yy := -1;
  if Dummy_Bool_MouseDown then
  begin
    if Y <= (Panel_OverView_Belegung_ZeitLeiste.Top + Panel_OverView_Belegung_ZeitLeiste.Height) then
      Y := Panel45.Top + 1;

    if Y > (Panel_OverView_Belegung_ZeitLeiste.Top + Panel_OverView_Belegung_ZeitLeiste.Height) then
    begin
      for Dummy_Integer := 0 to Panel29.ControlCount - 1 do
        if Panel29.Controls[Dummy_Integer] is TPanel then
        begin
          Dummy_Panel := TPanel(Panel29.Controls[Dummy_Integer]);
          a := Dummy_Panel.Top;
          b := Dummy_Panel.Top + Dummy_Panel.Height;

          if (Y >= a) and (Y <= b) then
          begin
            Dummy_Panel.Caption := IntToStr(Y) + ': ' + IntToStr(a) + #32 + IntToStr(b);
            yy := a + 1;
            Break;
          end;
        end;
    end;

    X_Start := X;
    Y_Start := YY;
  end;

end;



und ein entsprechedes

if Y_Start = -1 then exit;

in den anderen Routinen.

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 18.12.11 11:46 
Ich hätte das jetzt nicht unbedingt mit Komponenten gemacht (sprich Panels). Das geht grundsätzlich schon auch, aber wenn es dann darum geht, Linien und Pfeile zu zeichnen ist's nicht ganz das richtige. Ausserdem performen die Dinger nicht sehr gut.

Das MicroPaint funktioniert zwar, ich finde es aber ziemlich gefährlich so zu beginnen. Denn das ganze ist architektonisch auf wackeligen Füssen und kaum erweiterbar - daraus wird irgendwann mal ein monolithisches Chaos, wenn man daran einige Wochen und Monate weiterentwickelt.

Ich hätte jetzt das ganze sauber nach "Schulbuch-OOP" gemacht und die verschiedenen Concerns getrennt. Irgend sowas wie:

- Modellklassen: OvalShape, RectangleShape, LineShape, ArrowShape. Keine GUI sondern reine Datenklassen mit ein paar Properties ohne Logik. Ein zentrales Updated-Event würde ich jedoch noch machen.

- Ansichtsmodellklassen: Diese wrappen jeweils ein Modell und bieten zusätzlich weitere GUI-spezifische Dinge wie "Griffe" zum Vergrössern und Verkleinern an den Ecken an. Verschiedene Shapes können ja verschiedene Griffe haben: Ein OvalShape hat vielleicht 4 Griffe (oben, unten, rechts, links), ein RectangleShape 8 (zusätzlich noch in den Ecken), eine Linie hat nur 2 Griffe (an den beiden Enden). Diese Klassen sind ebenfalls reine Datenklassen. D.h. für die Griffe habe ich z.B. ein Property, welches eine Liste von HandleShapes oder so ist. Es muss nicht zwingend pro Modellklasse eine Ansichtsklasse existieren.

- Ansichtsklassen: Diese rendern das Ansichtsmodell und benachrichtigen das Ansichtsmodell, wenn irgendwas geklickt wurde. Die Ansichtsklasse implementiert zudem Hittests, usw.. Die Ansichtsklassen sind zustandslos.

Schlussendlich braucht man vielleicht noch ein dünnes Framework, welches die zusammengehörenden Klassen miteinander in Verbindung bringt. Die Assoziationen könnte man über eine Konfiguration oder In-Code durch Attribute steuern. Man könnte da auch ein bisschen etwas hartcodieren.

Das ganze gibt am Tag 1 eine etwas längere Nacht. Danach hast du aber eine saubere Sache. Einige Vorteile:
- Die Ansichtsklassen enthalten keine Zustandsinfos - diese sind im Ansichtsmodell. Die Ansichtsklassen kann man daher jederzeit austauschen, theoretisch sogar zur Laufzeit (z.B. Wechsel zwischen OpenGL und Canvas).
- Das Ansichtsmodell enthält das allermeiste an Logik. Diese Logik ist aber klar vom Modell getrennt. Im Modell sind nur noch Daten. Diese können einfach persistiert werden.
- Erweiterbar. Kommt morgen das Requirement, dass ich Sachen gruppieren können muss, mache ich ein neues Modell, das aus einer Liste von Modellen besteht. Als Ansichtsmodell nehme ich vielleicht das fürs Rectangle als Basis und die Ansicht aggregiert entsprechend die Paint-Methoden, Hittests, der Ansichten.

PS: Das ist jetzt einfach mal so aus dem Brauch raus - natürlich müsste man sich das mal genauer anschauen, mal paar Diagramme zeichnen, ein Proof-Of-Concept machen.
trm Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: So 18.12.11 14:23 
Hallo,

ich weiß nicht, ob ihr, die hier antworten, verstanden habt, um was es ging :(
(Bei einigen meine ich, dass die sich den Quelltext vielleicht angeschaut haben aber nicht tief genug. Andere ignorieren meine Fragen.)

user profile iconbummi hat folgendes geschrieben Zum zitierten Posting springen:
Ich verstehe nicht was Du meinst ... solange Du im Bereich der Panels bist passt es [..]


Ich wollte eigentlich wissen, warum der Vergleich mittels
ausblenden Delphi-Quelltext
1:
if (Y >= a) and (Y <= b) then					

funktioiert, abder der Vergleich mittels
ausblenden Delphi-Quelltext
1:
if Y in [a..b] then					

nicht. Beides sollte logisch gesehen doch vollkommen in Ordnung sein.

Weiterhin fange ich ein "außerhalb der Panel" dann in den folgenden Programmierprozessen anders ab.


user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Ich hätte das jetzt nicht unbedingt mit Komponenten gemacht (sprich Panels).[..]

Danke für Deine Ausführungen, aber das benötige ich wirklich nicht. Auch später nicht. Und die Panels sind immer noch Testkomponenten, ob die später als Panels bestand haben werden, weiß ich noch nicht. Jedenfalls mache ich ja auf den Panels nichts weiter als einen Text auszugeben. Ansonsten dienen die im Moment als Positionsmarker.


Danke an euch. Das Thema ist erledigt, wenn jedoch jemand nur kurz zur Problematik mit dem Vergleich einen Tipp hat, schreibt den doch bitte noch hinzu :)

Schönen 4. Advent.

_________________
In Erfurt gibt es eine Pension, in der es gemütlich ist, Google einfach nach Pension Fiege ;)
ub60
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 762
Erhaltene Danke: 127



BeitragVerfasst: So 18.12.11 15:01 
Ich vermute mal, das Problem der ungleichen Behandlung liegt daran:
"Die Ordinalpositionen der Werte müssen zwischen 0 und 255 liegen." (Aus Delphi-Hilfe)
Deine y-Werte werden wohl >255 sein.

Abgesehen davon, so (siehe Source) geht es wirklich einfacher. Mit X_Alt lösche ich übrigens das alte Rechteck vor einer Zeichenoperation in MouseMove, dann flackert es nicht mehr so, da ich mir das Repaint erspare.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if Dummy_Bool_MouseDown then
  begin
    y:=(y div 41)*41+5;
    X_Start := X;
    Y_Start := Y;
    X_Alt:=X;
  end;

ub60
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: So 18.12.11 16:15 
Du hast ja dicht gemacht, aber bzgl. der Vergleiche

das hier wird gar nicht kompiliert

if Y in [500..600] then

ich denke es ist davon auszugehen dass die ordinale des in ausgewertet werden, da wo sie sich mit dem Gültigkeitsbereich überlappen kommen "richtige" Ergebnisse.

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
trm Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: So 18.12.11 22:30 
Danke. Das hatte ich vergessen.

_________________
In Erfurt gibt es eine Pension, in der es gemütlich ist, Google einfach nach Pension Fiege ;)