![]() |
Classe/Interface aus WinProc aufrufen
Bekomme meine Referenz Zähler nicht herunter.
Das einzige was ich mir vorstellen könnte was das Problem verursacht ist das ich das Interface aus der WinProc heraus aufrufe\muss. bsp.
Delphi-Quellcode:
Mein Problem ist das ich die Winproc nicht in das Interface integrieren kann.
WM_COMMAND:
begin ShowWindow(WinHandle, SW_HIDE); SkinPopUpMenu.DlgItem := wP; SkinPopUpMenu.DestroyWindow; end; deshalb muss ich eine globale Variable definieren. Eventuell ist das mein Problem mit dem Reverenz Zähler
Delphi-Quellcode:
SkinPopUpMenu : TSkinPopUpMenu;
gruss |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
|
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Delphi-Quellcode:
TSkinPopUpMenu = class(TInterfacedObject, ISkinPopUpMenu, ISkinPopUpMenuEx)
Delphi-Quellcode:
SkinPopUpMenu : ISkinPopUpMenuEx;
Edit: Das ist erledigt meine Frage aber damit nicht beantwortet. gruss |
AW: Classe/Interface aus WinProc aufrufen
Ich hänge mich mal an die Frage mit ran, weil ich gerade ein ähnliches Problem habe. Meine DLL wird nämlich nicht sauber entladen, da irgendwo noch eine einzelne Referenz existiert, die ich aber ums verrecken nicht finden kann. Mich würde auch mal interessieren ob es irgendwie möglich ist, die Referenzen "aufzulösen". Also praktisch eine Art Liste in der ich sehe, wo ich meine Interface Instanz überall hin referenziert habe.
Ist so etwas möglich und wenn ja, wie? |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
gruss |
AW: Classe/Interface aus WinProc aufrufen
Ist das hier die Fortsetzung von dem:
![]() Du hast m.E. im Projekt als auch hier in Deinen Fragen zu wenig Ordnung bzw. Übersicht. Wenn Du mit Interfaces arbeitest und die Referenzzählung nutzen willst, musst Du halt den Ablauf soweit überschauen, dass Du weißt wo Referenzen zugewiesen und ob die wieder aufgelöst werden. Evtl. kann ein Tool wie EurekaLog helfen, hängende Referenzen zu finden. Da Du aber vermutlich nur 2 oder 3 Referenzen verwendest, findet man die Stelle aber evtl. auch so. Was hast Du denn geändert, nachdem Du im anderen Thread gesagt hattest, die Freigabe funktioniert? Wenn Du z.B. danach noch eine Interfacevariable
Delphi-Quellcode:
deklariert und zugewiesen hast, dann müsstest Du dieser Variablen auch wieder Nil zuweisen, damit Dein Objekt freigegeben wird.
MeineNeuePopupVariable: IMyPopup;
So von außen ist das schwer zu beurteilen. Vielleicht kannst Du die Ursache eingrenzen, wenn Du die Änderungen seit dem letzten Erfolgs-Post nochmal anschaust... |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Und die wird nicht freigegeben. Ich habe nichts geändert im anderen Projekt wird diese korrekt freigegeben. Das einzige was im anderen Projekt anders ist, ist das ich kein Submenu verwende. Nur was nicht initialisiert wird (SubMenu) muss auch nicht freigegeben werden. Zitat:
Aber im nachhinein dann dürfte im anderen Projekt die Referenz auch nicht freigegeben werden wenn es daran läge. gruss |
AW: Classe/Interface aus WinProc aufrufen
Sorry, ich kann Deine Fragen nicht ausreichend nachvollziehen.
Sind das zwei Threads zu zwei verschiedenen Projekten? Existiert das Problem der Nicht-Freigabe im anderen Thread noch - und wenn, dann in dem anderen Projekt oder nur in diesem hier? Wenn die Fragestellung nicht eindeutig klar ist, kann man darauf natürlich auch nicht hilfreich antworten. Aber ich orakle mal etwas... Wenn Du eine Interfacevariable MyPopupMenu hast, und dann noch eine Interfacevariable MySubMenu dann könnten diese u.U. gegenseitige Referenzen aufeinander halten. Also falls Du so etwas machen solltest wie: MySubMenu.RegisterOwnerPopupMenu(MyPopupMenu) und darin dem MyPopupMenu auch das SubMenu zugewiesen wird, dann halten beide eine Referenz aufeinander. Es kann dann keine automatische Freigabe mehr erfolgen, weil Interface1 in Interface2 referenziert wird und somit nicht freigegeben werden kann, weil noch eine Referenz existiert und andersrum auch. Um das aufzulösen, müsste man eine der beiden zirkulären Referenzen auflösen (z.B. MySubMenu.UnregisterOwnerPopupMenu(MyPopupMenu)). Vielleicht sind ja solche hängenden oder zirkulären Referenzen Dein Problem. Wie gesagt, so von außen ist das schwer zu beurteilen. |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
KVPlayer, OTTB Beide verwenden das gleiche Interface. KVPlayer mit SubMenus OTTB ohne KVPLayer gibt alle Reverenzen korrekt frei. OTTB nicht. So nun bin ich am Rätzeln denn eigentlich wäre das Problem verständlich wenn OTTB mit Submenu laufen würde. Das gibt es hier aber nicht und trotzdem wird die Reverenz nicht freigegeben. Also beide verwenden das selbe Interface das eine geht das andere nicht. gruss |
AW: Classe/Interface aus WinProc aufrufen
Ah, ok. Dann tippe ich wirklich auf gegenseitige Referenzierung. Wenn das Submenu sein Hauptmenu kennt (also ein einem Property oder ein einer Liste speichert) und auch das Hauptmenu sein Submenü verwaltet (was ja zu vermuten ist ;-) ) dann wird genau dieses Problem vorliegen. Quatsch. In der Eile hatte ich das falsch gelesen. Also dann wir es im OTTB noch irgendeine Referenz geben, der nicht NIL zugewiesen wird. Das zu finden kann aufwendig werden. |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Keine einzige Variable die damit im Zusammenhang stehen könnte wird dann verwendet oder initialisiert. gruss |
AW: Classe/Interface aus WinProc aufrufen
Habe das gerade korrigiert.
Ich schreibe hier schnell mal parallel während der Arbeit. Da bin ich manchmal nicht konzentriert genug. :-( Dann musst Du mal schauen, wo da noch eine Referenz gehalten wird. |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Werde ich wohl selbst fixen müssen wie auch immer. ;) gruss |
AW: Classe/Interface aus WinProc aufrufen
Liste der Anhänge anzeigen (Anzahl: 1)
Delphi-Quellcode:
Dann in den eigenen _AddRef und _Release Haltepunkte setzen und vergleichen.
TSkinPopUpMenu = class(TInterfacedObject, ISkinPopUpMenu...)
... protected function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; public ... end; ... function TSkinPopUpMenu._AddRef: Integer; begin Result := inherited _AddRef; end; function TSkinPopUpMenu._Release: Integer; begin Result := inherited _Release; end; Irgendwo gibt es das Ungleichgewicht. Fortgeschrittenen-Tipp: Haltepunkte setzen aber in den Eigenschafen Break/Anhalten deaktivieren und den Call Stack mitloggen in der Ereignisanzeige: |
AW: Classe/Interface aus WinProc aufrufen
Danke werde das mal testen obwohl _AddRef , _Release eigentlich geerbt werden :)
gruss |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
|
AW: Classe/Interface aus WinProc aufrufen
Zitat:
gruss |
AW: Classe/Interface aus WinProc aufrufen
Ich hätte das auch schon vorgeschlagen, dachte aber, das ginge nicht, weil _AddRef ja nicht virtuell ist und somit nicht überschrieben werden kann...
Gibt es (zum Verständnis) eine Erklärung, warum das so funktioniert? |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Delphi-Quellcode:
(und
virtual
Delphi-Quellcode:
).
abstract
Delphi-Quellcode:
,
_AddRef
Delphi-Quellcode:
und
_Release
Delphi-Quellcode:
werden von Delphi automatisch zu jedem Interface hinzugefügt, um die COM Kompatibilität zu gewährleisten.
QueryInterface
Im Grunde sind COM Interfaces auch lediglich Klassen, welche mindestens die oben genannten virtuellen Methoden besitzen. Unter C++ sieht man das ganz schön, denn da ist das Basisinterface ![]()
Delphi-Quellcode:
und
class
Delphi-Quellcode:
gibt es hier gar nicht). Die Unterscheidung - wie man sie in Delphi hat - ist vermutlich nur vorhanden, weil Delphi die Interfaces ja tatsächlich auch unterschiedlich behandelt (automatischer RefCount und Freigabe, etc). In anderen Sprachen hat man dieses Verhalten nicht (man muss manuell
interface
Delphi-Quellcode:
aufrufen, sobald man eine neue Referenz erzeugt bzw. Wrapperklassen verwenden, die das für einen übernehmen).
_AddRef
|
AW: Classe/Interface aus WinProc aufrufen
Oha, vielen Dank! Wichtiger Hinweis!
|
AW: Classe/Interface aus WinProc aufrufen
Also beim Start habe ich 3 Referenzen dann wird einmalig _Release aufgerufen bleiben 2. Dann wird das Menu angezeigt.
Beim beenden jedoch wird nicht einmal _Release aufgerufen und SkinPopUpMenu ist nicht Nil. Habe meine Funktion mal geändert zum initialisieren rufe nicht mehr
Delphi-Quellcode:
result := TSkinPopUpMenu.Create
von außen auf sondern diese.
Delphi-Quellcode:
danach
function CTRL_PopUpMenuCreate(callback: POPUPSTATECALLBACK): ISkinPopUpMenu; stdcall;
begin result := InitPopUpMenu(); PopUpCallback := callback; end;
Delphi-Quellcode:
und in create
function InitPopUpMenu: ISkinPopUpMenu;
begin if SkinPopUpMenu = nil then SkinPopUpMenu := TSkinPopUpMenu.Create; result := SkinPopUpMenu as ISkinPopUpMenu; end;
Delphi-Quellcode:
constructor TSkinPopUpMenu.Create;
begin inherited Create; // SkinPopUpMenu := self; ItemEnabled := True; SideBarCount := 0; ButtonCount := 0; SubMenuHandleCount := 0; FHPopupWindow := 0; gP.ProgManHandle := FindWindow('Progman', 'Program Manager'); end;
Delphi-Quellcode:
verstehe es nicht.var SkinPopUpMenu : ISkinPopUpMenuEx; Die Funktionen werden alle entladen bzw.. freigegeben. Hilft niemandem weiter nur zur Info. Und das funktioniert alles in meinem KVPlayer.
Delphi-Quellcode:
gruss
procedure TSkinPopUpMenu.DestroyWindow;
var IntI: Integer; hResource: HBitmap; begin UnSubClass(gP.ParentHandle); KillTimer(Handle, SKAERO_AERO_TIMER); KillTimer(Handle, POPUP_TIMER); // Alle Skinresourcen freigeben. if SubMenuHandleCount > 0 then for IntI := 0 to SubMenuHandleCount - 1 do SkinEngine.DestroyWindowResource(SubMenuWindow[IntI].Handle); // Privaten font freigeben if Assigned(FPrivateFont) then GdipCheck(GdipDeletePrivateFontCollection(FPrivateFont)); // erstellte Button freigeben if ButtonCount > 0 then begin for IntI := 0 to ButtonCount - 1 do begin btnMenu[IntI].DestroyWindow; btnMenu[IntI] := nil; end; FillChar(btnMenu, ButtonCount, 0); ButtonCount := 0; end; // Sidebar resourcen freigeben if SideBarCount > 0 then begin for IntI := 0 to SideBarCount - 1 do begin SideBarFrame[IntI].DestroyWindow; SideBarFrame[IntI] := nil; end; FillChar(SideBarFrame, SideBarCount, 0); SideBarCount := 0; end; hResource := SkinEngine.GetPaintBitmap(SkinPopUpMenu.Handle); DeleteObject(hResource); if SubMenuHandleCount > 0 then begin for IntI := 0 to SubMenuHandleCount - 1 do if Windows.DestroyWindow(SubMenuWindow[IntI].Handle) then SubMenuWindow[IntI].Handle := 0; FillChar(SubMenuWindow, SubMenuHandleCount, 0); end; if Windows.DestroyWindow(Handle) then UnRegisterClass(wc.lpszClassName, hInstance); // Skinresource des Hauptfenster freigeben SkinEngine.DestroyWindowResource(Handle); // TODO // FillChar(SkinPopUpMenu, SizeOf(SkinPopUpMenu), 0); if not Assigned(SkinPopUpMenu) then PopUpCallback(OnPopupDestroyed); end; |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Wird die ausgeführt? Wenn ja, müsste später ja SkinPopUpMenu wieder etwas zugewiesen werden. Wenn nein, dann musst Du prüfen, warum nicht. |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Und das SkinPopUpMenu(DLL) PopUpMenu(Anwendung) muss vorher schon Nil sein bevor ich die Callback abschicke. Und das ist auch so im KVPlayer aber nicht in OTTB. gruss |
AW: Classe/Interface aus WinProc aufrufen
Die Anwendung fordert das Interface an.
Delphi-Quellcode:
PopUpMenu := CTRL_PopUpMenuCreate(PopUpCallback);
Delphi-Quellcode:
Anschließend werden die Variablen an das Interface der DLL übergeben.
procedure TMainApp.CreatePopUpMenu(WinHandle: HWND);
var PrivateFont: PWideChar; begin PopUpMenu := CTRL_PopUpMenuCreate(PopUpCallback); PopUpMenu.Width := CLIENT_WIDTH; PopUpMenu.Height := CLIENT_HEIGHT; PopUpMenu.SkinConfigFile := PWideChar(FolderResource + 'PopUpWindow\OTTB.ske'); PopUpMenu.UseVistaCrystal := true; PopUpMenu.UseVistaBlur := false; PopUpMenu.UseSideBar := True; PopUpMenu.SideBarImgPath := ''; PopUpMenu.SelectedImgPath := FolderResource + 'PopUpWindow\MEN_Select.png'; PopUpMenu.IconArrowPath := ''; PopUpMenu.SeperatorImgPath := ''; PopUpMenu.SideBarCaption := 'Over the TaskBar'; PopUpMenu.SideBarCaptionLeft := 12; PopUpMenu.SideBarCaptionTop := 198; PopUpMenu.ImageStateMax := 0; PopUpMenu.ItemHeight := 20; PopUpMenu.ItemWidth := 190; PopUpMenu.ItemLeft := 29; PopUpMenu.ItemShadow := 1; PopUpMenu.ItemTextLeft := 20; hPopUpHandle := PopUpMenu.CreatePopUpMenu(WinHandle); if hPopUpHandle <> 0 then begin AppendMenu(hPopUpHandle); PrivateFont := PWideChar(FolderResource + 'PopUpWindow\OTTB.ttf'); PopUpMenu.FontName := 'Nasalization Free'; PopUpMenu.FontSize := 14; PopUpMenu.CreatePrivateFont(PrivateFont); gP.hPopUpMenu := hPopUpHandle; end; end;
Delphi-Quellcode:
diese übernimmt nun das Zeichen und alle anderen dinge die mit dem Menu zu tun haben.
procedure TMainApp.AppendMenu(hMain: HWND);
var Text: PWideChar; procedure Append(Handle: HWND; ItemShadow: integer; ItemIconPath: WideString; ItemToolTip: PWideChar; ItemHiliteColor: COLORREF; ItemTextAlligment: TTextAlligment; Top: integer; Flags, DlgItemID: UINT; Text: PWideChar; Enabled: BOOL = True); begin PopUpMenu.ItemShadow := ItemShadow; PopUpMenu.ItemIconPath := ItemIconPath; PopUpMenu.ItemToolTip := ItemToolTip; PopUpMenu.ItemHiliteColor := ItemHiliteColor; PopUpMenu.ItemTextAlligment := ItemTextAlligment; PopUpMenu.ItemTop := Top; PopUpMenu.ItemEnabled := Enabled; PopUpMenu.AppendMenu(Handle, Flags, DlgItemID, Text); end; begin panBackgoundFrame := CTRL_FrameButtonCreate(); panBackgoundFrame.ImagePath := SKAERO_FOLDER + 'Frame.png'; panBackgoundFrame.Left := 9; panBackgoundFrame.Top := 9; panBackgoundFrame.Width := 210; panBackgoundFrame.Height := 340; panBackgoundFrame.DlgItemID := ID_BACKGROUNDFRAME; panBackgoundFrame.ImageStateMax := 0; panBackgoundFrame.Enabled := false; panBackgoundFrame.Visible := True; panBackgoundFrame.CreateWindow(hMain); SKAERO_SetAnchorMode(panBackgoundFrame.Handle, ANCHOR_HEIGHT_WIDTH); SKAERO_SetZorder(panBackgoundFrame.Handle, HWND_TOP); // About Append(PopUpMenu.Handle, 1, '', 'Oops...' + CHR(13) + 'Are they in the wrong place?', SKAERO_BTNTEXTCOLOR, Left, 9, MF_OWNERDRAW, IDM_About, 'About'); // Icon frame Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 49, MF_OWNERDRAW, IDM_IconFrame, 'Icon frame'); // Background layer Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 69, MF_OWNERDRAW, IDM_IconBack, 'Background layer'); // Change Wallpaper Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 89, MF_OWNERDRAW, IDM_Wallpaper, 'Change Wallpaper'); // Shortcut if gP.ShortCutVisible then Text := 'Hide shor cut' else Text := 'Show short cut'; Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 129, MF_OWNERDRAW, IDM_ShortCut, Text); // Sound if gP.SoundActive then Text := 'Disable sound' else Text := 'Enable sound'; Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 169, MF_OWNERDRAW, IDM_Sound, Text); // Build Config file Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 209, MF_OWNERDRAW, IDM_BuildCONFIG, 'Build Config file'); // Edit Config file Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 229, MF_OWNERDRAW, IDM_Edit, 'Edit Config file'); // Cleanup Config file Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 249, MF_OWNERDRAW, IDM_Cleanup, 'Cleanup Config file'); // Restart OverTheTaskBar Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 269, MF_OWNERDRAW, IDM_Restart, 'Restart OverTheTaskBar'); // Portable App if gP.Portable then Text := 'Disable Portable App' else Text := 'Enable Portable App'; Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 309, MF_OWNERDRAW, IDM_PORTABLE, Text); // Close OverTheTaskBar Append(PopUpMenu.Handle, 1, '', '', SKAERO_BTNTEXTCOLOR, Left, 329, MF_OWNERDRAW, IDM_Close, 'Close OverTheTaskBar'); end; Das war's. Aber entladen wird das Interface nicht. Warum habe ich schon gesagt. wird die Callback abgefeuert
Delphi-Quellcode:
wird nur das PopUpMenu der Anwendung auf Nil gesetzt.
procedure PopUpCallback(PopUpState: TPopUpState); stdcall;
begin case PopUpState of OnPopupDestroyed: PopUpMenu := nil; end; end; Das Interface in der DLL sollte dann schon NIL sein. EDIT: Das Menu wird dann in der WinProc gestartet.
Delphi-Quellcode:
Wenn man zweimal hintereinander den rechten Button klickt wird das Menu über PopUpMenu.DestroyWindow; zerstört.
WM_RBUTTONDOWN:
begin if PopUpMenu <> nil then PopUpMenu.DestroyWindow; nObjectID := MainApp.GetMouseMoveSpriteID(WinHandle, lpX, lpY); if nObjectID = 0 then begin SKAERO_CONFIG_ShadowColor(SKAERO_ColorARGB(255, RGB(0, 0, 0)), SKAERO_WRITE); KillTimer(MainHandle, 1); MainApp.CreatePopupMenu(WinHandle); GetCursorPos(P); GetWindowRect(gP.hPopUpMenu, Rect); ClientToScreen(gP.hPopUpMenu, P); MenuWahl := PopUpMenu.TrackPopupMenu(gP.hPopUpMenu, P.X - 7, (P.Y - Rect.Bottom) + 9, Rect.Right, Rect.Bottom); if MenuWahl then SendMessage(WinHandle, WM_COMMAND, Makelong(word(MenuWahl), 0), 0); Andernfalls wird es in der DLL beendet. gruss |
AW: Classe/Interface aus WinProc aufrufen
Schwierig nachzuvollziehen, finde ich.
Auf DLL-Seite ist das Problem, dass "SkinPopUpMenu" nicht Nil ist?
Delphi-Quellcode:
Der Callback wird aber auf Anwendungsseite ausgeführt?
if not Assigned(SkinPopUpMenu) then
PopUpCallback(OnPopupDestroyed); Dann muss die obige Anweisung ja ausgeführt worden sein. Wenn SkinPopUpMenu nicht Nil ist, müsstest Du Nil zuweisen - das kann nicht das Problem sein. Wird vielleicht SkinPopUpMenu erst mal auf Nil gesetzt und dann nochmal neu durch irgendeine unbeabsichtigte Reaktion wieder zugewiesen? Kannst Du das Problem genau auf einer Seite eingrenzen? |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Das macht nur sinn wenn in der DLL das Interface Nil ist vorher kann ich das in der Anwendung nicht löschen. Zitat:
Zitat:
Aus der DLL heraus wenn SkinPopUpMenu Nil ist gruss |
AW: Classe/Interface aus WinProc aufrufen
Ok.
Delphi-Quellcode:
wird nicht ausgeführt, weil SkinPopupMenu immer zugewiesen ist (lassen wir mal die doppelte Verneinung weg).
if not Assigned(SkinPopUpMenu) then
PopUpCallback(OnPopupDestroyed); Ich habe hier den Thread durchsucht nach "SkinPopUpMenu :=". Zumindest hier kann ich nichts finden, das SkinPopupMenu Nil zuweist. Dort, wo das passiert (oder erfolgt dies vielleicht gar nicht?), sollte SkinPopupMenu danach ja auch Nil sein (andernfalls verwendest Du vielleicht eine lokale Variable gleichen Namens). Wenn das so ist, - kommt das Programm danach nie mehr zur obigen Prüfung oder - SkinPopupMenu wird wieder ein InterfaceObject zugewiesen. |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Nur das wird er nie. Das ist doch mein Problem das ich dir über Mail mitgeteilt habe. Deshalb wollte ich alle Variablen des SkinPopupMenu mit FillChar auf 0 setzen um den Status bzw. den Reverenz Zähler auf 0 zu bekommen. Du sagtest das soll ich nicht tun. Im Netzt ist leider nichts zu finden ohne das man sich ein Buch dafür zulegen muss. Der eine sagt man darf ein Interface selber nicht auf NIL setzen. Der andere sagt doch ist kein Problem Der nächste sehe zu das der Reverenz Zähler auf 0 geht dann ist SkinPopupMenu automatisch Nil. Langsam blicke ich da selbst nicht mehr durch da jeder etwas anderes sagt. gruss |
AW: Classe/Interface aus WinProc aufrufen
Den Referenzzähler verwaltet Delphi für Dich.
Und zwar wird er erhöht, wenn Du einer Interfacevariable Dein InterfaceObject zuweist und verringert, wenn Du Nil zuweist. Intf1 := TInterfacedObject.Create; // RefCount = 1 Intf2 := Intf1; // RefCount = 2 Intf1 := Nil; // RefCount = 1 Intf2 := Nil; // RefCount = 0 --> InterfaceObject.Free wird "von Delphi" ausgeführt. In dem anderen Thread hatte ich Dir das erklärt. Zitat:
Also setze SkinPopupMenu auf Nil, wenn das Ding nicht mehr gebraucht wird. Dann wird der Callback ausgeführt und auch im Hauptprogramm die Referenzvariable auf Nil gesetzt und das Objekt freigeben. Du musst den Interfacevariablen Nil zuweisen. Den Rest macht Delphi für Dich. In dem anderen Projekt scheint das ja auch zu klappen. |
AW: Classe/Interface aus WinProc aufrufen
Ich habe versucht jetzt durchzusteigen wo das Problem ist.
Zitat:
Andersherum wird ein Schuh daraus: Wenn alle!!! Referenzen auf das Interface nil sind geht der Referenz Zähler auf 0 und das darunter liegende Objekt wird freigegeben. Du weist wie Du mich erreichen kannst...... |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Das ist zum Verständnis vielleicht wichtig, da wir hier schon so lange um den Brei herum reden. Wenn ein Objekt 5 Interfaces unterstützt und 3 Interfaces je einer Interfacevariablen zugewiesen sind, ist der RefCounter des Objektes = 3. |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
|
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Ich suche das jetzt raus. Zitat:
Dann tue ich folgendes..
Delphi-Quellcode:
Hier setze ich alle variablen auf 0, NIL oder wie auch immer danach ist mein Interface NIL (Da keine Variable mehr in gebrauch ist.)
// TODO
FillChar(SkinPopUpMenu, SizeOf(SkinPopUpMenu), 0); if not Assigned(SkinPopUpMenu) then PopUpCallback(OnPopupDestroyed); Darf man aber anscheinend auch nicht. Und ja ich weis das man eine Variable direkt auf Nil setzen kann wäre es nicht so dann sollte man es direkt lassen. Aber da hat man mir dann wieder zwischen gepfuscht mit der Meldung nein man darf kein Interface selbst auf NIL setzen.
Delphi-Quellcode:
SkinPopUpMenu := Nil;
Ehrlich keine Ahnung was das noch soll. Wie man es macht, macht man es falsch. Hätte man mich nicht so irritiert mit den Referenz Zähler dann hätte ich schon lange einfach vor
Delphi-Quellcode:
PopUpCallback(OnPopupDestroyed);
Einfach
Delphi-Quellcode:
SkinPopUpMenu := Nil;
gesetzt und fertig. Wäre ja nicht das erste mal das ich eine Variable auf NIL setze LOL. Zitat:
Mich interessiert das überhaupt nicht ob der Zähler 0 oder auf 3 steht. Mich interessiert nur eins kann ich mein Interface selbst auf NIL setzen oder nicht. Dann wäre meine Lösung diese
Delphi-Quellcode:
und fertig .. alles so wie gehabt. (Bei normalen Classen)
SkinPopUpMenu := nil;
PopUpCallback(OnPopupDestroyed); gruss |
AW: Classe/Interface aus WinProc aufrufen
Genau so ist es korrekt. Berichte mal, ob dann alles funktioniert.
Wenn Du mit Interfaces incl. Referenzzählung arbeitest, dann nie bei dem Objekt hinter dem Interface Free aufrufen! Immer nur Interfacevariablen Nil zuweisen. Bei der letzten Nil-Zuweisung wird Free automatisch ausgeführt. Dafür ist die Referenzzählung da. Wie schon mal gesagt: "InterfaceObject.Free" ist etwas völlig anderes als "MyInterfaceVariable := Nil" |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Warum auch nicht. Ich habe mich hier einfach nur verrückt machen lassen weil entschuldige kein Angriff gegen irgend jemanden jeder etwas anderes gesagt hat. Zitat:
gruss |
AW: Classe/Interface aus WinProc aufrufen
Du hast das m.E. nur falsch verstanden. Ist auch kein Vorwurf. :-)
Ich habe auch Interfaces schon eine Weile genutzt, bis ich die Zusammenhänge wirklich verstanden habe. Jetzt ist mir gar nicht klar, was daran so schwierig war. Auch durch so eine Diskussion hier festigt man die eigenen Kenntnisse. Insofern profitieren hier alle. :thumb: |
AW: Classe/Interface aus WinProc aufrufen
Ich denke da ich kein Informatiker bin .. ist es mir auch nicht so geläufig die richtigen Ausdrücke für ein Problem zu definieren.
Auf Grund dessen entstehen die Probleme mit denen ich zu kämpfen habe. (siehe Spaghetti Code) usw... für mich stellt dann so etwas einen Angriff gegen meine Person dar. Ich bin ja nicht blöd.. hab ich wohl schon bewiesen aber mir fehlt es halt an den Dingen die ein Informatiker als selbstverständlich voraussetzt. Aber das muss man nicht alles wissen. ;) PS: EurekaLog ist ein mächtiges Werkzeug :) Habe mal die 30Tage Test Version versucht. Feines Teil. gruss |
AW: Classe/Interface aus WinProc aufrufen
Wir helfen uns ja hier gegenseitig und freiwillig.
Persönliche Angriffe gibt es ja hier zum Glück so gut wie nicht - ist ja leider selten im Netz, dass es so freundlich zugeht. Insofern muss man nur versuchen, nicht aneinander vorbei zu reden. An Dich der Tipp: Es wäre vielleicht etwas geordneter zugegangen, wenn Du die Probleme und Fragen präziser formuliert hättest. Wobei mir auch klar ist, dass das manchmal nicht so einfach ist, wenn man die Zusammenhänge noch nicht richtig einordnen kann. Geht ja fast jedem so. |
AW: Classe/Interface aus WinProc aufrufen
Zitat:
Nur. Ich bin Hobbykoch und da kennt man auch nicht jede Apfelsorte ;) So sieht s jetzt aus und ist gut genug für mich. gruss |
AW: Classe/Interface aus WinProc aufrufen
Also die Optik entschädigt jede Mühe. Das hast Du echt drauf. :thumb:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:12 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 by Thomas Breitkreuz