Shell Objects 

Content / madShell /...

The interface "IShellObj" described in this section implements functionality around shell objects, with which browseable objects of any kind are meant (drives, files, folders, special folders, non file system objects). Everything that you can browse through in the Windows Explorer can be represented by and handled with an IShellObj interface. See also the IShellObj Reference.

type IShellObj = interface (ICustomBasicList) ['{00BED961-C78D-11D3-A530-00005A180D69}'];

There are multiple ways to get an IShellObj instance:

function ShellObj (path         : string        ) : IShellObj; overload;
function ShellObj (sf           : TSpecialFolder) : IShellObj; overload;
function ShellObj (const idList : IIDList       ) : IShellObj; overload;
function ShellObj (const sfi    : IShellFolder  ) : IShellObj; overload;

// Examples:
with ShellObj('C:\'                 ) do [...]
with ShellObj('D:\Folder\ReadMe.txt') do [...]
with ShellObj(sfControlPanel        ) do [...]

Calling "Desktop" is the same as calling "ShellObj(sfDesktopRoot)". It's a very special shell object: The child items of the Desktop shell object are the only ones where the properties IShellObj.Position and IShellObj.State are supported.

function Desktop : IShellObj;

Each shell object - except the Desktop shell object - has a parent:

property IShellObj.Parent : IShellObj;

Some shell objects are folder objects (so you can browse into them), others are not. If the current shell object is a folder object, it may have child items (see also IList.ItemCount). With "RefreshItems" you can refresh the child items, that is look for new/deleted/changed items. Last but not least you can search for specific child items.

function IShellObj.IsFolder : boolean;

property IShellObj.Items [index: integer] : IShellObj;

function IShellObj.RefreshItems : boolean;

function IShellObj.Item (name       : string ) : IShellObj; overload;
function IShellObj.Item (const name : TGuid  ) : IShellObj; overload;
function IShellObj.Item (const name : IIDList) : IShellObj; overload;

Each shell object is identified by a unique IDList:

property IShellObj.IDList : IIDList;

The property "Path" returns the full path of the current shell object as a string. If the shell object is a non file system object, the path consists of GUID strings. The other 3 properties don't return the path of the shell object, but instead only the name. They often bring the same results, but sometimes they differ. "Name" simply returns the last part of the "Path" string, "Description" and "DescrInFolder" are 2 slightly different variants that return the display string, which is shown in the Windows Explorer when browsing.

property IShellObj.Path          : string;

property IShellObj.Name          : string;
property IShellObj.Description   : string;
property IShellObj.DescrInFolder : string;

// Examples:
ShellObj(sfMyComputer).Path           ->  '::{20D04FE0-3AEA-1069-A2D8-08002B30309D}'
ShellObj(sfMyComputer).Name           ->  '::{20D04FE0-3AEA-1069-A2D8-08002B30309D}'
ShellObj(sfMyComputer).Description    ->  'My Computer'
ShellObj(sfMyComputer).DescrInFolder  ->  'My Computer'

The following 2 properties are only valid for the child items of the Desktop shell object. You can ask the position and the state of such objects, furthermore you can also set the position.

property IShellObj.Position : TPoint;
property IShellObj.State    : cardinal;

// Example:
with Desktop.Item(ShellObj(sfMyComputer).IDList) do
  ShowMessage('My Computer position: ' + IntToStr(Position.X) + '/' + IntToStr(Position.Y));

When you need an icon for a shell object, just call "GetIcon". You can specify, how big the icon shall be. Also you can specify some additional parameters:

  TIconFlags = set of (ifForShell,       // the icon is for shell browsing
                       ifForShortcut,    // the icon is for a shortcut
                       ifOpenState  );   // get the "open" state of the icon

// askAgain =  nil -> correct icon will be returned even if it takes a while
// askAgain <> nil -> GetIcon will fill the parameter "askAgain" with
//                    false : correct icon was available quite fast
//                    true  : simplified icon is returned, ask again later
//                            without specifiying "askAgain" to get the
//                            correct icon -> this may be time consuming
function IShellObj.GetIcon (size     : cardinal   = 32;
                            flags    : TIconFlags = [];
                            askAgain : TPBoolean  = nil) : cardinal;

// Example:
Image1.Picture.Icon.Handle := ShellObj(sfMyComputer).GetIcon;

The following properties return additional infos about our shell object. You can ask the attributes, the GUID (in case the object has one) and you can also ask for a IShellFolder instance of this shell object (in case this object supports it).

property IShellObj.Attributes    : cardinal;
property IShellObj.Guid          : TGuid;
property IShellObj.IShellFolder_ : IShellFolder;

Almost every shell object has a context menu (which pops up when you right click on the shell object in the Windows Explorer). The following methods can show this context menu or alternatively execute a specific menu item of the context menu without showing it. In order to execute the default menu item you can enter an empty "item" string.

type TContextAlign = (caLeftTop,   caLeftCenter,  caLeftBottom,
                      caCenterTop, caCenter,      caCenterBottom,
                      caRightTop,  caRightCenter, caRightBottom);

function IShellObj.ShowContextMenu (parentWnd : cardinal;
                                    x         : integer       = -1;
                                    y         : integer       = -1;
                                    align     : TContextAlign = caLeftTop;
                                    explore   : boolean       = false    ) : boolean;

function IShellObj.ExecContextItem (parentWnd : cardinal;
                                    item      : string        = ''       ) : boolean;

// Examples:
with ShellObj(sfControlPanel) do begin
  ShowContextMenu(Application.Handle);  // shows the context menu of the control panel
  ExecContextItem(Application.Handle);  // opens the control panel in the Explorer

If you want to create a new shortCut/shellLink, which links to the current shell object, simply call the method "NewShortCut". You can enter a file name for the new shortCut/shellLink right away, or later when calling IShortCut.Save.

function IShellObj.NewShortCut (shortCutFileName: string = '') : IShortCut;

If the current shell object is a shortCut/shellLink (*.lnk or *.pif) file, you can use the method "LoadShortCut" to load it into a new IShortCut object.

function IShellObj.LoadShortCut : IShortCut;