Link to home
Start Free TrialLog in
Avatar of vladi44
vladi44

asked on

Getting the desktop icons?

Hello body!How can I get all the desktop icons and their labels and put them into a popup menu.And when we click on an item from the menu the associated file to be executed?Please HELP!!!
ASKER CERTIFIED SOLUTION
Avatar of b26
b26

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 inthe
inthe

here is the way to get the desktop directory
just add "shlobj" to the uses section:

procedure TForm1.Button1Click(Sender: TObject);
Var
  SFolder :  pItemIDList;
  SpecialPath : Array[0..MAX_PATH] Of Char;
begin
SHGetSpecialFolderLocation(Form1.Handle,CSIDL_DESKTOPDIRECTORY, SFolder);
SHGetPathFromIDList(SFolder, SpecialPath);
Label1.Caption := StrPas(SpecialPath);
end;

Regards Barry
Hi Barry,

you've forgotten to free the pItemIDList - you *MUST* do that!!!

procedure FreeIDList(var idList: PItemIDList);
var malloc : IMalloc;
begin
  if (idList<>nil) and (SHGetMalloc(malloc)<>NOERROR) then begin
    malloc.Free(idList);
    idList:=nil;
  end;
end;

vladi44,

b26's suggestion shows you all the files and directories of the desktop, but *NOT* the system symbols like "My Computer" or "Recycle Bin" or "Internet Explorer" or ...
I hope, you don't need these system symbols. Look into the c:\windows\desktop folder. If there's everything you need, then b26's solution should work for you.

Regards, Madshi.
Madshi,

Yes you are rigt about that. About getting the folder location you can do that too but like this you deal with some ole stuff... :O)


Regards,
B.
Check http://www.pcmag.com and download Win Tidy 95 (source code included). This is very useful for handling desktop icons.

Regards,
B
about 6 months ago i seen full source on a newsgroup to put all desktop icons in a menu.can i find it know.... :-( no...
Free();
Avatar of vladi44

ASKER

Thanks to everyone who helped me and who didn't!
Avatar of vladi44

ASKER

Hey b26,you helped me a lot!Thanks!What's your e-mail?
Avatar of vladi44

ASKER

Look guys your source works but not in the way I want.I mean that the *lnk must have icon and the name must be the label of the file not its' name.And on the other hand all of this should be in a popup - it's maybe the hardest thing to do so - if you e-mail me at vd@bitex.com i'll send you the sample which I ask you to improve.
Avatar of vladi44

ASKER

Hey inthe would you remind where have you seen that sample?Please!
sorry but it was on www.dejanews.com but i have searched dejanews everywhere and cant find it now. i tried when you asked the question but couldnt find it.i would suggest looking around dejanews for info on getting information out of .lnk files ,unless someone else reading this knows how to do it.
here is a unit i had wrote by Ken White.you can use functions from it to get info from .lnk files.
Regards Barry

unit ShelStuff;

{
This unit is loosely based on the article in Delphi Developer's Journal .I found out it did not work under Delphi 3, even though the article said it did... Took a couple hours to figure out what the problem was; now this one does not work under Delphi 2.01, but will work under Delphi 3.

To use this example, select a file using the Link To... button, or type in something like "TEMP.TXT" in the open file dialog.  Clicking on the Desktop button will create a shortcut on the desktop; the Programs button will create a shortcut on the Start|Programs menu; and the Start button
will create it on the Start menu.

The Resolve It button answers your specific question about finding out
info on a particular shortcut; the code is in TForm1.ReadNotePadLink.

To test the Resolve It button, you'll need to go to the end of the file
and change the filename that's used in the TForm1.Button5Click method;
I hard-coded in the path to a shortcut I have on the desktop to the
Windows calculator... Enter a filename that's valid on your machine,
then click Resolve It; you'll see the path, working directory, and
command line arguments in the Memo control.

Hope this helps!  See the notes below on what the difference was between
Delphi 2 & 3...

Ken
}
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ShlObj, ComObj, StdCtrls, ActiveX;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Label1: TLabel;
    OpenDialog1: TOpenDialog;
    Edit1: TEdit;
    Label2: TLabel;
    Memo1: TMemo;
    Button5: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
  private
    { Private declarations }
    procedure MakeNotePadLink(Location: Word);
    procedure ReadNotePadLink(sFileName: String);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure CreateShellLink( sDesc, sLinkToFileName, sStartIn,
    sArguments, sIconPath, sLinkName: String; iIconIndex: Integer);
var
   sl : IShellLink;
   ppf : IPersistFile;
   wcLinkName : array[0..Max_Path] of WideChar;
begin
   OleCheck(CoInitialize(nil));

   {
     Original code used IID_IShellLink; Delphi 3 wouldn't resolve
     this.  Digging around in the source found IID_IShellLinkA and
     IID_IShellLinkW...
   }
   OleCheck(CoCreateInstance(CLSID_ShellLink, nil,
           CLSCTX_INPROC_SERVER, IID_IShellLinkA, sl));

   {
     The original code used
         sl.QueryInterface(IID_IPersistFile, ppf);
     This bombed under Delphi 3... Also, I had to add
     ActiveX to the uses clause in order to find anything
     like IID_ShellLinkA or IPersistFile.
   }
   OleCheck(sl.QueryInterface(IPersistFile, ppf));
   {
   OleCheck(sl.SetDescription('Test link creation'));
   }
   OleCheck(sl.SetPath(Pchar(sLinkToFileName)));
   OleCheck(sl.SetWorkingDirectory(PChar(sStartIn)));
   OleCheck(sl.SetArguments(PChar(sArguments)));
   OleCheck(sl.SetIconLocation(Pchar(sIconPath), iIconIndex));

   MultiByteToWideChar(CP_ACP, 0, PChar(sLinkName), -1, wcLinkName, Max_Path);
   OleCheck(ppf.Save(wcLinkName, true));
   CoUninitialize;
end;

procedure TForm1.ReadNotePadLink( sFileName: String );
var
   sl : IShellLink;
   ppf : IPersistFile;
   wcLinkName : array[0..Max_Path] of WideChar;
   sPath, sDir, sArgs, sDesc : String;
   wf: TWin32FindData;
begin
   SetLength(sDesc, MAX_PATH);
   SetLength(sPath, MAX_PATH);
   SetLength(sDir, MAX_PATH);
   SetLength(sArgs, MAX_PATH);
   OleCheck(CoInitialize(nil));

   OleCheck(CoCreateInstance(CLSID_ShellLink, nil,
           CLSCTX_INPROC_SERVER, IID_IShellLinkA, sl));

   OleCheck(sl.QueryInterface(IPersistFile, ppf));

   MultiByteToWideChar(CP_ACP, 0, PChar(sFileName), -1, wcLinkName, Max_Path);

   OleCheck(ppf.Load(wcLinkName, STGM_READ));

   OleCheck(sl.GetPath(PChar(sPath), Max_Path, wf, SLR_ANY_MATCH));
   OleCheck(sl.GetDescription(PChar(sDesc), Max_Path));
   OleCheck(sl.GetWorkingDirectory(PChar(sDir), Max_Path));
   OleCheck(sl.GetArguments(PChar(sArgs), Max_Path));
   with Form1.Memo1.Lines do begin
      Add('Description: ' + sDesc);
      Add('Path       : ' + sPath);
      Add('Directory  : ' + sDir);
      Add('Arguments  : ' + sArgs);
   end;

   CoUninitialize;
end;

procedure GetFolderPath( var sPath: String; iFolder: Integer);
var
   iID: PItemIDList;
   szPath: PChar;
begin
     szPath := StrAlloc(Max_Path);
     if (SHGetSpecialFolderLocation(Application.Handle, iFolder, iID) = NOERROR) then
     begin
          SHGetPathFromIDList(iID, szPath);
          sPath := szPath;
     end;
     StrDispose(szPath);
end;

procedure TForm1.MakeNotePadLink(Location: Word);
var
   sDeskTopPath, sLinkPath: String;
begin
     GetFolderPath( sDeskTopPath, Location);
     sLinkPath := sDeskTopPath + '\' +
               ExtractFileName(OpenDialog1.FileName) + '.lnk';
     CreateShellLink('', OpenDialog1.FileName,
               ExtractFilePath(OpenDialog1.FileName),
               Edit1.Text, OpenDialog1.FileName,
               sLinkPath, 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
     MakeNotePadLink(CSIDL_DESKTOP);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
     MakeNotePadLink(CSIDL_Programs);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
     MakeNotePadLink(CSIDL_STARTMENU);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
     if OpenDialog1.Execute then
        Label1.Caption := OpenDialog1.FileName
     else
         OpenDialog1.FileName := '';
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
     ReadNotePadLink('C:\WINDOWS\Desktop\Windows Calculator.lnk');
end;

end.
Hi Barry,

it's again the same mistake as every year: The ItemIDList returned from SHGetSpecialFolderLocation is not freed in these sources!!!

And the sources don't use all the Delphi advantages. E.g. you could shorten the CreateShellLink function like this:

procedure CreateShellLink( sDesc, sLinkToFileName, sStartIn,
    sArguments, sIconPath, sLinkName: String; iIconIndex: Integer);
var sl : IShellLink;
begin
   OleCheck(CoInitialize(nil));
   sl:=CreateComObject(CLSID_ShellLink) as IShellLink;
   OleCheck(sl.SetDescription('Test link creation'));
   OleCheck(sl.SetPath(Pchar(sLinkToFileName)));
   OleCheck(sl.SetWorkingDirectory(PChar(sStartIn)));
   OleCheck(sl.SetArguments(PChar(sArguments)));
   OleCheck(sl.SetIconLocation(Pchar(sIconPath), iIconIndex));
   OleCheck((sl as IPersistFile).Save(pWideChar(wideString(wcLinkName)),true));
   CoUninitialize;
end;

Note, that

(1) CreateComObject is much easier than CoCreateInstance
(2) "Int1 as Int2" is much easier than "Int1.QueryInterface(IID_Int2,Int2)", especially since you don't need IID_XXX anymore at all
(3) Delphi converts the string into PWideChar for us

BTW, Barry, perhaps you might want to look in the winObj unit I've sent you. There's a complete object encapsulation of IShellLink in it, which compiles/runs perfectly under D3&4...   :-)))

Regards, Madshi.
but i didnt write it ken white (clipper functions) did.
perhaps he has same problem with freeing as me  ;-)

i seen your winobj bit on ishell... but as i simply already had a project unit from ken that i once answered a question with before  that i posted it so vladdi could put the buttons on a form etc and see what to do.i admit i never actually read the code i posted cause i in a hurry.
between you and viktor i get told off every day,and i cant break tradition now can i...hehe
 
from now on i going to free everything i promise   :-)
see ya
Barry
Thank you guys!I want to ask you a question - which of you have Delphi 4.0?Please write as soon as possible because I have a great idea!My e-mail is : vd@bitex.com.
Vladi, I've Delphi 4.0. Why are you asking? My eMail is "madshi@gmx.net".

Barry, didn't mean to tell you off - just wanted to boast with my knowledge.   :-)))
Ok, to be serious, I'm not too lucky when I see code that doesn't use Delphi's advantages, because if the people see such code, they think: Well, VB handles that better and VC code is not worse than that. So I keep telling how wonderful Delphi is and how short/good really Delphi optimized code can look...
I mean there are so many people out there that use MultiByteToWideChar and such stuff. That's really sad. Delphi makes it so easy...

Regards, Madshi.