2016-03-21 6 views
3

Hallo Ich habe ein Programm, das, wenn eine Schaltfläche geladen wird, erstellt eine Ressource manuell in der Anwendung selbst (in diesem Fall ein Bild) und liest dann die Ressource in einem timage.El Problem angezeigt wird dass es scheint, dass die Ressource gut erstellt, aber wenn ich die Ressource laden will sagt es nicht finden, wenn Sie suchen.Erstellen und Laden von Ressourcen in Delphi

Der Code.

procedure StringtoRes(const FileName: string; Inputstream: TMemoryStream); 
var 
    hUpdate: THandle; 
begin 
    hUpdate := BeginUpdateResource(PChar(FileName), True); 
    try 
    UpdateResource(hUpdate, RT_RCDATA, 'ID', LANG_NEUTRAL, Inputstream.Memory, 
     Inputstream.Size); 
    finally 
    EndUpdateResource(hUpdate, False); 
    end; 
end; 

procedure TForm1.btnTestClick(Sender: TObject); 
var 
    MemStr: TMemoryStream; 
    FileName: string; 

var 
    RStream: TResourceStream; 
    JPEGImage: TJPEGImage; 
begin 

    FileName := 'c:/test/test.jpg'; 

    MemStr := TMemoryStream.Create; 
    MemStr.LoadFromFile(FileName); 
    MemStr.Seek(0, soFromBeginning); 
    StringtoRes(paramstr(0), MemStr); 
    MemStr.Free; 


    Sleep(3000); 


    RStream := TResourceStream.Create(HInstance, 'ID', RT_RCDATA); 
    JPEGImage := TJPEGImage.Create; 
    JPEGImage.LoadFromStream(RStream); 
    Image1.Picture.Graphic := JPEGImage; 

    JPEGImage.Free; 
    RStream.Free; 

end; 

wie ich das lösen?

Antwort

4

Im Allgemeinen kann ein laufender Prozess seine eigenen Ressourcen nicht aktualisieren, da die ausführbare Datei gesperrt und nicht schreibbar ist. Um das zu tun, was Sie versuchen, sollten Sie die Ressource in eine separate DLL verschieben. Dann können Sie die DLL dynamisch über LoadLibrary() laden, wenn Sie ihre Ressourcen laden müssen, und sie über FreeLibrary() entladen, wenn Sie ihre Ressourcen aktualisieren müssen.

var 
    hResLib: THandle = 0; 

procedure TForm1.btnTestClick(Sender: TObject); 
var 
    ResFileName: string; 
    MemStr: TMemoryStream; 
    RStream: TResourceStream; 
    JPEGImage: TJPEGImage; 
begin 
    ResFileName := ExtractFilePath(ParamStr(0)) + 'myres.dll'; 

    if hResLib <> 0 then 
    begin 
    FreeLibrary(hResLib); 
    hResLib := 0; 
    end; 

    MemStr := TMemoryStream.Create; 
    try 
    MemStr.LoadFromFile('c:/test/test.jpg'); 
    MemStr.Position := 0; 
    StringtoRes(ResFileName, MemStr); 
    finally 
    MemStr.Free; 
    end; 

    Sleep(3000); 

    hResLib := LoadLibrary(ResFileName); 
    Win32Check(hResLib <> 0); 

    RStream := TResourceStream.Create(hResLib, 'ID', RT_RCDATA); 
    try 
    JPEGImage := TJPEGImage.Create; 
    try 
     JPEGImage.LoadFromStream(RStream); 
     Image1.Picture.Graphic := JPEGImage; 
    finally 
     JPEGImage.Free; 
    end; 
    finally 
    RStream.Free; 
    end; 
end; 

Auch Sie überprüfen nicht den Rückgabewert von BeginUpdateResource() sicherzustellen, dass es tatsächlich erfolgreich ist, bevor dann UpdateResource() aufrufen.

procedure StringtoRes(const FileName: string; Inputstream: TMemoryStream); 
var 
    hUpdate: THandle; 
    bDiscard: BOOL; 
begin 
    hUpdate := BeginUpdateResource(PChar(FileName), True); 
    Win32Check(hUpdate <> 0); // <-- ADD THIS! 
    bDiscard := True; 
    try 
    Win32Check(UpdateResource(hUpdate, RT_RCDATA, 'ID', LANG_NEUTRAL, Inputstream.Memory, Inputstream.Size)); 
    bDiscard := False; 
    finally 
    EndUpdateResource(hUpdate, bDiscard); 
    end; 
end; 
+0

Dank Remy, eine letzte Frage, wenn ich ohne meinen ursprünglichen Code verwenden eine andere exe Angabe, meine Funktion die Exe beschädigt, weil er verbrachte das? weil ich sieben 64-bit habe? – FF2

+0

eine Frage, warum Schlaf (3000); ? Vielen Dank. – Passella