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
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 15:59
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?
Sämtliche Methoden, die du in einem Interface deklarierst, sind automatisch virtual (und abstract ). _AddRef , _Release und QueryInterface werden von Delphi automatisch zu jedem Interface hinzugefügt, um die COM Kompatibilität zu gewährleisten.

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 MSDN-Library durchsuchenIUnknown einfach als normale Klasse mit den entsprechenden 3 virtuellen Methoden deklariert (eine Unterscheidung zwischen class und interface 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 _AddRef aufrufen, sobald man eine neue Referenz erzeugt bzw. Wrapperklassen verwenden, die das für einen übernehmen).
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl (14. Sep 2017 um 16:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

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

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 16:02
Oha, vielen Dank! Wichtiger Hinweis!
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
 
#3

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 16: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 16:22 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

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

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 16: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
 
#5

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 16: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
 
#6

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 16: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 16:54 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

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

AW: Classe/Interface aus WinProc aufrufen

  Alt 14. Sep 2017, 18: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
Antwort Antwort


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:16 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-2025 by Thomas Breitkreuz