Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Application.Icon setzen (https://www.delphipraxis.net/195916-application-icon-setzen.html)

freimatz 6. Apr 2018 18:24

Application.Icon setzen
 
Hallo,
in meiner App erscheint zuerst ein SpashScreen. Das ist eine einfache TForm. Das Hauptformular wird erst später geladen. Ich möchte nun dass in der Taskleiste nun gleich ein Icon und der Titel erscheint.
Beim Titel klappt das mit Application.Titel recht gut, beim Icon gelingt es mir nicht.
Wie macht man das am Besten, woran kann es liegen?
Letzter Versuch war:
Delphi-Quellcode:
       
       Icon := TIcon.Create;
       try
         SplashForm.cxImageListMainIcon.GetIcon(0, Icon);
         Application.Icon.Assign(Icon);
       finally
         Icon.Free;
       end;
cxImageListMainIcon ist dabei einem Imagelist. Mit einem TImage gings auch nicht. Auch nicht mit SplashForm.Icon.
Für Ideen oder eine Lösung wäre ich dankbar.

günni0 6. Apr 2018 18:42

AW: Application.Icon setzen
 
Delphi-Quellcode:
Application.Icon := SplashForm.cxImageListMainIcon.GetIcon(0, Icon);

sollte eigentlich funktionieren.

freimatz 6. Apr 2018 18:52

AW: Application.Icon setzen
 
Danke. Leider Nein: [DCC Fehler] Fm_Splash.pas(70): E2010 Inkompatible Typen: 'TIcon' und 'procedure, untyped pointer or untyped parameter': GetIcon ist keine function.
(PS.: gegooglet habe ich auch schon lange.)

günni0 6. Apr 2018 18:53

AW: Application.Icon setzen
 
Mein Fehler. So natürlich:

Delphi-Quellcode:
IconX := SplashForm.cxImageListMainIcon.GetIcon(0, Icon);

Application.Icon := IconX;

freimatz 6. Apr 2018 21:33

AW: Application.Icon setzen
 
Sorry, dadurch wird GetIcon immer noch nicht zu einer function ;-)

KodeZwerg 6. Apr 2018 22:21

AW: Application.Icon setzen
 
So hole ich mir zur Laufzeit Icons aus der Resource:

Delphi-Quellcode:
{$R MYICONS.RES}

procedure TForm1.Button1Click(Sender: TObject);
var
  h : hIcon;
begin
  h := LoadIcon(hInstance, 'ICON_1');
  Application.Icon.Handle := h;
  InvalidateRect(Application.Handle, nil, true);
end;

günni0 6. Apr 2018 22:24

AW: Application.Icon setzen
 
Na dann jetzt aber nochmal richtig ...
Delphi-Quellcode:
SplashForm.cxImageListMainIcon.GetIcon(0, Icon);
Application.Icon := Icon;
oder direkt ohne Zwischenvariable

Delphi-Quellcode:
SplashForm.cxImageListMainIcon.GetIcon(0, Application.Icon);

freimatz 7. Apr 2018 08:53

AW: Application.Icon setzen
 
Funktioniert leider auch nicht - außer dass es später eine Schutzverletzung gibt (vermutlich weil es dann SplashForm und soit auch das Icon nicht mehr gibt.)

@KodeZwerg: Danke. Das sieht jetzt eher lowlevel aus. Versucht habe ich es so:
Delphi-Quellcode:
  h := LoadIcon(hInstance, 'MAINICON');
  Application.Icon.Handle := h;
  InvalidateRect(Application.Handle, nil, true);
Es funktionert aber auch nicht. Nach dem Debugger hat h einen Wert. Nach der Doku ("If the function succeeds, the return value is a handle to the newly loaded icon. If the function fails, the return value is NULL. To get extended error information, call GetLastError.") müsste das Laden ja dann geklappt haben weil h ist ja nicht NULL.
Application, Application.Icon.Handle und Application.Handle habe nach Debugger auch was drin.
Das Icon erscheint aber nicht bei mir.

Ich habe den Verdacht dass mir DevExpress da noch irgendwie reinspuckt.

Aufgrund von https://stackoverflow.com/questions/...plication-icon mein neuster letzter erfolgloser Versuch:
Delphi-Quellcode:
var
  hApp: HWND;
  hSmall : hIcon;
  hLarge : hIcon;
begin
  hApp := Application.Handle;

  hSmall := LoadImage(HInstance, 'MAINICON', IMAGE_ICON,16, 16, 0);
  hLarge := LoadImage(HInstance, 'MAINICON', IMAGE_ICON,256, 256, 0);

  SendMessage(hApp, WM_SETICON, ICON_SMALL, hSmall) ;
  SendMessage(hApp, WM_SETICON, ICON_BIG, hLarge) ;

  InvalidateRect(hApp, nil, true);
  UpdateWindow(hApp);
end;
Ich gebs mal vorläufig auf.

KodeZwerg 7. Apr 2018 09:25

AW: Application.Icon setzen
 
Delphi-Quellcode:
{$R MYICONS.RES}

procedure TForm1.Button1Click(Sender: TObject);
var
  h : hIcon; // wir brauchen das Handle, nicht das Image, deswegen HICON
begin
  h := LoadIcon(hInstance, 'ICON_1'); // in Resource-Datei MyIcons.res ist ein Eintrag Namens ICON_1, Handle dahin erzeugen
  Application.Icon.Handle := h; // Handle an das Programm übergeben
  InvalidateRect(Application.Handle, nil, true); // Programm update
end;
Also in MyIcons.res existiert ein Icon was den Namen "ICON_1" bekommen hat, dem System ist in der Regel die Größe egal da es von selbst runter/hoch skaliert. Ich hab keinen Check drinn da die Resource bei mir immer existiert. Ob es LowLevel ist kann ich nicht sagen, nur das es bei mir auf diese Weise klappt kann ich sagen.

Code:
SendMessage(hApp, WM_SETICON, ICON_BIG, h);
sollte das WinApi Äquivalent sein und genügen.
Ich vermute LoadImage() macht nicht das gleiche wie LoadIcon().

Code:
SendMessage(hApp, WM_SETICON, ICON_BIG, LoadIcon(hInstance, 'MAINICON'));
Probier's mal so.

günni0 7. Apr 2018 11:06

AW: Application.Icon setzen
 
Zitat:

Funktioniert leider auch nicht - außer dass es später eine Schutzverletzung gibt (vermutlich weil es dann SplashForm und soit auch das Icon nicht mehr gibt.)
Wenn das hier nicht funktioniert stimmt irgendwas in deinem Projekt aber nicht. Einfacher gehts nicht.

Delphi-Quellcode:
SplashForm.cxImageListMainIcon.GetIcon(0, Application.Icon);

Delphi.Narium 7. Apr 2018 11:17

AW: Application.Icon setzen
 
Ungetestet als Idee hingedaddelt:
Delphi-Quellcode:
Icon := TIcon.Create;
st  := TMemoryStream.Create;
try
  SplashForm.cxImageListMainIcon.GetIcon(0, Icon);
  Icon.SaveToStream(st);
  Application.Icon.LoadFromStream(st);
finally
  st.Free;
  Icon.Free;
end;

Alallart 7. Apr 2018 19:58

AW: Application.Icon setzen
 
@freimatz

Kann es sein, das du das etwas kompliziert machst? Warum kopierst du soviel herum? Wenn du ein Icon hast, dann übergibt Application die Adresse und gut ist es. Das habe ich auf die Schnelle gemacht. Ich habe auf dem Formular eine TImage abgelegt, ein Icon rein geladen, und es übergeben. Funktioniert.

Delphi-Quellcode:
program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);

  Application.Title := 'Dies und Das';
  //Application.Icon.Handle := Form1.Image1.Picture.Icon.Handle; //Funktioniert
  //Application.Icon := Form1.Image1.Picture.Icon; //Funktioniert
  Application.Icon := Form1.Icon; //Funktioniert

  Application.Run;
  Application.Icon.Assign(Icon);
end.
Dann habe ich noch zwei andere versuche unternommen. Funktionieren auch.

Hier ein anderes Beispiel, mal schnell ein Splashscreen eingebaut (Form2)

Delphi-Quellcode:
program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm2, Form2);

  Application.Title := 'Dies und Das';
  Application.Icon := Form2.Icon;
  Form2.ShowModal; // Nach 2 Sekunden schließt sich Form2 selbst.
  Application.Icon := Form1.Icon;

  Application.Run;
end.
Delphi-Quellcode:
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm2 = class(TForm)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Timer1Timer(Sender: TObject);
begin
  if Timer1.Tag = 2000 then
    Close;

  Timer1.Tag := Timer1.Tag + Timer1.Interval;
end;

end.
Nach 2 Sekunden wechselt das Icon erneut.

freimatz 9. Apr 2018 11:30

AW: Application.Icon setzen
 
Zitat:

Zitat von Alallart (Beitrag 1398437)
Kann es sein, das du das etwas kompliziert machst? Warum kopierst du soviel herum? Wenn du ein Icon hast, dann übergibt Application die Adresse und gut ist es.

Nein es ist nicht gut, zumindest bei mir. Ich glaube ja gerne, dass das bei dir funktioniert. Auch nehme ich an, dass es auch bei mir funktioniert, wenn ich ein neues Projekt mit deinem Code mache.
Leider habe ich noch mehr als 500.000 andere Zeilen Code die halt auch im Projekt drin sein müssen sonst werden manche Leute unzufrieden ;-)

günni0 9. Apr 2018 11:36

AW: Application.Icon setzen
 
Wieso beeinflussen die anderen 500.000 Zeilen denn Application.Icon?

freimatz 9. Apr 2018 11:52

AW: Application.Icon setzen
 
Tja, wenn ich das wüsste ... :?
Wie geschrieben habe ich DevExpress im Verdacht. Die hooken sich ins System rein. Allerdings hatte ich noch keine Zeit das näher zu untersuchen.

himitsu 9. Apr 2018 11:57

AW: Application.Icon setzen
 
In aktuellen Delphis ist standardmäßig nicht das Application.Icon in der Taskleiste zu sehn, sondern Application.MainForm.Icon, denn Delphi-Referenz durchsuchenMainFormOnTaskbar.

Du könntest beim Programmstart MainFormOnTaskbar umstellen, aber anschließend sollte es besser immer auf True stehen, denn in Bezug auf Aero Peek und das Kontextmenü des Taskbuttons hat es einen großen Einfluss.

freimatz 9. Apr 2018 12:36

AW: Application.Icon setzen
 
Ah danke. Das hatte ich noch nicht "auf dem Schirm". Werde das untersuchen.

Alallart 9. Apr 2018 17:12

AW: Application.Icon setzen
 
Zitat:

Zitat von freimatz (Beitrag 1398525)
Leider habe ich noch mehr als 500.000 andere Zeilen Code die halt auch im Projekt drin sein müssen sonst werden manche Leute unzufrieden ;-)

500.000 Zeilen? Respekt. Nur baut man Splash Screens nicht eher beim Start des Programms ein?

himitsu 9. Apr 2018 17:39

AW: Application.Icon setzen
 
Zitat:

Zitat von Alallart (Beitrag 1398574)
Nur baut man Splash Screens nicht eher beim Start des Programms ein?

Umd den Benutzer maximal zu nerven und zum Kauf zu nötigen, sollte man den auch mittendrin alle 5 Minuten aufspringen lassen. :stupid:

günni0 9. Apr 2018 17:40

AW: Application.Icon setzen
 
Ich handhabe es so, dass der Splash-Screen für die Dauer angezeigt wird die es benötigt alle Formulare zu erzeugen + 500 Millisekunden.
Natürlich ist er ausschaltbar.

freimatz 9. Apr 2018 18:55

AW: Application.Icon setzen
 
Hallo,
also erstmal - ich habe eine Lösung:
Delphi-Quellcode:
procedure DoIcon();
var
  h : hIcon;
begin
  h := LoadIcon(hInstance, 'MAINICON');
  Application.Icon.Handle := h;
  InvalidateRect(Application.Handle, nil, true);
end;

begin
  Application.Title := 'BalBlaBla';
  DoIcon();
  Application.Initialize;
  SplashFormCreate('',false);
  Application.ProcessMessages();
  ...
An sich fehlte gegenüber vorigen Versuchen nur ein "Application.ProcessMessages();"

Zitat:

Zitat von Alallart (Beitrag 1398574)
500.000 Zeilen? Respekt. Nur baut man Splash Screens nicht eher beim Start des Programms ein?

Das Einbauen und die zeitliche Abfolge ist nicht unbedingt abhängig. Etliche units haben einen initialization Abschnitt und vor allem bei Fremdkomponenten habe ich da nicht den Überblick.

Zwischen Programmstart und bis das Hauptfenster fertig ist können schon mal 10 Sekunden vergehen.
Application.MainFormOnTaskbar ist von Beginn an False; ob das später noch mal auf True geht habe ich nicht untersucht. Das Hauptfenster setzt später auch nochmal das Icon (je nach Konfiguration unterschiedliche)

Mein Splash ist nicht ausschaltbar; andererseits ist er auch nicht fsStayOnTop so dass man noch was anders tun kann.

Danke für alle Beiträge. :thumb:

günni0 9. Apr 2018 19:05

AW: Application.Icon setzen
 
Solange der Splash-Screen nur für die Dauer des Programmstarts angezeigt wird, wenn auch wirklich was geladen/initialisiert wird, ist doch alles OK. Nag-Screen kann man das nicht nennen.
Sonst wäre der Photoshop-Splash-Screen ja auch ein Nag-Screen.

KodeZwerg 9. Apr 2018 19:07

AW: Application.Icon setzen
 
So sollts auch gehen um Code kurz zu halten.
Delphi-Quellcode:
procedure DoIcon();
begin
  Application.Icon.Handle := LoadIcon(hInstance, 'MAINICON');
  InvalidateRect(Application.Handle, nil, true);
end;
Sonst müsstest Du irgendwo das "h" wieder freigeben, oder?

günni0 9. Apr 2018 19:12

AW: Application.Icon setzen
 
Programmierung Lehrjahr 1: Zwischenvariablen, wenn möglich, immer vermeiden. Besonders bei Blöcken <= 10 Zeilen.

KodeZwerg 9. Apr 2018 19:29

AW: Application.Icon setzen
 
In der Entstehung nutz ich erstmal viele Variablen um halt Feedback auswerten zu können, die kommen alle schön brav in eine {$IFNDEF DEPLOY} rein um automatisch bei {$DEFINE DEPLOY} ignoriert/übersprungen zu werden.

Als Beispiel dient mir obiger Source:
Delphi-Quellcode:
{.$DEFINE DEPLOY} // Wenn der Punkt entfernt wird, ist's aktiv

procedure DoIcon();
{$IFNDEF DEPLOY}
var
  h : hIcon;
{$ENDIF DEPLOY}
begin
{$IFNDEF DEPLOY}
  h := LoadIcon(hInstance, 'MAINICON');
  Application.Icon.Handle := h;
{$ELSE DEPLOY}
  Application.Icon.Handle := LoadIcon(hInstance, 'MAINICON');
{$ENDIF DEPLOY}
  InvalidateRect(Application.Handle, nil, true);
end;
Habs grad nur so hingekritzelt, korrektheit könnt falsch sein.

günni0 9. Apr 2018 19:42

AW: Application.Icon setzen
 
Sieht schwer noch nahezu doppeltem und unheimlich schwer wartbarem Code aus wenn es dann mal tausende Zeilen sind die man so schreibt.

freimatz 9. Apr 2018 19:45

AW: Application.Icon setzen
 
Zitat:

Zitat von günni0 (Beitrag 1398584)
Programmierung Lehrjahr 1: Zwischenvariablen, wenn möglich, immer vermeiden. Besonders bei Blöcken <= 10 Zeilen.

:shock: :roll: :mrgreen:
Programmierung Lehre -> diese Schule meiden.

Ok - schöner Code ist meiner auch nicht. Aber da mache ich erst wieder rum wenn das Produkt raus ist und das ist Donnerstag.

@KodeZwerg: was soll das bringen? Macht es doch nur extrem unleserlich. Der Compiler optimiert das doch eh weg.

günni0 9. Apr 2018 19:49

AW: Application.Icon setzen
 
Zitat:

Programmierung Lehre -> diese Schule meiden.
Wird zwar jetzt ein Streitthema, aber das sehe ich anders. Wo man Zwischenvariablen meiden KANN, sollte man das tun. Für drei Zeilen Code braucht meine keine Zwischenvariable. Auch wenns zwei, drei Zeilen mehr sind nicht. Das bläht Code unnötig auf. Außerdem wird Code nicht zwangsläufig lesbarer, nur weil man 10 Zwischenvariablen nutzt.
Wenn man einen Wert in einem Code-Block x-mal benötigt ist das was anderes.

KodeZwerg 9. Apr 2018 20:08

AW: Application.Icon setzen
 
Das war halt nur ein Beispiel, jeder so wie er es mag.
Da ich mich an so eine Art der Programmierung gewöhnt habe, also das innerhalb bestimmter {$IF} Blöcke nur bestimmte Sachen beim Compilieren berücksichtigt werden, kann ich mich halt in den {$IFNDEF} Blöcken relativ frei austoben und in den {$IFDEF} oder {$ELSE} Blöcken halt Achten alles richtig zu machen.
Da es bei mir viele eigene Funktionen/Prozeduren gibt die ich halt in zwei Varianten brauche, einmal Testing einmal Release ohne jede Funktion/Prozedur doppelt haben zu müssen, nutze ich diese Möglichkeit.
Punkt entfernen = nur Release Code wird compiliert und das betrifft bei mir halt viele Aufrufe.

himitsu 9. Apr 2018 21:23

AW: Application.Icon setzen
 
Beim Debuggen kann man sich die Zwischenergebnisse ansehen. (OK, im Assembler, teilschritte in den überwachten Ausdrücke, Variable auswerten, ...)

Zitat:

Zitat von günni0 (Beitrag 1398576)
Ich handhabe es so, dass der Splash-Screen für die Dauer angezeigt wird die es benötigt alle Formulare zu erzeugen

Warum überhaupt immer alles erstellen, anstatt es nur/erst dann, wenn es auch verwendet wird?

Vieles wird selten/fast nie verwendet, oder schaust du dir den Options- oder gar den Info-Dialog deines Delphi mehrmals täglich an?

günni0 9. Apr 2018 21:54

AW: Application.Icon setzen
 
Zitat:

Warum überhaupt immer alles erstellen, anstatt es nur/erst dann, wenn es auch verwendet wird?
Ist zwar am Thema vorbei, aber damals so begonnen, nie geändert, heute keine Lust mehr dazu. Es funktioniert ohne Fehler und schnell, was will man mehr.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz