Link to home
Start Free TrialLog in
Avatar of m_adil
m_adil

asked on

Shell NameSpace Extension

Is it possible to create a Shell NameSpace Extension project using Delphi-5.

Let me describe in detail what I want.
I want a new drive to be shown in windows explorer. When ever I click this drive, it connects to an ftp server and shows me the contents of the server. It allows me to drag drop, cut/copy/paste files from my computer to ftp server. Basically it will be an ftp client in windows explorer and will be using its interface.
I think it is possible using in-process server. but how to do that???
In other words I want to create a project like xDrive or NetDrive. You can find more details from www.xdrive.com or www.netdrive.com

If it is possible in Delphi-5 then I'll increase points to 100+ to know how to do.
Avatar of inthe
inthe

hi ,
the answer is yes and you can find some stuff here:

http://members.tripod.com/~delphipower/winshell.htm

it was for d3 but it shouldnt be far from working in d5.

Regards Barry
Actually, I wrote a name space extension myself (a virtual folder to access Interbase databases, D4+). So if you have questions, just ask (after you increased the points :-)).

Ciao, Mike
Avatar of m_adil

ASKER

Adjusted points from 10 to 120
Avatar of m_adil

ASKER

ok Mike. I've incresed points to 120.
Now can u give me a sample code that connects me to an ftp server when I click on the folder, and allows me to upload/download files from/to the server.

Thanks

Adil.
Adil, it seems you have a totally wrong impression what is involved in a name space extension. I can give you code and help to write and install the core of the extension. The rest is totally up to you.

What you need first is to write a shell folder interface. To do this create a new application (File|New|ActiveX|ActiveX Library). You will get a dpr file which looks like:

library Test;

uses
  ComServ,
  ShellFolder in 'ShellFolder.pas';

exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

{$R *.RES}

begin
end.

The Unit ShellFolder is of course not already there. You need to create that unit and add it to the project (File|New|ActiveX|COM object). The new COM object implements IShellFolder and IPersistFolder and is derived from TComObject. The result looks something like:

unit ShellFolder;

interface

uses
  Windows, ActiveX, Classes, ComObj, ShlObj;

type
  TShellFolder = class(TComObject, IShellFolder, IPersistFolder)
  protected
    // We do the following declaration to alias the Initialize function.
    // Initialize is also declared in TComObject and conflicts with the one from IPersistFolder
    function IPersistFolder.Initialize = IPersistFolder_Initialize;
  public
    // IPersist declarations
    function GetClassID(out classID: TCLSID): HResult; stdcall;

    // IPersistFolder declarations
    function IPersistFolder_Initialize(pidl: PItemIDList): HResult; stdcall;

    // IShellFolder declarations
    function ParseDisplayName(hwndOwner: HWND; pbcReserved: Pointer; lpszDisplayName: POLESTR; out pchEaten: ULONG;
             out ppidl: PItemIDList; var dwAttributes: ULONG): HResult; stdcall;
    function EnumObjects(hwndOwner: HWND; grfFlags: DWORD; out EnumIDList: IEnumIDList): HResult; stdcall;
    function BindToObject(pidl: PItemIDList; pbcReserved: Pointer; const riid: TIID; out ppvOut): HResult; stdcall;
    function BindToStorage(pidl: PItemIDList; pbcReserved: Pointer; const riid: TIID; out ppvObj): HResult; stdcall;
    function CompareIDs(lParam: LPARAM; pidl1, pidl2: PItemIDList): HResult; stdcall;
    function CreateViewObject(hwndOwner: HWND; const riid: TIID; out ppvOut): HResult; stdcall;
    function GetAttributesOf(cidl: UINT; var apidl: PItemIDList; var rgfInOut: UINT): HResult; stdcall;
    function GetUIObjectOf(hwndOwner: HWND; cidl: UINT; var apidl: PItemIDList; const riid: TIID; prgfInOut: Pointer;
             out ppvOut): HResult; stdcall;
    function GetDisplayNameOf(pidl: PItemIDList; uFlags: DWORD; var lpName: TStrRet): HResult; stdcall;
    function SetNameOf(hwndOwner: HWND; pidl: PItemIDList; lpszName: POLEStr; uFlags: DWORD; var ppidlOut: PItemIDList): HResult; stdcall;

    // ShellFolder declarations
    destructor Destroy; override;
  end;

const
  Class_ShellFolder: TGUID = '{449AB457-A7F8-11D3-8FC2-0080C894409B}';

implementation

uses ComServ;

{ TShellFolder }

function TShellFolder.BindToObject(pidl: PItemIDList;
  pbcReserved: Pointer; const riid: TIID; out ppvOut): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.BindToStorage(pidl: PItemIDList;
  pbcReserved: Pointer; const riid: TIID; out ppvObj): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.CompareIDs(lParam: LPARAM; pidl1,
  pidl2: PItemIDList): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.CreateViewObject(hwndOwner: HWND; const riid: TIID;
  out ppvOut): HResult;
begin
  Result := E_NOTIMPL;
end;

destructor TShellFolder.Destroy;
begin
  inherited;
end;

function TShellFolder.EnumObjects(hwndOwner: HWND; grfFlags: DWORD;
  out EnumIDList: IEnumIDList): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.GetAttributesOf(cidl: UINT; var apidl: PItemIDList;
  var rgfInOut: UINT): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.GetClassID(out classID: TCLSID): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.GetDisplayNameOf(pidl: PItemIDList; uFlags: DWORD;
  var lpName: TStrRet): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.GetUIObjectOf(hwndOwner: HWND; cidl: UINT;
  var apidl: PItemIDList; const riid: TIID; prgfInOut: Pointer;
  out ppvOut): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.IPersistFolder_Initialize(
  pidl: PItemIDList): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.ParseDisplayName(hwndOwner: HWND;
  pbcReserved: Pointer; lpszDisplayName: POLESTR; out pchEaten: ULONG;
  out ppidl: PItemIDList; var dwAttributes: ULONG): HResult;
begin
  Result := E_NOTIMPL;
end;

function TShellFolder.SetNameOf(hwndOwner: HWND; pidl: PItemIDList;
  lpszName: POLEStr; uFlags: DWORD; var ppidlOut: PItemIDList): HResult;
begin
  Result := E_NOTIMPL;
end;

initialization
  TComObjectFactory.Create(ComServer, TShellFolder, Class_ShellFolder,
    'ShellFolder', '', ciMultiInstance, tmApartment);
end.


Here I have already filled the class body with default results. This way you can compile it at least and see if it installs (Run|Register ActiveX server).

Ciao, Mike
Snooping around...
ps.
if you downloaded winshell3.zip you already have these files..
Adil, Barry usually makes very good comments so I'd first download and see what's in winshell3 before we continue here...

Ciao, Mike
mike ,
my advice,
download winshell example.
read tutorial etc to get understanding.
compile in d5 and get 1-2 errors ,come back and ask mike why the errors ;-)
i doubt i can fix these errors ,they dont look too bad but not stuff ive time to learn at moment ,but the example code may save you a lot of extra typing.

sorry that should be to madil not mike (i think mike already understand this stuff :o)
I tryed winshell.
It compiles and does install fine.
but when I browse in my windows explorer
to it, I get an Error:TShellFolderImpl.GetClassID
after clicking ok, I get an application
error:write where I cannot (I'm using NT)
And last explorer tells me they was an internal error and closes the window.
Even if I saw the contain of the two files
it tries to open...

I know, this is not my question ;)...
I just tried it out myself and it works fine for me (D5, WinNT4, SP6). But I had to correct some errors in the sources which were made in pre D5 versions and have been corrected later. These errors, though, seem not to have serious impact on the way the extension works, because they dealt mainly with var parameters for a property sheet page or removed pointer paramter types.

So there must something other be wrong.

Ciao, Mike
mike if you dont mind would you send me the "corrected for d5" code with a comment as to what was wrong, there will be some points waiting for you :o)
Avatar of m_adil

ASKER

thanks for the code.
plz give me some time to check it out.

>>Adil, it seems you have a totally wrong impression what is involved in a name space extension.

Mike can u plz correct me if i'm wrong.
What I know about name space extension is that these are the folders displayed in the name space ext viewer (such as windows explorer) with the root folder starting from desktop. These name space ext are also visible in file open/save dislog boxes.
isn't it. plz correct me if i am wrong.
I was playing around whith winshell too.
To update the code just look in the Delphi sourcode files or the helpfiles.
Will take 5 minutes to correct the parameters and get it compiled.
But to correctly implement all the interfaces you will have to read the MS-documentation on those interfaces which could take quite a while...
In fact I have the same config then you Mike, but I compiled it with D3 because of the errors. Mays I get my hands on the D5 project too please ? Thank you.

And what about making it appear in open/save dialogs ? Is there a type we can give to our extension to make it appear ?

Barry, xsoft is right, there are only very few changes to make. Just try to compile Winshell in D5 and it will show you the places where the declaration differs. Use then Ctrl+Left click on the particular interface to view the original declaration and change Winshell accordingly. No need to waste points for that, but thanks for your offer :-)

Adil,

you are right. Your description is roughly about what a name space extension is. But the actual implementation is much harder and actually one of the toughest areas in Windows programming I ever worked at.

Ciao, Mike
Well, Barry, jeurk, mail me at public@lischke-online.de and I will send you the project.

Because also open and save dialogs are using the shell name space your own extension should appear there. But the must be of the correct type, I think. I have not yet tried it but I suppose the SFGAO_FILESYSTEM flag must be specified too for the extension to show up in those dialogs.

Ciao, Mike
hehe cool i got it working at last ,for anyone interested  ,there only about 8 changes to make for d5 ,some in shellview.pas and shellfolder.pas ,you can find the proper declarations in ishellview declaration in shlobj.pas..

mike my ctrl-left click stopped working last week ,that was the biggest problem but something has now fixed it?strange stuff.
Super Barry. Once you have got it working it is not half the stress to go further than before :-)

Ciao, Mike
Avatar of m_adil

ASKER

I've gone through the code. Its almost the same as winshell3.zip. It is doing the basic functionality, but I want to do much more than this. for eg.

1. I want to use Explorers cut/copy/paste, change view buttons to work with my name-space

2. I want to add child items to my name-space icon on the left side TreeView.

How can I do this. Basically I need the basic features of the explorer to work with my name-space.
ASKER CERTIFIED SOLUTION
Avatar of Lischke
Lischke

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of m_adil

ASKER

Thank u very much...
by the way are there any sites that can help name-space programming with Delphi.
Well, I wasn't looking very hard for other informatin and the only address I have is http://members.tripod.com/~delphipower/shellext.htm, but unfortunately this site already disappeard. I strongly recommend that you do a search on www.deja.com.

Ciao, Mike