Jump to content
Mark Billig

Desktop Icons

Recommended Posts

I am looking to get a list of desktop icons with their descriptions and positions.  Any help appreciated.

Share this post


Link to post
12 hours ago, Remy Lebeau said:

Raymond Chen's blog article on Manipulating the positions of desktop icons includes code "to enumerate all the desktop icons and print their names and locations."

Thank you for your post.  My problem is understanding C to convert and fully understand what needs to be done.

Share this post


Link to post
On 4/22/2024 at 7:30 AM, Mark Billig said:

My problem is understanding C to convert and fully understand what needs to be done.

The post Remy linked shows you what API will let you accomplish your task. Going further is basically asking someone to write the code for you or teach you C. Maybe someone will want to do that (I am not saying there is anything wrong with asking for it), but you may get faster results asking a chat AI to convert it for you. You'll have to fix bugs in it for sure, but it could probably get you Delphi-ish code that is easier to work with for you.

Share this post


Link to post
1 minute ago, Brandon Staggs said:

...but you may get faster results asking a chat AI to convert it for you.

I did that a few days ago out of curiosity. I did it a function at a time so it needs work to make it workable.

procedure FindDesktopFolderView(riid: TGUID; var ppv: Pointer);
var
  spShellWindows: IShellWindows;
  vtLoc: OleVariant;
  vtEmpty: OleVariant;
  lhwnd: LongInt;
  spdisp: IDispatch;
  spBrowser: IShellBrowser;
  spView: IShellView;
begin
  spShellWindows := CoShellWindows.Create;
  vtLoc := CSIDL_DESKTOP;
  vtEmpty := VarEmpty;
  spShellWindows.FindWindowSW(vtLoc, vtEmpty, SWC_DESKTOP, lhwnd, SWFO_NEEDDISPATCH, spdisp);
  spBrowser := (spdisp as IServiceProvider).QueryService(SID_STopLevelBrowser, IShellBrowser) as IShellBrowser;
  spBrowser.QueryActiveShellView(spView);
  spView.QueryInterface(riid, ppv);
end;

-----------------

program DesktopFolderView;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  ActiveX,
  ComObj,
  ShlObj,
  ShellAPI;

// CCoInitialize incorporated by reference

function wmain(argc: Integer; argv: PWideChar): Integer;
var
  init: IUnknown; // Equivalent to CCoInitialize
  spView: IFolderView;
  spFolder: IShellFolder;
  spEnum: IEnumIDList;
  spidl: PItemIDList;
  str: TStrRet;
  spszName: PWideChar;
  pt: TPoint;
begin
  init := CreateComObject(CLSID_CoInitialize);
  FindDesktopFolderView(IID_IFolderView, spView);
  spView.GetFolder(IID_IShellFolder, spFolder);

  spView.Items(SVGIO_ALLVIEW, IID_IEnumIDList, spEnum);
  while spEnum.Next(1, spidl, nil) = S_OK do
  begin
    spFolder.GetDisplayNameOf(spidl, SHGDN_NORMAL, str);
    StrRetToStr(@str, spidl, spszName);

    spView.GetItemPosition(spidl, pt);
    Writeln(Format('At %4d,%4d is %s', [pt.x, pt.y, WideString(spszName)]));
    CoTaskMemFree(spidl);
  end;
  Result := 0;
end;

begin
  try
    CoInitialize(nil);
    wmain(ParamCount, PWideChar(ParamStr(0)));
    CoUninitialize;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
---------------------------
program DesktopFolderRandomPosition;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  ActiveX,
  ComObj,
  ShlObj,
  ShellAPI,
  Windows;

function wmain(argc: Integer; argv: PWideChar): Integer;
var
  init: IUnknown; // Equivalent to CCoInitialize
  spView: IFolderView;
  spEnum: IEnumIDList;
  spidl: PItemIDList;
  pt: TPoint;
  apidl: array[0..0] of PItemIDList;
begin
  init := CreateComObject(CLSID_CoInitialize);
  FindDesktopFolderView(IID_IFolderView, spView);

  spView.Items(SVGIO_ALLVIEW, IID_IEnumIDList, spEnum);
  while spEnum.Next(1, spidl, nil) = S_OK do
  begin
    spView.GetItemPosition(spidl, pt);
    pt.x := pt.x + (Random(5) - 2);
    pt.y := pt.y + (Random(5) - 2);

    apidl[0] := spidl;
    spView.SelectAndPositionItems(1, @apidl[0], @pt, SVSI_POSITIONITEM);
    CoTaskMemFree(spidl);
  end;
  Result := 0;
end;

begin
  try
    CoInitialize(nil);
    Randomize; // Initialize random number generator
    wmain(ParamCount, PWideChar(ParamStr(0)));
    CoUninitialize;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
------------------------------------
procedure SavePositions(pView: IFolderView; pszFile: PWideChar);
var
  spStream: IStream;
  spEnum: IEnumIDList;
  spidl: PItemIDList;
  pt: TPoint;
begin
  SHCreateStreamOnFileEx(pszFile, STGM_CREATE or STGM_WRITE,
    FILE_ATTRIBUTE_NORMAL, True, nil, spStream);
  pView.Items(SVGIO_ALLVIEW, IID_IEnumIDList, spEnum);
  while spEnum.Next(1, spidl, nil) = S_OK do
  begin
    WritePidlToStream(spStream, spidl); // Custom function to write PIDL to stream
    pView.GetItemPosition(spidl, pt);
    WritePointToStream(spStream, pt); // Custom function to write POINT to stream
    ILFree(spidl); // Free the PIDL
  end;
end;

-----------------------------------
procedure RestorePositions(pView: IFolderView; pszFile: PWideChar);
var
  spStream: IStream;
  spidl: PItemIDList;
  pt: TPoint;
  apidl: array[0..0] of PItemIDList;
begin
  // Create a file stream
  SHCreateStreamOnFileEx(pszFile, STGM_READ, FILE_ATTRIBUTE_NORMAL, False, nil, spStream);
  // Read PIDLs and their positions from the stream and restore them
  while Succeeded(IStream_ReadPidl(spStream, spidl)) and
        Succeeded(spStream.Read(@pt, SizeOf(pt), nil)) do
  begin
    apidl[0] := spidl;
    pView.SelectAndPositionItems(1, @apidl[0], @pt, SVSI_POSITIONITEM);
    CoTaskMemFree(spidl); // Free the PIDL
  end;
end;

// Note: IStream_ReadPidl is a placeholder for the actual function you would use to read a PIDL from a stream.
// You will need to implement this functionality in Delphi, as it is not provided by Delphi's standard libraries.

 

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×