AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Classe/Interface aus WinProc aufrufen
Thema durchsuchen
Ansicht
Themen-Optionen

Classe/Interface aus WinProc aufrufen

Ein Thema von EWeiss · begonnen am 14. Sep 2017 · letzter Beitrag vom 14. Sep 2017
Antwort Antwort
Seite 3 von 4     123 4      
EWeiss
(Gast)

n/a Beiträge
 
#21

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 17:17
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
result := TSkinPopUpMenu.Create

von außen auf sondern diese.
Delphi-Quellcode:
function CTRL_PopUpMenuCreate(callback: POPUPSTATECALLBACK): ISkinPopUpMenu; stdcall;
begin

  result := InitPopUpMenu();
  PopUpCallback := callback;
end;
danach
Delphi-Quellcode:
function InitPopUpMenu: ISkinPopUpMenu;
begin

  if SkinPopUpMenu = nil then
    SkinPopUpMenu := TSkinPopUpMenu.Create;

  result := SkinPopUpMenu as ISkinPopUpMenu;
end;
und in create
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:
  
var
  SkinPopUpMenu : ISkinPopUpMenuEx;
verstehe es nicht.

Die Funktionen werden alle entladen bzw.. freigegeben. Hilft niemandem weiter nur zur Info.
Und das funktioniert alles in meinem KVPlayer.
Delphi-Quellcode:
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;
gruss

Geändert von EWeiss (14. Sep 2017 um 17:22 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#22

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 17:27
... SkinPopUpMenu ist nicht Nil ...
Das sollte doch in der Callback-Methode gemacht werden - oder?
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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#23

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 17:35
... SkinPopUpMenu ist nicht Nil ...
Das sollte doch in der Callback-Methode gemacht werden - oder?
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.
Ja die wird ausgeführt in der Main Application da hat aber die DLL nichts von.
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
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#24

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 17:42
Die Anwendung fordert das Interface an.

  PopUpMenu := CTRL_PopUpMenuCreate(PopUpCallback);
Delphi-Quellcode:
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;
Anschließend werden die Variablen an das Interface der DLL übergeben.
Delphi-Quellcode:
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;
diese übernimmt nun das Zeichen und alle anderen dinge die mit dem Menu zu tun haben.
Das war's.

Aber entladen wird das Interface nicht.
Warum habe ich schon gesagt.

wird die Callback abgefeuert
Delphi-Quellcode:
procedure PopUpCallback(PopUpState: TPopUpState); stdcall;
begin
  case PopUpState of
    OnPopupDestroyed:
      PopUpMenu := nil;
  end;
end;
wird nur das PopUpMenu der Anwendung auf Nil gesetzt.
Das Interface in der DLL sollte dann schon NIL sein.

EDIT:
Das Menu wird dann in der WinProc gestartet.
Delphi-Quellcode:
    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);
Wenn man zweimal hintereinander den rechten Button klickt wird das Menu über PopUpMenu.DestroyWindow; zerstört.
Andernfalls wird es in der DLL beendet.

gruss

Geändert von EWeiss (14. Sep 2017 um 17:54 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#25

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 19:03
Schwierig nachzuvollziehen, finde ich.

Auf DLL-Seite ist das Problem, dass "SkinPopUpMenu" nicht Nil ist?
Delphi-Quellcode:
  if not Assigned(SkinPopUpMenu) then
     PopUpCallback(OnPopupDestroyed);
Der Callback wird aber auf Anwendungsseite ausgeführt?
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?
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#26

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 19:09
Zitat:
Auf DLL-Seite ist das Problem, dass "SkinPopUpMenu" nicht Nil ist?
richtig deshalb kann ich auch kein Callback schicken.
Das macht nur sinn wenn in der DLL das Interface Nil ist vorher kann ich das in der Anwendung nicht löschen.

Zitat:
Wird vielleicht SkinPopUpMenu erst mal auf Nil gesetzt und dann nochmal neu durch irgendeine unbeabsichtigte Reaktion wieder zugewiesen?
Nein denn _Release wird nicht aufgerufen.

Zitat:
Der Callback wird aber auf Anwendungsseite ausgeführt?
Nein kann ich nicht schicken.. ansonsten ja wenn das Interface in der DLL Nil ist funktioniert das Callback.

Aus der DLL heraus wenn SkinPopUpMenu Nil ist

gruss

Geändert von EWeiss (14. Sep 2017 um 19:17 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#27

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 20:10
Ok.
Delphi-Quellcode:
  if not Assigned(SkinPopUpMenu) then
      PopUpCallback(OnPopupDestroyed);
wird nicht ausgeführt, weil SkinPopupMenu immer zugewiesen ist (lassen wir mal die doppelte Verneinung weg).

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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#28

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 20:26
Zitat:
Zumindest hier kann ich nichts finden, das SkinPopupMenu Nil zuweist.
Den Status Nil erhält das SkinPopupMenu wenn der Reverenz Zähler auf 0 ist.

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
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#29

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 20:40
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:
Den Status Nil erhält das SkinPopupMenu wenn der Reverenz Zähler auf 0 ist.
kann also nicht funktionieren, da der Referenzzähler erst auf 0 fällt, wenn alle Referenzvariablen Nil sind.


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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (14. Sep 2017 um 20:42 Uhr)
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#30

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 20:42
Ich habe versucht jetzt durchzusteigen wo das Problem ist.
Zitat:
Den Status Nil erhält das SkinPopupMenu wenn der Reverenz Zähler auf 0 ist.
das widerspricht allem was mit Interfaces zu tun hat.

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......
Fritz Westermann
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz