Autor |
Beitrag |
FriFra
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 16:00
Ich weiss, dass ich irgendwo etwas falsch mache, zumindest fängt bei wiederholter Ausführung der folgenden Funktion der Rechner irgendwann komplett an zu spinnen... obwohl eigentlich alles jeweils korrekt freigegeben wird (werden sollte).
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: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156:
| procedure TForm1.SetIcon(Loading, Ignoring, Stopped, Plugin: boolean); function CombineIcons(FrontIcon, BackIcon: HIcon): HIcon; var WinDC: HDC; FrontInfo: TIconInfo; FrontDC: HDC; FrontSv: HBITMAP; BackInfo: TIconInfo; BackDC: HDC; BackSv: HBITMAP; BmpObj: tagBitmap; begin WinDC := GetDC(0);
GetIconInfo(FrontIcon, FrontInfo); FrontDC := CreateCompatibleDC(WinDC); FrontSv := SelectObject(FrontDC, FrontInfo.hbmMask);
GetIconInfo(BackIcon, BackInfo); BackDC := CreateCompatibleDC(WinDC); BackSv := SelectObject(BackDC, BackInfo.hbmMask);
GetObject(FrontInfo.hbmMask, SizeOf(BmpObj), @BmpObj); BitBlt(BackDC, 0, 0, BmpObj.bmWidth, BmpObj.bmHeight, FrontDC, 0, 0, SRCAND);
SelectObject(BackDC, BackInfo.hbmColor); DrawIconEx(BackDC, 0, 0, FrontIcon, 0, 0, 0, 0, DI_NORMAL);
Result := CreateIconIndirect(BackInfo);
SelectObject(FrontDC, FrontSv); DeleteDC(FrontDC); SelectObject(BackDC, BackSv); DeleteDC(BackDC); ReleaseDC(0, WinDC); DeleteObject(FrontInfo.hbmColor); DeleteObject(FrontInfo.hbmMask); DeleteObject(BackInfo.hbmColor); DeleteObject(BackInfo.hbmMask); DeleteObject(FrontSv); DeleteObject(BackSv); end; var RS: TResourceStream; sI: string; Ico: array[0..8] of TIcon; n: integer; begin for n := 0 to High(Ico) do Ico[n] := TIcon.Create;
try StrPLCopy(IconData.szTip, '[' + Label2.Caption + ']'#13 + 'WAN-IP: ' + Edit3.Text + #13 + 'LAN-IP: ' + Edit4.Text, 63);
if G_IP = '0.0.0.0'#0 then sI := 'I_Inactive' else if G_IP = '0.0.0.0' then sI := 'I_Offline' else sI := 'I_Online'; try RS := TResourceStream.Create(0, sI + GetIconSufix, RT_RCDATA); RS.Position := 0; Ico[0].LoadFromStream(RS); finally RS.Free; end;
if Loading then sI := 'I_Loading' else sI := 'I_Blank'; try RS := TResourceStream.Create(0, sI + GetIconSufix, RT_RCDATA); RS.Position := 0; Ico[1].LoadFromStream(RS); finally RS.Free; end; Ico[2].Handle := CombineIcons(Ico[1].Handle, Ico[0].Handle);
if Ignoring then sI := 'I_Ignoring' else sI := 'I_Blank'; try RS := TResourceStream.Create(0, sI + GetIconSufix, RT_RCDATA); RS.Position := 0; Ico[3].LoadFromStream(RS); finally RS.Free; end; Ico[4].Handle := CombineIcons(Ico[3].Handle, Ico[2].Handle);
if Stopped then sI := 'I_Stop' else sI := 'I_Blank'; try RS := TResourceStream.Create(0, sI + GetIconSufix, RT_RCDATA); RS.Position := 0; Ico[5].LoadFromStream(RS); finally RS.Free; end; Ico[6].Handle := CombineIcons(Ico[5].Handle, Ico[4].Handle);
if Plugin then sI := 'I_Plugin' else sI := 'I_Blank'; try RS := TResourceStream.Create(0, sI + GetIconSufix, RT_RCDATA); RS.Position := 0; Ico[7].LoadFromStream(RS); finally RS.Free; end; Ico[8].Handle := CombineIcons(Ico[7].Handle, Ico[6].Handle);
DestroyIcon(TNA_Icon.Handle); TNA_Icon.Assign(Ico[8]); DestroyIcon(IconData.hIcon); IconData.hIcon := TNA_Icon.Handle;
DestroyIcon(Image1.Picture.Icon.Handle); Image1.Picture.Icon.Handle := IconData.hIcon; Image1.Repaint; Edit3.Text := G_IP; Label7.Caption := G_IT;
if G_IP = '0.0.0.0'#0 then Label2.Caption := 'undefined' else if G_IP = '0.0.0.0' then Label2.Caption := 'Offline' else Label2.Caption := 'Online';
if IsMinimized = True then Shell_NotifyIcon(NIM_MODIFY, @IconData);
finally for n := 0 to High(Ico) do begin Ico[n].ReleaseHandle; DestroyIcon(Ico[n].Handle); FreeAndNil(Ico[n]); end; IconReady := True; end; end; |
Update: Ich habe auf einen Array of Icon umgestellt 
_________________ Michael
(principal certified lotus professional - developer)
Zuletzt bearbeitet von FriFra am So 25.01.04 19:11, insgesamt 1-mal bearbeitet
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 18:13
Ähm - Frage so nebenbei - warum verwendest den kein Array für die Icons ! Da blickt ja keiner mehr durch und die Fehleranfälligkeit steigt ins astronomische ... nein, fast intergalaktische Sphären die sich überdimensional auszudehen scheinen im Raumzeitkontinuum ! 
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
FriFra 
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 18:17
Ähm... sooo viele Icons sind es nun auch wieder nicht, und da jedes der temporären Icons nur einmal belegt wird, sollte es noch überschaubar sein... Array oder nicht Array, da ist hier nicht die Frage, gesucht wird der Fehler bei der Ressourcenfreigabe 
_________________ Michael
(principal certified lotus professional - developer)
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 18:46
Schön - Frage: Wo gibst du FrontSv frei ? Und wo BackSv ?
Und ich bleibe dabei, du sagst selber du hast den Überblick verloren, also ist ein Array angesagt. Bei alles was mehr als 2 ist, ist ein Array nämlich angesagt. Da schrumpfen in deinem Fall 9 Zeilen auf zwei - und das in 3 Fällen ... wirst ja nicht nach Codezeilen bezahlt, oder ?
Edit
Moment - SelectObject ... in dem Fall braucht man das RegionObject nnicht freizugeben. *puh* Ich blick da gerade nicht durch. Vielleicht tut sich ein anderer leichter bei deinem Code !
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
FriFra 
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 19:02
Ich habe nirgends gesagt, dass ich den Überblick verloren habe...
Danke für den Tip  . Die Funktion CombineIcons habe ich vom SwissDelphicenter und wende sie auch schon längere Zeit ohne Probleme an, deshalb habe ich dort keinen Fehler vermutet. Aber Du hast recht, ich habe am Ende der Funktion noch folgendes eingebaut: Delphi-Quelltext 1: 2:
| DeleteObject(FrontSv); DeleteObject(BackSv); |
Allerdingt kommt immernoch nach wenigen Minuten (einige hundert Updates) ein EOutOfResources
Ich habe die Funktion CombineIcons auch noch nie so häufig genutzt, aber da der Tip schon länger veröffentlicht ist und offenbar noch keiner solche Probleme hatte denke ich nicht, das es an dieser Funktion liegt. Der Fehler müsste eigentlich wo anders liegen...
_________________ Michael
(principal certified lotus professional - developer)
|
|
FriFra 
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 19:14
@MaxiTB: Ich habe Deinem Wunsch entsprochen und auf Array umgestellt 
_________________ Michael
(principal certified lotus professional - developer)
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 19:19
Der Absatz kommt mir noch ein bisserl merkwürdig vor ... was pssiert hier genau ?
Delphi-Quelltext 1: 2: 3: 4:
| DestroyIcon(TNA_Icon.Handle); TNA_Icon.Assign(Ico[8]); DestroyIcon(IconData.hIcon); IconData.hIcon := TNA_Icon.Handle; |
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
FriFra 
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 19:28
MaxiTB hat folgendes geschrieben: | Der Absatz kommt mir noch ein bisserl merkwürdig vor ... was pssiert hier genau ?
Delphi-Quelltext 1: 2: 3: 4:
| DestroyIcon(TNA_Icon.Handle); TNA_Icon.Assign(Ico[8]); DestroyIcon(IconData.hIcon); IconData.hIcon := TNA_Icon.Handle; | |
1. Zeile: Ich habe in meinem Programm eine globale Icon Variable TNA_Icon, deren Icon wird hier freigegeben.
2. Zeile: Meinem globalen Icon wird der Inhalt des gerade berechneten Icons (Ico[8]) zugewiesen
3. Zeile: Das Icon der globalen Variable IconData (Typ: TNotifyIconData) wird hier freigegeben.
4. Zeile: Das TNA_Icon wird dem eigentlichen NotifyIcon zugewiesen (noch nicht in den TNA upgedatet)
_________________ Michael
(principal certified lotus professional - developer)
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 19:32
Jetzt fällt mir nix mehr auf ... ists sicher, daß es an dieser Stelle passiert ? Immerhin wird hier wesentlich mehr freigegeben als überhaupt reserviert wird ...
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
FriFra 
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 19:44
MaxiTB hat folgendes geschrieben: | Immerhin wird hier wesentlich mehr freigegeben als überhaupt reserviert wird ... |
Eben deshalb frage ich ja hier... Ich bin mir aber 100% sicher, dass es an dieser Procedure liegt. Denn wenn ich direkt am Procedure-beginn ein Exit platziere, läuft das Programm Fehlerfrei... nur eben sinnlos, weil das Icon nicht geändert wird 
_________________ Michael
(principal certified lotus professional - developer)
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 21:38
Oki - kann dir nur noch einen Tip geben ... klammert per Kommentare soviel Code in der Prozedure aus wie möglich und dann schrittweise weniger ... bis der Fehler wieder auftritt.
Mehr fällt mir nicht ein ... so kannst du vielleicht die Stelle besser eingrenzen ...
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
FriFra 
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 21:49
Ich habe jetzt festgestellt, dass bei Auskommentierung aller Zuweisungen über CombineIcon kein Fehler mehr auftritt  ... Allerdings ist die Kombination der Icons elementar für mein Programm
Wenn ich das nicht gelöst bekomme, muss ich die Anzahl der Icons in der Resource vervierfachen, um alle Kombinationen abzudecken 
_________________ Michael
(principal certified lotus professional - developer)
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 21:52
Okay - jetzt wirds ernst - gucken wir mal, was das Ding wirklich macht und wo da der Saft verloren geht ... Moment ...
Jetzt habe ich gerade X-Men 2: United hinter mir, jetzt bin ich wieder motiviert 
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 22:01
Haha ... ist doch klar. *lol* Warum ists mir nicht gleich aufgefallen ...
Mit CreateIconIndirect erstellst du eine neue Resource, welche du mit DestroyIcon ja wieder freigibst, oder ? ODER ? Ja was ist ? Wo wird die jetzt freigegeben ? *g*
Das ist die Frage, nicht ?
Schauen wir uns diese Zeile mal genau an:
Delphi-Quelltext 1:
| Ico[2].Handle := CombineIcons(Ico[1].Handle, Ico[0].Handle); |
Die Frage ist: Was macht sie ? Ändert sie nur eine Referenz, wird die alte Resource freigegeben - wird vielleicht intern wieder ein CreateIconIndirect gemacht um eine Kopie zu bekommen - da hilft nur ein Blick in die Source  Moment ...
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
toms
      
Beiträge: 1099
Erhaltene Danke: 2
|
Verfasst: So 25.01.04 22:03
Zitat: | Remember: The icon created with the CombineIcons function must be destroyed with DestroyIcon() function when finished using it. |
|
|
FriFra 
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 22:09
MaxiTB hat folgendes geschrieben: | Haha ... ist doch klar. *lol* Warum ists mir nicht gleich aufgefallen ...
Mit CreateIconIndirect erstellst du eine neue Resource, welche du mit DestroyIcon ja wieder freigibst, oder ? ODER ? Ja was ist ? Wo wird die jetzt freigegeben ? *g* |
Schau mal in den finally Abschnitt... da gebe ich alles frei. Zwischendurch ändere ich auch nichts mehr an den bettr. Icons.
_________________ Michael
(principal certified lotus professional - developer)
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 22:12
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TIcon.SetHandle(Value: HICON); begin NewImage(Value, nil); Changed(Self); end; |
Aha ... weiterstöbern ...
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TIcon.NewImage(NewHandle: HICON; NewImage: TMemoryStream); var Image: TIconImage; begin Image := TIconImage.Create; try Image.FHandle := NewHandle; Image.FMemoryImage := NewImage; except Image.Free; raise; end; Image.Reference; FImage.Release; FImage := Image; end; |
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TIconImage.FreeHandle; begin if FHandle <> 0 then DestroyIcon(FHandle); FHandle := 0; end; |
Okay ... Mist ... schaut so aus, wie wenn das auch richtig täte ...
Aber so wie es aussieht, ists vielleicht gar nicht soo gut, wenn du am Schluß auf diese Referenz ein DestroyIcon machst eben wegen den Code da oben ...
Wenn mans nämlich genau betrachtet, wird zweimal ein DestroyIcon durchgeführt ... und ich weiß nicht, ob das nicht zu Nebeneffekten führen kann. Obwohl FHandle:=nil ... daher müßten die schon alle nil sein zu dem Zeitpunkt ...
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 22:25
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function TIcon.ReleaseHandle: HICON; begin with FImage do begin if FRefCount > 1 then NewImage(CopyIcon(FHandle), nil); Result := FHandle; FHandle := 0; end; Changed(Self); end; |
Schau mal, ob zufällig ReleaseHandle ein Icon zurückgibt; das solltest du nämlich freigeben. Man beachte das CopyIcon !
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
FriFra 
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: So 25.01.04 23:11
Also, nach ReleaseHandle bleibt die Handlenummer immer erhalten, genau wie nach DestroyIcon...
Ohne DestroyIcon schaufelt sich merklich der Arbeisspeicher zu. So wie es jetzt ist, bleibt der Speicherverbrauch relativ konstant, bis plötzlich die Ressourcen verbraucht sind.
Ich habe übrigens etwas merkwürdiges im Debugger bemerkt:

_________________ Michael
(principal certified lotus professional - developer)
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: So 25.01.04 23:20
Dann hats aber was - weil da oben siehst du ja, das FHandle auf 0 gesetzt wird. Nach ReleaseHandle muß also Handle=nil sein.
Nochmals der ...
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function TIcon.ReleaseHandle: HICON; begin with FImage do begin if FRefCount > 1 then NewImage(CopyIcon(FHandle), nil); Result := FHandle; FHandle := 0; end; Changed(Self); end; |
Irgendwie scheints da ordentlich den Speicher durcheinander zu wirbeln ...
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
|