Einzelnen Beitrag anzeigen

scp

Registriert seit: 31. Okt 2003
1.120 Beiträge
 
Delphi 7 Personal
 
#4

Re: Icon ersetzen funktioniert nicht

  Alt 16. Jul 2004, 16:42
Es ist noch nicht ganz fertig, aber funktionieren tuts schon:
So, hier die fertige Version:

Delphi-Quellcode:
// You can add unit Math to uses instead of using this function
function Log2(X: Extended): Extended;
asm
        FLD1
        FLD X
        FYL2X
        FWAIT
end;

type
  PIconHeader = ^TIconHeader;
  TIconHeader = packed record
    idReserved: Word; // Reserved (must be 0)
    idType: Word; // Resource Type (1 for icons)
    idCount: Word; // How many images?
  end;

function UpdateApplicationIconGroup(icofile: PChar; exefile: PChar; resID:PcHar; LangID:DWORD): Boolean;
type
  PIconResInfoArray = ^TIconResInfoArray;
  TIconResInfoArray = packed record
    idReserved: Word; // Reserved (must be 0)
    idType: Word; // Resource Type (1 for icons)
    idCount: Word; // How many images?
    idEntries: array[0..(MaxInt div SizeOf(GRPICONDIRENTRY))-2] Of GRPICONDIRENTRY;
  end;

  TIconOffsetArray = array[0..(MaxInt div SizeOf(DWORD))-1] Of DWORD;
  PIconOffsetArray = ^TIconOffsetArray;
  TIconResIDArray = array[0..(MaxInt div SizeOf(Word))-1] Of Word;
  PIconResIDArray = ^TIconResIDArray;
var
  hExeInst : HMODULE;
  hResInst : THANDLE;
  AIconHeader : TIconHeader;
  AIconResInfo : GRPICONDIRENTRY;
  AIconResInfoArray : PIconResInfoArray;
  AIconOffsetArray : PIconOffsetArray;
  AIconResIDArray : PIconResIDArray;
  i,CurResID : integer;
  //AIconOrdinals : array Of Word;

  hFile: THandle;
  id: ICONDIR;
  ide: ICONDIRENTRY;
  pid: PICONDIR;
  pgid: PGRPICONDIR;
  uRead: DWord;
  nSize: DWord;
  pvFile: PByte;

  hResSrc : HRSRC;
  hResGlob : HGLOBAL;
  pRes : Pointer;
  ResSize : DWORD;
begin
  result := False;

  hFile := CreateFile(icofile, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

  FillChar(id, sizeof(id), 0);
  if hFile <> INVALID_HANDLE_VALUE then
  try
    ReadFile(hFile, id, sizeof(id), uRead, nil);
  finally
    CloseHandle(hFile);
  end;
  
  AIconResIDArray := nil;
  FillChar(AIconHeader, SizeOf(AIconHeader), 0);

  hExeInst := LoadLibraryEx(exefile, 0, LOAD_LIBRARY_AS_DATAFILE);
  If (hExeInst <> 0) then
  begin
    hResSrc := FindResourceEx(hExeInst, RT_GROUP_ICON, resID, LangID);

    If (hResSrc <> 0) Then
    begin
      // get resource size
      ResSize := SizeofResource(hInstance, hResSrc);

      If (ResSize <> INVALID_FILE_SIZE) Then
      begin
        hResGlob := LoadResource(hExeInst, hResSrc);

        If (hResGlob <> 0) Then
        begin
          pRes := LockResource(hResGlob);

          If (pRes <> nil) Then
          begin
            // Collect information about old Icon group
            CopyMemory(@AIconHeader, pRes, SizeOf(AIconHeader));
            Inc(PChar(pRes), SizeOf(AIconHeader));

            {Form1.ListBox1.Items.Add('Type: ' + IntToStr(AIconHeader.idType) + ', '
                                   + 'Count: ' + IntToStr(AIconHeader.idCount));}


            FillChar(AIconResInfo, SizeOf(AIconResInfo), 0);
            //SetLength(AIconOrdinals, AIconHeader.wCount);

            If (AIconHeader.idCount < id.idCount) then
              GetMem(AIconResIDArray, id.idCount*SizeOf(Word))
            else
              GetMem(AIconResIDArray, AIconHeader.idCount*SizeOf(Word));

            FillChar(AIconResIDArray^, AIconHeader.idCount*SizeOf(Word), 0);
            for i := 1 to AIconHeader.idCount do
            begin
              CopyMemory(@AIconResInfo, pRes, SizeOf(AIconResInfo));
              Inc(PChar(pRes), SizeOf(AIconResInfo));

              AIconResIDArray^[i-1] := AIconResInfo.nID;

              //If (AIconResInfo.common.wBitCount = 0) then
              // AIconResInfo.common.wBitCount := Trunc(log2(AIconResInfo.common.bColorCount));
              {Form1.ListBox1.Items.Add(IntToStr(AIconResInfo.common.bWidth) + 'x' + IntToStr(AIconResInfo.common.bHeight)
                            + ', ' + IntToStr(AIconResInfo.common.bColorCount + (AIconResInfo.common.bReserved * $100)) + ' colors'
                            //+ ', ' + IntToStr(AIconResInfo.common.bReserved) + ' bReserved'
                            + ', ' + IntToStr(AIconResInfo.common.wPlanes) + ' planes'
                            + ', ' + IntToStr(AIconResInfo.common.wBitCount) + ' bit'
                            + ', ' + IntToStr(AIconResInfo.common.dwBytesInRes) + ' byte'
                             + ', ' + 'Ordinal ' + IntToStr(AIconResInfo.nID));}

            end;

            // Search for unused Icon resource IDs
            If (AIconHeader.idCount < id.idCount) then
            begin
              i := AIconHeader.idCount;
              CurResID := 1;
              while (i < id.idCount) and (CurResID < $7FFF) do
              begin
                hResSrc := FindResourceEx(hExeInst, RT_ICON, MAKEINTRESOURCE(CurResID), LangID);

                If not (hResSrc <> 0) Then
                begin
                  Inc(i);
                  AIconResIDArray^[i-1] := CurResID;
                end;

                Inc(CurResID);
              end;
            end;
          end;
        end;
      end;
    end;
    FreeLibrary(hExeInst);
  end;

  If not ((AIconHeader.idCount > 0) and (id.idCount > 0)) then
    Exit;

  hFile := CreateFile(icofile, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

  if hFile <> INVALID_HANDLE_VALUE then
  try
    // Read Data from new icon group in file
    ReadFile(hFile, id, sizeof(id), uRead, nil);
    SetFilePointer(hFile, 0, nil, FILE_BEGIN);
    GetMem(pid, sizeof(ICONDIR) {+ sizeof(ICONDIRENTRY)});
    ReadFile(hFile, pid^, sizeof(ICONDIR) {+ sizeof(ICONDIRENTRY)}, uRead, nil);

    GetMem(pgid, sizeof(GRPICONDIR) {+ sizeof(GRPICONDIRENTRY)});
    move(pid^, pgid^, sizeof(GRPICONDIR));
    pgid^.idEntries.common := pid^.idEntries.common;
    pgid^.idEntries.nID := AIconResIDArray^[0];

    If (pgid^.idEntries.common.wBitCount = 0) then
      pgid^.idEntries.common.wBitCount := Trunc(Log2(pgid^.idEntries.common.bColorCount + (pgid^.idEntries.common.bReserved*$100)));

    {Form1.ListBox1.Items.Add(IntToStr(uRead));}

    // Write new data to EXE resources
    hResInst := BeginUpdateResource(exefile, False);

    // Resource deletion doesn't really work
    {
    for i := 1 to AIconHeader.idCount do
    begin
      ShowMessage(IntToStr(AIconResIDArray^[i-1]));
      UpdateResource(hResInst, RT_Icon, MAKEINTRESOURCE(AIconResIDArray^[i-1]), LangID, nil, 0);
    end;
    }


    //CopyMemory(pgid, @AIconHeader, SizeOf(TIconHeader));
    //pgid^.idCount := 1;
    //If (AIconHeader.idCount < pgid^.idCount) then
    // pgid^.idCount := AIconHeader.idCount;

    //SetFilePointer(hFile, SizeOf(TIconHeader), nil, FILE_BEGIN);

    GetMem(AIconResInfoArray, SizeOf(TIconHeader)+(SizeOf(GRPICONDIRENTRY)*pgid^.idCount));
    GetMem(AIconOffsetArray , SizeOf(DWORD)*pgid^.idCount);
    AIconResInfoArray^.idReserved := pgid^.idReserved;
    AIconResInfoArray^.idType := pgid^.idType;
    AIconResInfoArray^.idCount := pgid^.idCount;
    
    AIconResInfoArray^.idEntries[0] := pgid^.idEntries;
    AIconOffsetArray^[0] := pid^.idEntries.dwImageOffset;

    {Form1.ListBox1.Items.Add(IntToStr(AIconResInfoArray^.idEntries[0].common.bColorCount));}
    for i := 2 to pgid^.idCount do
    begin
      ReadFile(hFile, ide, sizeof(ICONDIRENTRY), uRead, nil);
      AIconResInfoArray^.idEntries[i-1].common := ide.common;
      AIconResInfoArray^.idEntries[i-1].nID := AIconResIDArray^[i-1];
      AIconOffsetArray^[i-1] := ide.dwImageOffset;

      {Form1.ListBox1.Items.Add(IntToStr(AIconResInfoArray^.idEntries[i-1].common.bColorCount + (AIconResInfoArray^.idEntries[i-1].common.bReserved*$100)));}

      If (AIconResInfoArray^.idEntries[i-1].common.wBitCount = 0) then
        AIconResInfoArray^.idEntries[i-1].common.wBitCount := Trunc(Log2(AIconResInfoArray^.idEntries[i-1].common.bColorCount + (AIconResInfoArray^.idEntries[i-1].common.bReserved*$100)));
    end;

    pvFile:= nil;
    result := true;
    for i := 1 to pgid^.idCount do
    begin
      nSize := AIconResInfoArray^.idEntries[i-1].common.dwBytesInRes;
      GetMem(pvFile, nSize);
      SetFilePointer(hFile, AIconOffsetArray^[i-1], nil, FILE_BEGIN);
      ReadFile(hFile, pvFile^, nSize, uRead, nil);

      result := result and UpdateResource(hResInst, RT_ICON, MAKEINTRESOURCE(AIconResInfoArray^.idEntries[i-1].nID), LangID, pvFile, nSize);
    end;

    UpdateResource(hResInst, RT_Group_Icon, resID, LangID, AIconResInfoArray, SizeOf(TIconHeader)+(SizeOf(GRPICONDIRENTRY)*pgid^.idCount));

    EndUpdateResource(hResInst, False);

    FreeMem(AIconOffsetArray);
    FreeMem(AIconResInfoArray);
    FreeMem(pvFile);
    FreeMem(pgid);
    FreeMem(pid);
  finally
    CloseHandle(hFile);
  end;

  If Assigned(AIconResIDArray) then
    FreeMem(AIconResIDArray);
end;
Diese Funktion braucht den Code, den du schon oben angegeben hast. Der einzige Unterschied beim Aufruf ist, das man die ID der Icongruppe angibt, anstatt die des einzelnen Icons. Also zum Beispiel bei einem Delphi-Prog 'MAINICON' statt MAKEINTRESOURCE(1).

EDIT 1: Habe sie jetzt soweit erweitert, das alle Icons einer Gruppe ersetzt werden.
EDIT 2: for-Schleife korrigiert. Die Funktion geht jetzt übrigens ohne die weiter oben, nur die Typendeklarationen sind davon noch erforderlich.
EDIT 3: So, jetzt stimmt alles soweit.
  Mit Zitat antworten Zitat