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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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)<>NOER ROR) 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.
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)<>NOER
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.
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
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();
Free();
ASKER
Thanks to everyone who helped me and who didn't!
ASKER
Hey b26,you helped me a lot!Thanks!What's your e-mail?
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.
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_Shel lLink, nil,
CLSCTX_INPROC_SERVER, IID_IShellLinkA, sl));
{
The original code used
sl.QueryInterface(IID_IPer sistFile, 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 (IPersistF ile, ppf));
{
OleCheck(sl.SetDescription ('Test link creation'));
}
OleCheck(sl.SetPath(Pchar( sLinkToFil eName)));
OleCheck(sl.SetWorkingDire ctory(PCha r(sStartIn )));
OleCheck(sl.SetArguments(P Char(sArgu ments)));
OleCheck(sl.SetIconLocatio n(Pchar(sI conPath), iIconIndex));
MultiByteToWideChar(CP_ACP , 0, PChar(sLinkName), -1, wcLinkName, Max_Path);
OleCheck(ppf.Save(wcLinkNa me, 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_Shel lLink, nil,
CLSCTX_INPROC_SERVER, IID_IShellLinkA, sl));
OleCheck(sl.QueryInterface (IPersistF ile, ppf));
MultiByteToWideChar(CP_ACP , 0, PChar(sFileName), -1, wcLinkName, Max_Path);
OleCheck(ppf.Load(wcLinkNa me, STGM_READ));
OleCheck(sl.GetPath(PChar( sPath), Max_Path, wf, SLR_ANY_MATCH));
OleCheck(sl.GetDescription (PChar(sDe sc), Max_Path));
OleCheck(sl.GetWorkingDire ctory(PCha r(sDir), Max_Path));
OleCheck(sl.GetArguments(P Char(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 (SHGetSpecialFolderLocatio n(Applicat ion.Handle , iFolder, iID) = NOERROR) then
begin
SHGetPathFromIDList(iID, szPath);
sPath := szPath;
end;
StrDispose(szPath);
end;
procedure TForm1.MakeNotePadLink(Loc ation: Word);
var
sDeskTopPath, sLinkPath: String;
begin
GetFolderPath( sDeskTopPath, Location);
sLinkPath := sDeskTopPath + '\' +
ExtractFileName(OpenDialog 1.FileName ) + '.lnk';
CreateShellLink('', OpenDialog1.FileName,
ExtractFilePath(OpenDialog 1.FileName ),
Edit1.Text, OpenDialog1.FileName,
sLinkPath, 0);
end;
procedure TForm1.Button1Click(Sender : TObject);
begin
MakeNotePadLink(CSIDL_DESK TOP);
end;
procedure TForm1.Button2Click(Sender : TObject);
begin
MakeNotePadLink(CSIDL_Prog rams);
end;
procedure TForm1.Button3Click(Sender : TObject);
begin
MakeNotePadLink(CSIDL_STAR TMENU);
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:\WINDOW S\Desktop\ Windows Calculator.lnk');
end;
end.
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:
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(
CLSCTX_INPROC_SERVER, IID_IShellLinkA, sl));
{
The original code used
sl.QueryInterface(IID_IPer
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
{
OleCheck(sl.SetDescription
}
OleCheck(sl.SetPath(Pchar(
OleCheck(sl.SetWorkingDire
OleCheck(sl.SetArguments(P
OleCheck(sl.SetIconLocatio
MultiByteToWideChar(CP_ACP
OleCheck(ppf.Save(wcLinkNa
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(
CLSCTX_INPROC_SERVER, IID_IShellLinkA, sl));
OleCheck(sl.QueryInterface
MultiByteToWideChar(CP_ACP
OleCheck(ppf.Load(wcLinkNa
OleCheck(sl.GetPath(PChar(
OleCheck(sl.GetDescription
OleCheck(sl.GetWorkingDire
OleCheck(sl.GetArguments(P
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 (SHGetSpecialFolderLocatio
begin
SHGetPathFromIDList(iID, szPath);
sPath := szPath;
end;
StrDispose(szPath);
end;
procedure TForm1.MakeNotePadLink(Loc
var
sDeskTopPath, sLinkPath: String;
begin
GetFolderPath( sDeskTopPath, Location);
sLinkPath := sDeskTopPath + '\' +
ExtractFileName(OpenDialog
CreateShellLink('', OpenDialog1.FileName,
ExtractFilePath(OpenDialog
Edit1.Text, OpenDialog1.FileName,
sLinkPath, 0);
end;
procedure TForm1.Button1Click(Sender
begin
MakeNotePadLink(CSIDL_DESK
end;
procedure TForm1.Button2Click(Sender
begin
MakeNotePadLink(CSIDL_Prog
end;
procedure TForm1.Button3Click(Sender
begin
MakeNotePadLink(CSIDL_STAR
end;
procedure TForm1.Button4Click(Sender
begin
if OpenDialog1.Execute then
Label1.Caption := OpenDialog1.FileName
else
OpenDialog1.FileName := '';
end;
procedure TForm1.Button5Click(Sender
begin
ReadNotePadLink('C:\WINDOW
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( sLinkToFil eName)));
OleCheck(sl.SetWorkingDire ctory(PCha r(sStartIn )));
OleCheck(sl.SetArguments(P Char(sArgu ments)));
OleCheck(sl.SetIconLocatio n(Pchar(sI conPath), iIconIndex));
OleCheck((sl as IPersistFile).Save(pWideCh ar(wideStr ing(wcLink Name)),tru e));
CoUninitialize;
end;
Note, that
(1) CreateComObject is much easier than CoCreateInstance
(2) "Int1 as Int2" is much easier than "Int1.QueryInterface(IID_I nt2,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.
it's again the same mistake as every year: The ItemIDList returned from SHGetSpecialFolderLocation
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_
OleCheck(sl.SetDescription
OleCheck(sl.SetPath(Pchar(
OleCheck(sl.SetWorkingDire
OleCheck(sl.SetArguments(P
OleCheck(sl.SetIconLocatio
OleCheck((sl as IPersistFile).Save(pWideCh
CoUninitialize;
end;
Note, that
(1) CreateComObject is much easier than CoCreateInstance
(2) "Int1 as Int2" is much easier than "Int1.QueryInterface(IID_I
(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
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.
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.
just add "shlobj" to the uses section:
procedure TForm1.Button1Click(Sender
Var
SFolder : pItemIDList;
SpecialPath : Array[0..MAX_PATH] Of Char;
begin
SHGetSpecialFolderLocation
SHGetPathFromIDList(SFolde
Label1.Caption := StrPas(SpecialPath);
end;
Regards Barry