Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Wie nutzt man ein Interface (IKnownFolderManager) (https://www.delphipraxis.net/177414-wie-nutzt-man-ein-interface-iknownfoldermanager.html)

p80286 5. Nov 2013 14:37

Wie nutzt man ein Interface (IKnownFolderManager)
 
Hallo zusammen,
Um für die neueren Windowsversionen gerüstet zu sein, dachte ich es wäre gut das IKnownfolderManager-Interface zu nutzen.
dabei ist mir aufgefallen, daß ich überhaupt keine Ahnung habe, wie ein Interface richtig eingesetzt wird.
Aus dem was ich mir zusammengesucht habe habe ich dann die folgende Unit gebastelt.
Mein konkretes Problem ist daß
Zitat:

[DCC Fehler] Unit1.pas(24): E2065 Ungenügende Forward- oder External-Deklaration: 'TKnownFolderManager.FolderIdFromCsidl'
......
angemeckert wird. Da die Funktionen aber im Interface stecken, verstehe ich diese Fehlermeldung überhaupt nicht.

U.U. ist das überhaupt Blödsinn, dann wäre es schön wenn Ihr mir sagen könntet wie ich's richtig machen muß.

Delphi-Quellcode:
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls
  ,activeX
  ,shlObj;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

  TKnownFolderManager = class(TInterfacedObject, IKnownFolderManager)
  public
    function FolderIdFromCsidl(nCsidl: Integer;
      var pfid: TKnownFolderID): HRESULT; stdcall;
    function FolderIdToCsidl(const rfid: TIID;
      var pnCsidl: Integer): HRESULT; stdcall;
    function GetFolderIds(ppKFId: array of TKnownFolderID;
      var pCount: UINT): HRESULT; stdcall;
    function GetFolder(const rfid: TIID;
      out ppkf: IKnownFolder): HRESULT; stdcall;
    function GetFolderByName(pszCanonicalName: LPCWSTR;
      out ppkf: IKnownFolder): HRESULT; stdcall;
    function RegisterFolder(const rfid: TIID;
      var pKFD: TKnownFolderDefinition): HRESULT; stdcall;
    function UnregisterFolder(const rfid: TIID): HRESULT; stdcall;
    function FindFolderFromPath(pszPath: LPCWSTR; mode: FFFP_MODE;
      out ppkf: IKnownFolder): HRESULT; stdcall;
    function FindFolderFromIDList(pidl: PItemIDList;
      out ppkf: IKnownFolder): HRESULT; stdcall;
    function Redirect(const rfid: TIID; hwnd: HWND; flags: TKFRedirectFlags;
      pszTargetPath: LPCWSTR; cFolders: UINT; var pExclusion: TKnownFolderID;
      var ppszError: LPWSTR): HRESULT; stdcall;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);

var
  io   : TKnownFolderManager;
  count : Cardinal;
  vielefolder : array of TKnownFolderID;
  buffer : array [0..1024] of byte absolute vielefolder;
begin
  io:=TKnownFolderManager.Create;
  io.GetFolderIds(vielefolder,count);
  Memo1.Lines.Add(' Anz:'+inttostr(count));
end;
(hierfür verwende ich übrigens xe2)

Gruß
K-H

himitsu 5. Nov 2013 15:02

AW: Wie nutzt man ein Interface (IKnownFolderManager)
 
Du hast dir da eine Klasse erstellt, welche dieses Interface "unterstützt", welche also die Funktionalität bereit stellt, welche mann dan hinter dem Interface verstecken kann.

Und da du eine klasse hast, worin du Methoden deklariert hast, mußt du, wie bei jeder Klasse natürlich auch diese methoden implementieren, sonst weiß die Klasse ja nicht was sie machen soll. :zwinker:
Und genau diese fehlende implementation wurde dir vom Compiler angekreidet.


Aber du willst ja keine "eigene" Objektinstanz erstellen, welche dan über dieses Interface angesprochen wird, sondern du willst irgendeine eine fremde Instanz haben.
Im Prinzip wirst du da wohl Windows fragen müssen, ob es dir eine Instanz mit diesem Interface gibt.

Hab da jetzt auch nichts auf die Schnelle im Kopf, aber schau doch einfach mal in deren Demo nach, wo die sich diese Interface-Instanz herholen.
http://archive.msdn.microsoft.com/shellapplication > KnownFolders.zip




PS: Das Interface ist die Schnittstelle. Stell es dir wie eine Klasse vor, wo alle Funktionen als Abstract deklariert sind (z.B. TStrings oder TStream).
Jetzt brauchst du nur noch eine Funktion, welche dir eine Instanz gibt (die intern also 'ne TStringList oder TMemoryStream erstellt) und die du dann verwenden kannst (lesen und schreiben), ohne daß es dich interessiert, was für ein Objekt wirklich da drin ist.

Du hast praktisch deine eigene TXyzStream-Kalsse deklariert, zu welcher du jetzt noch die Funktionen definieren müßtest (wie z.B. TMemoStrings, welches die Zugriffe auf ein TMemo umleitet),
aber das wolltest du ja eigentlich nicht machen.

Uwe Raabe 5. Nov 2013 15:15

AW: Wie nutzt man ein Interface (IKnownFolderManager)
 
Mal abgesehen davon ist die Deklaration von GetFolderIds in ShlObj falsch! Die anderen habe ich jetzt nicht überprüft.

Richtig wäre

Delphi-Quellcode:
   
type
  IKnownFolderManager = interface(IUnknown)
    [SID_IKnownFolderManager]
    function FolderIdFromCsidl(nCsidl: Integer;
      var pfid: TKnownFolderID): HRESULT; stdcall;
    function FolderIdToCsidl(const rfid: TIID;
      var pnCsidl: Integer): HRESULT; stdcall;
    function GetFolderIds(out ppKFId: PGUIDList;
      var pCount: UINT): HRESULT; stdcall;
    function GetFolder(const rfid: TIID;
      out ppkf: IKnownFolder): HRESULT; stdcall;
    function GetFolderByName(pszCanonicalName: LPCWSTR;
      out ppkf: IKnownFolder): HRESULT; stdcall;
    function RegisterFolder(const rfid: TIID;
      var pKFD: TKnownFolderDefinition): HRESULT; stdcall;
    function UnregisterFolder(const rfid: TIID): HRESULT; stdcall;
    function FindFolderFromPath(pszPath: LPCWSTR; mode: FFFP_MODE;
      out ppkf: IKnownFolder): HRESULT; stdcall;
    function FindFolderFromIDList(pidl: PItemIDList;
      out ppkf: IKnownFolder): HRESULT; stdcall;
    function Redirect(const rfid: TIID; hwnd: HWND; flags: TKFRedirectFlags;
      pszTargetPath: LPCWSTR; cFolders: UINT; var pExclusion: TKnownFolderID;
      var ppszError: LPWSTR): HRESULT; stdcall;
  end;

type
  TKnownFolderManager = class
  public
    class function CreateInstance: IKnownFolderManager;
  end;

class function TKnownFolderManager.CreateInstance: IKnownFolderManager;
begin
  if CoCreateInstance(CLSID_KnownFolderManager, nil, CLSCTX_INPROC_SERVER, IID_IKnownFolderManager, Result) <> S_OK then begin
    result := nil;
  end;
end;

procedure TForm254.Button1Click(Sender: TObject);
var
  io : IKnownFolderManager;
  count : Cardinal;
  vielefolder : PGUIDList;
begin
  io:=TKnownFolderManager.CreateInstance;
  io.GetFolderIds(vielefolder, count);
  Memo1.Lines.Add(' Anz:'+inttostr(count));
  CoTaskMemFree(vielefolder);
end;

p80286 6. Nov 2013 11:16

AW: Wie nutzt man ein Interface (IKnownFolderManager)
 
Vielen Dank!
Ich bin im Augenblick ein wenig im Stress, darum hab ich wenig Zeit hier herein zu schauen.
Der Tip mit "KnownFolders.zip" hat mich auf einem Umweg zu http://www.swissdelphicenter.ch/de/showcode.php?id=1009
geführt, das kann ich vielleicht als Prototyp verwursten.
@Uwe
ich hab Deine Korrekturen noch nicht durchgesehen, werd sie aber bestimmt nicht ignorieren.

vielen Dank nochmal

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:06 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