Autor Beitrag
galikor
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Do 19.02.09 18:18 
Hallo Community,

es gab 5 relevante Themen, da hab ich aber keine Lösung gefunden.
Falls ich etwas übersehen haben sollte, dann verzeiht mir bitte.

Habe folgendes Anliegen, ich erzeuge dynamisch ein Array of TImage
und dann werden diese Bilder auf meiner Tform1 zugeordnet und plaziert.
Dies passiert hier:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
     while not eof(f) do
        begin
          readln(f,str);
          pics[i]:=TImage.create(form1);
          pics[i].Parent:=form1;
          pics[i].Visible:=true;
          pics[i].Picture.LoadFromFile(str);
          pics[i].Stretch:=true;
          pics[i].Left:=a;
          pics[i].Top:=b;
          a:=a+110;
        if a > 700 then begin a:=10;b:=b+110;
        end;
     end;


Ich weiß das man mit dem Befehl ( ShellExecute(Application.Handle, 'open', PChar('Project1.exe'),NilNil, SW_NORMAL); ) eine Datei öffnen kann.

Mein Anliegen ist nun, dass wenn man dann auf einen der Bilder klickt, es sich das Original öffnet.
Mit pics[i].Onclick:=ShellExecute(Application.Handle, 'open', PChar(str),   NilNil, SW_NORMAL);
geht es allerdings nicht. 'str' ist der Pfad der Datei aus ner anderen Datei genommen.

Bin über jeden hinweis dankbar.

Moderiert von user profile iconmatze: Delphi-Tags hinzugefügt
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Do 19.02.09 19:05 
Hallo und :welcome: im Delphi-Forum, user profile icongalikor!

Du musst irgendwie die Dateinamen der Grafiken speichern. Das kannst du auf verschiedene Arten tun:

  • Speichere sie als PChar im Tag des TImage. Den PChar verwandelst du noch in ein Integer, um ihn in Tag speichern zu können: ImageX.Tag := Integer(PChar(Dateiname))
  • Definiere einen Record, in dem einerseits die Bildkomponente gespeichert ist, andererseits aber auch noch ein String für den Dateinamen enthalten ist. Natürlich musst du das Bildarray nun auf diesen Typ deklarieren.
  • Erstelle ein zweites Array of String für die Dateinamen. Gibt aber schnell Probleme, wenn du das eine änderst - dann werden die Dateinamen durcheinanderkommen.

Entscheide selber, welche der genannten Varianten für dich am günstigsten ist :idea:

Manche Programmierer mögen das Speichern größerer Daten in einem Tag nicht, und das auch begründet: Du musst die Strings auch irgendwie wieder freigeben. Ist zwar logisch, aber ich weiß gerade nicht, wie das gehen soll :?

Grüße,
Yogu
galikor Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Do 26.02.09 18:00 
Stimmt das mit dem Namen speichern war der Punkt. ;)

Habe erstmal rausgefunden, wie das mit dem TNotifyEvent für OnClick funktioniert.
Meinem createten Image weise ich dann ne Procedur zu:
ausblenden Delphi-Quelltext
1:
pics[i].OnClick := Click;					
Und dies ist die Procedure dann:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure tpics.Click(Sender: TObject);
var str,str_aktiv:string;i:integer;
begin
str:=TImage(Sender).Name; //das war der Knackpunkt, da hab ich lange für gesucht, dass man das so übergeben kann

str:= copy(str,1,pos('Dateiname',str)-1) + '.' + copy(str,pos('Dateiname',str)+9,length(str)) ; 
//das ist nur, damit ich den kompletten Dateinamem als Name habe, schreibe halt vorher an die Stelle vom '.' das Wort Dateiname (hoffe das ich nie ne datei habe, die dann so heißt, aber kann man ja noch ändern), und hier ersetzt er dann wieder das Wort durch einen '.'

ShellExecute(Application.Handle, 'open', PChar(str),   NilNil, SW_NORMAL)
end;

Falls jemand dazu noch Ideen hat, oder Verbesserungsvorschläge, die es noch einfacher machen, nur raus damit.
Oder Kritik ist auch erwünscht (aber macht mich nicht ganz runter, bin erstmal froh, dass es funktioniert :) )

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Do 26.02.09 20:09 
Hallo,

wenn es so funktioniert ist das ja schonmal gut. Allerdings ist das natürlich ziemlich umständlich gelöst und verbesserungsfähig. Also, gute Nachrichten: Du kannst wieder was lernen :)

Ich beschreib dir jetzt mal den ersten von mir genannten Punkt genauer, das kannst du ja mal ausprobieren.

Also, die Idee ist folgende: Jede Komponente hat eine Eigenschaft Tag mit dem Datentyp Integer - also eine Zahl. In dieser Zahl können wir aber auch speichern, wo denn der Dateiname zu finden ist. Das machen wir so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var Dateiname: PChar; Adresse: Integer;

// Wir wandeln den Dateinamen str in einen PChar um, da dieser
// besser mit Pointern zu bedienen ist. Ein PChar ist ein Zeiger
// auf das erste Zeichen der Zeichenkette.
Dateiname := PChar(str);

// Wir wandeln die Adresse auf das erste Zeichen in einen Integer um,
// um sie dann der Eigenschaft "Tag" der Komponente zuweisen zu können
Adresse := Integer(Dateiname);
pics[i].Tag := Adresse;

Das war's. Drei Anweisungen zum Speichern des Namens.

Jetzt noch das lesen, also alles wieder rückgängig

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var Adresse: Integer; Dateiname: PChar;

// Adresse aus Tag auslesen, vorher noch den Sender in eine
// TComponent casten, damit wir auf die Eigenschaft Tag zugreifen
// können
Adresse := TComponent(Sender).Tag;

// Adresse in ein PChar umwandeln, um auf die Zeichen zugreifen zu können
Dateiname := PChar(Adresse);

// - jetzt steht der Dateiname in der gleichnamigen Variable -

So einfach geht das :idea:

Bei Fragen einfach - fragen ;)

Grüße,
Yogu

Edit:

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Beim zweiten Quelltext fehlt aber noch ein klitzekleiner Cast würde ich sagen. ;-)

:oops:
Verpessert.


Zuletzt bearbeitet von Yogu am Do 26.02.09 20:41, insgesamt 1-mal bearbeitet
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 26.02.09 20:15 
Beim zweiten Quelltext fehlt aber noch ein klitzekleiner Cast würde ich sagen. ;-)
galikor Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Do 26.02.09 21:20 
Klingt interessant, ich probier das morgen gleich mal aus, heute keine Nerven mehr.
Hab eben noch gemerkt, dass wenn ich diese Bilder anzeigen lasse und dann Neue suche, weil es eine Art Bildersuche ist, dann kommt wieder son lustiger Fehler.

Fehlermeldung: Method 'Click' hides virtual method of base type 'TControl'

Denke es hängt damit zusammen, dass ich bei erneutem Drücken auf Suche, ja irgendwie die alten gefunden Bilder in dem Array of TImage wieder löschen muss. Das muss ich mir erstmal wieder näher anschauen.

Ich meld mich morgen mal, nach weiterem "Lernen". ^^
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 26.02.09 21:37 
Nenn deine Methode mal nicht ausgerechnet Click, dann kommt die Fehlermeldung auch nicht. Click gibts nämlich schon, damit kannst du einen Klick auf in diesem Fall das Formular simulieren, und durch deine neue Methode Click wird die alte versteckt.

Was meinst du warum die automatisch erstellten Methoden so schöne Namen haben wie Button1Click oder so und nicht nur alle Click heißen? Dann könnte die keiner auseinander halten, schon gar nicht der Compiler. ;-)

Deshalb: Nimm aussagekräftige Namen, auch wenn es mal ein paar Zeichen mehr zu tippen sind.
galikor Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Fr 27.02.09 01:17 
Da meine Kreativität zu wünschen läßt, heißt es jetzt ClickKlack.

Junge bin ich ein Voll*****.
Wenn ich meine pics[i]:=TImage.create(Form1); gemacht habe, hab ich Trottel doch total vergessen das "i" hochzuzählen. *Kopf->Tischplatte*

Wenn ich jetzt was neu suche und das alte lösche, spricht was gegen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
for i:=0 to overflow do
begin
pics[i].Destroy;
end;

Funktioniert jetzt soweit alles - wie es soll, aber ist Destroy so die elegante Wahl?

PS: Danke an Yogu und jaenicke, falls ich noch Probleme haben sollte, weiß ich ja wo ich sie bekomme.
Und bevor ich hier was frage, seit euch gewiss, dass ich schon vorher ne Stunde (oder mehr) im Netz/ DelphiHilfe gesucht habe. ;)

Moderiert von user profile iconmatze: Delphi-Tags hinzugefügt
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 27.02.09 01:24 
user profile icongalikor hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich jetzt was neu suche und das alte lösche, spricht was gegen:

ausblenden Delphi-Quelltext
1:
for i:=0 to overflow do					
Ist overflow die Anzahl oder der höchste Index? Wenn es die Anzahl ist, dann fehlt da ein -1.

user profile icongalikor hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
begin
pics[i].Destroy;
end;


Funktioniert jetzt soweit alles - wie es soll, aber ist Destroy so die elegante Wahl?
Nein, der Konstruktor Destroy sollte niemals direkt aufgerufen werden, es sollte immer Free benutzt werden. Das prüft z.B. vorher, dass das Objekt überhaupt noch existiert.