![]() |
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...... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:31 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