[Delphi] Icon uit exe halen en aan menuitem koppelen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Orwell
  • Registratie: December 2009
  • Laatst online: 08-09 22:11
Om het kort te houden: ik ben voor een IDE een menu aan het maken. Gebruikers kunnen daar items aan toevoegen die zijn gekoppeld aan externe executables. Nu leek het me wel handig om een icoontje aan die items toe te voegen, puur ter herkenning:

CODE MIST STUKJES, MAAR DAT IS PUUR OM DE BOEL EEN BEETJE RELEVANT TE HOUDEN

Delphi:
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
if fToolList.Count > 0 then begin

    // Pass all menu items
    for I:=0 to pred(fToolList.Count) do begin
        Item:= TMenuItem.Create(fMenu);

        // If it doesn't have an icon already
        if not fToolList.Items[I].HasIcon then begin
            Icon:=TIcon.Create;
            try
                if FileExists(S) then begin

                    // Er moet een variabele meegegeven worden
                    LargeIcons := nil;
                    SmallIcons := nil;

                    // Lijst opbouwen die alle icons bevat
                    numicons:=ExtractIconEx(PChar(S),-1,LargeIcons^,SmallIcons^,0);

                    if numicons > 0 then begin

                        // Pluk de kleinste eruit
                        GetMem(SmallIcons,sizeof(HICON)*numicons);
                        ExtractIconEx(PChar(S),0,LargeIcons^,SmallIcons^,numicons);
                        Inc(SmallIcons,numicons-1);
                        Icon.Handle:=SmallIcons^;

                        // Check if we got hold of something
                        Icon.savetofile('C:\Users\Johan Mes\Desktop\icon' + inttostr(I) + '.ico');

                        // Add the icon to the image lists if it exists
                        if Icon.Handle <> 0 then begin

                            // Add it to every theme
                            fToolList.Items[I].IcoNumNewLook:=dmMain.MenuImages_NewLook.AddIcon(Icon);
                            fToolList.Items[I].IcoNumBlue:=dmMain.MenuImages_Blue.AddIcon(Icon);
                            fToolList.Items[I].IcoNumGnome:=dmMain.MenuImages_Gnome.AddIcon(Icon);
                            fToolList.Items[I].HasIcon:=True;

                            // Save random prestored icon to see what format it uses - laat in gedachte weg
                            dmMain.MenuImages_NewLook.GetIcon(1,Icon);
                            Icon.savetofile('C:\Users\Johan Mes\Desktop\testiconfromlib' + inttostr(1) + '.ico');

                            // Setting the image index to 'not -1' should do the trick
                            if devData.Theme=DEV_GNOME_THEME then
                                Item.ImageIndex:=fToolList.Items[I].IcoNumGnome
                            else if devData.Theme=DEV_BLUE_THEME then
                                Item.ImageIndex:=fToolList.Items[I].IcoNumBlue
                            else
                                Item.ImageIndex:=fToolList.Items[I].IcoNumNewLook;

MessageBox(application.Handle,PChar('Icon belonging to ' + S + ' exists. Added as index ' + inttostr(Item.ImageIndex) + '!'),PChar('bericht'),MB_OK);

                        end;
                    end;
                    FreeMem(SmallIcons,sizeof(HICON)*numicons); // gevaarlijk, maar van later zorg
                end;
            finally
                Icon.Free;
            end;
        end;
        fMenu.Add(Item);
    end;
end;


Een puik stukje Arrow Code zeg ik maar (er ontbreken een stuk of 3~4 indents uit dit knipsels).

Goed. Simpelgezegd voegt dit item voor elk bestaande toolitem een TMenuItem toe, stelt die in (weggelaten) en gaat daarna naar een icon zoeken. Kijkt dan hoeveel icons er in de exe zitten, dan het kleinste (16x16) icon opzoeken in de lijst van verzamelde icons, en die in een globale ImageList opslaan. Bij het opslaan wordt de index van het zojuist opgeslagen item ook opgeslagen in de ImageIndex van een menuitem.

Dit zou allemaal moeten werken, maar doet het om wat voor reden dan ook niet. Het menuitem toont simpelweg geen icon. Hier wat ik alvast heb kunnen constateren:
  • De items die al in de dmMain.MenuImages stonden zijn origineel opgeslagen als 16x16 24bpp.
  • De messagebox toont de goeie informatie. De icons worden netjes aan het eind zonder fouten toegevoegd.
  • Item.ImageIndex een waarde geven van de vooraf geladen icons levert wel een plaatje op.
  • Item.ImageIndex een waarde geven van een zojuist geladen icon levert geen plaatje op.
  • Beide soorten icons saven levert bij beide een 16x16 32bpp-plaatje op (de savetofile-calls).
  • De MessageBox verschijnt altijd als een icon gevonden wordt.
  • Uiteraard ben ik weer iets stoms vergeten. Dat is altijd zo.
Zou iemand mij van dit probleem willen verlossen? Bij voorbaat dank. :)

Acties:
  • 0 Henk 'm!

  • SilentStorm
  • Registratie: November 2000
  • Laatst online: 27-04 11:59

SilentStorm

z.o.z

Even geleden dat ik iets met delphi deed, maar was er niet zoiets dat je de grootte van je plaatje zelf in moet stellen en dat ie anders op 0x0 pixels staat? Controleren of je icoon een grootte heeft, is ook een betere controle dan 'm proberen op te slaan, als er niet al een andere functie voor is.

oh en iiiieew :P
'C:\Users\Johan Mes\Desktop\icon'
Maar dat doe je vast niet hardcoded in je echte programma :)

Localhost is where the heart is


Acties:
  • 0 Henk 'm!

  • Orwell
  • Registratie: December 2009
  • Laatst online: 08-09 22:11
Ik heb er een beetje mee lopen rommelen, maar het komt erop neer dat dat gewoon niet mag (hij gooit een EInvalidGraphicsOperation - Cannot change the size of an icon).

Weer wat geleerd, en toch bedankt voor de moeite.

Dit is wel weer een klassiek facepalm-veroorzakend voorbeeld van een fix :P



Het blijkt dat als ik het zojuist geladen icon aan een al bestaand (tijdens designtime toegevoegd) menuitem toevoeg er ook niets gebeurt. Echter, als ik het aan een top-level-item toevoeg werkt alles perfect, maar als de muis eroverheengaat (repaint o.i.d.d) verdwijnt het icon. Vreemd.

Right, als ik bij een OnClick van het zojuist gemaakte menuitem (Sender as TMenuItem).ImageIndex opvraag, geeft 'ie -1 terug. Dus tijdens het maken van het losse Menu zijn de indices nog goed, maar bij het koppelen aan de hoofdform zijn de indices ineens foetsie.

Preciezer:
  • Maak een losse rij van TMenuItems. ImageIndex staat nog goed.
  • Bind ze vast aan een bestaand menu. ImageIndex klopt nog steeds.
  • Als de items nu up front zonder repaints o.i.d. verschijnen staat het plaatje er. Muis eroverheen -> permanent foetsie.
  • Als ik op het item klik (en het plaatje zelf dankzij de mouseover/repaint(?) weg is) is de ImageIndex zoals te verwachten is -1. Geen plaatje dus. Tijdens die klik de Index weer goedzetten levert alleen plaatje op als dat plaatje tijdens designtime was ingevoegd.

[ Voor 76% gewijzigd door Orwell op 01-11-2011 14:58 ]


Acties:
  • 0 Henk 'm!

  • Armageddon_2k
  • Registratie: September 2002
  • Laatst online: 10-09 15:29

Armageddon_2k

Trotse eigenaar: Yamaha R6

Orwell schreef op maandag 31 oktober 2011 @ 21:52:

Het blijkt dat als ik het zojuist geladen icon aan een al bestaand (tijdens designtime toegevoegd) menuitem toevoeg er ook niets gebeurt. Echter, als ik het aan een top-level-item toevoeg werkt alles perfect, maar als de muis eroverheengaat (repaint o.i.d.d) verdwijnt het icon. Vreemd.
Was er niet altijd een icon en een mouseover icon? deze moet je beide instellen.

Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 14-09 19:30

alienfruit

the alien you never expected

Waarom sla je de icoon eerst op?

Acties:
  • 0 Henk 'm!

  • Orwell
  • Registratie: December 2009
  • Laatst online: 08-09 22:11
Puur voor het debuggen. Ik wilde kijken of de geladen icoontjes even groot waren als Width en Height van de ImageList. Dat was overigens inderdaad zo (ze zijn beide 16x16 / 32bpp).
Pagina: 1