?
Solved

PItemIdList To String & String To PItemIdList

Posted on 2003-03-16
14
Medium Priority
?
2,323 Views
Last Modified: 2007-12-19

   Hi again,

   I need to convert a PItemIdList to a string and, of course, I need to do the back conversion from string to PItemIdList also.

   Something like that :

function PItemIdListToString (pidl : PItemIdList) : string;
function StringToPItemIdList (str : string) : PItemIdList;

   Thanks
0
Comment
Question by:ivan_llanas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 3
  • +1
14 Comments
 
LVL 9

Expert Comment

by:mocarts
ID: 8151322
you mean ShellObj itemidlist?
in what format in string you need?
mo.
0
 

Author Comment

by:ivan_llanas
ID: 8152689

   Yes, the ShellObj.PItemIdList.

   Well, I would like to use the Windows' notation (if possible) :

::{208D2C60-3AEA-1069-A2D7-08002B30309D}

for "single" PILD's and

::{208D2C60-3AEA-1069-A2D7-08002B30309D}\::{02004700-6F54-6164-206C-612072656400}\::{666F736F....

for PIDL's with parents.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 8167253
Well, you could use my package madShell, which is free for non-commercial purpose.

http://help.madshi.net/madShell.htm

To convert a pidl into a path you can use "IDList(pidl).Path". The other way round works by using "ShellObj(path).IDList.Pidl".

Regards, Madshi.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:ivan_llanas
ID: 8168415

   madShell.dcu is more than 100 Kb and if this module uses madBasic routines, this makes about 200 additional Kb's to the executable to just convert PIDL's to strings.

   Anyway, if these functions are using ShellFolder.GetDisplayNameOf (aItemIdList, SHGDN_FORPARSING, aString), they do not work with PIDL's like "Microsoft Network", "Network neighborhood"... as they return an special name (like "EntireNetwork") or the icon title instead the PIDL converted to string. This makes impossible to "go" back to this PIDL just having this description string.

   There must be a way to store a PIDL and restore it later as Windows Explorer lets create a shortcut from any icon it displays.

   Ivan :(
0
 
LVL 20

Expert Comment

by:Madshi
ID: 8174634
>> they do not work with PIDL's like

madShell converts system PIDLs into "::{guid}" paths, it's exactly what you've asked for. You're right, though, madShell's footprint is quite big.

Regards, Madshi.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 8176867
hello ivan, you might try these 2 functions -


function GUIDToString(GUID1: TGUID): string;
var
Pwc: PWideChar;
begin
StringFromCLSID(GUID1, Pwc);
Result := WideCharToString(Pwc);
end;

function StringToGUID(IDstr: String): TGUID;
var
Pwc: PWideChar;
begin
Pwc := StringToOleStr(IDstr);
OleCheck(CLSIDFromString(Pwc, Result));
end;

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

var
ClsID1: TGUID;
begin
Label1.Caption := GUIDToString(IMalloc);
ClsID1 := StringToGUID(Label4.Caption);
Label2.Caption := GUIDToString(ClsID1);
end;
0
 

Author Comment

by:ivan_llanas
ID: 8180449

  This seems to almost be, but I don't have TGUID's; I have PItemIdList's, and I haven't found a way to convert them to TGUID or get a TGUID from a PItemIdList. Functions SHGetDataFromIDList has a "supicious" pointer-to-anything parameter...

var pp : TSHDescriptionID;

   SHGetDataFromIDList (Desktop, The_PIDL, SHGDFIL_DESCRIPTIONID, @pp, SizeOf(pp));
   TheString := GUIDToString (pp.Id);

but this hasn worked.
0
 

Author Comment

by:ivan_llanas
ID: 8196123

   The Control Panel GUID is ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D} and running this piece of code,
........................................
var pp : TSHDescriptionID;

   SHGetDataFromIDList (Desktop, ControlPanelItemIdList, SHGDFIL_DESCRIPTIONID, @pp, SizeOf(pp));

   result := GUIDToString (pp.Id);
........................................

the only thing I get is the first part:

{20D04FE0-3AEA-1069-A2D8-08002B30309D}

so, there must be a way to iterate the GUID or the PItemIdList to get the rest of the GUID-path...
0
 
LVL 34

Expert Comment

by:Slick812
ID: 8197588
I haven't had much time to work on this. . .  but I think the
SHGetDataFromIDList( ) might be for a single reference of the ItemList? ?, , , , since it has the   psf  parameter for the Parent folder. . . but I can't tell if you might use QueryInterface to get the rest of the list???, Here's a Thought - It seems you want to store the ItemList in a string, and then use that stored string to create that ItemList, Since you hve a pointer to the list you might just copy the Bytes from this pointer, into your own Pointer storage block and save that memory or save it to file. . . I have no Idea how the system may or may not have unique bytes for these ItemLists. . . but you would not need to convert them to strings
0
 

Author Comment

by:ivan_llanas
ID: 8197968

   Yes, SHGetDataFromIDList asks for a IShellFolder; may be the parent? May be, but if I use the real Parent IShellFolder I get a real strange string instead one of the portions of ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}. But if I use the Desktop IShellFolder I get the first portion of the string.

   Yes, the real matter is to store the ItemList and restore it previously. The conversion to string is not required (but I think it's somewhat "elegant", as long as a PItemIDList can be converted to a string like ::{nnn...}\::{n...}\::{nnn...). The real problem is to avoid creating manually a PItemIdList and fill it with a bunch of bytes. I have an object (TShellBrowser) with a published property (Folder). This folder is set using IShellFolder.ParseDisplayName, and this method "understands" this kind of strings I want to get.

   One reason more to get the PIDL's converted to strings is that they must be saved to the registry. Yes, the registry can host almost any data type, but you'll agree that strings is the most easy to manage, won't you?
0
 
LVL 34

Accepted Solution

by:
Slick812 earned 300 total points
ID: 8204247
??. .  well, in this case No. . . I have seen many Delphi programmers here do code that converts EVERYTHING into strings. .  I used to try and do that , , but now I use the variable type or Pointers to memory blocks. . . Anyway, I took some time to try and store Item Lists in the Registry, here's something that seems to work - -



procedure TForm1.sbut_SavePItemListClick(Sender: TObject);
var
pFontsIDL: PItemIDList;
ShellMalloc: IMalloc;
ListSize: Integer;
Reg1: TRegistry;
AryChar: Array[0..1024] of Char;
begin
if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
  begin
  SHGetSpecialFolderLocation(Form1.Handle, CSIDL_FONTS, pFontsIDL);
  SHGetPathFromIDList(pFontsIDL, @AryChar);
  try
    ListSize := ShellMalloc.GetSize(pFontsIDL);
    Reg1 := TRegistry.Create;
    try
      Reg1.RootKey := HKEY_CURRENT_USER;
      if Reg1.OpenKey('\Software\Tbear2u', False) then
        begin
        Reg1.WriteBinaryData('PList1', pFontsIDL^, ListSize);
        Reg1.CloseKey;
        end;
      finally
      Reg1.Free;
      end;
    finally
    ShellMalloc.Free(pFontsIDL);
    end;
  ShowMessage(IntToStr(ListSize)+' '+AryChar);
  end;
end;

procedure TForm1.sbut_LoadPListRegClick(Sender: TObject);
var
ShellMalloc: IMalloc;
ListSize: Integer;
Reg1: TRegistry;
pNewIDL: PItemIDList;
AryChar: Array[0..1024] of Char;
begin
ListSize := 0;
Reg1 := TRegistry.Create;
try
  Reg1.RootKey := HKEY_CURRENT_USER;
  if Reg1.OpenKey('\Software\Tbear2u', False) then
    begin
    ListSize := Reg1.GetDataSize('PList1');
    if ListSize > 4 then
      begin
      if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
        begin
        pNewIDL := ShellMalloc.Alloc(ListSize);
        try
          Reg1.ReadBinaryData('PList1', pNewIDL^, ListSize);
          SHGetPathFromIDList(pNewIDL, @AryChar);
          finally
          ShellMalloc.Free(pNewIDL);
          end;
        end;
      end;
    Reg1.CloseKey;
    end;
  finally
  Reg1.Free;
  end;
ShowMessage(IntToStr(ListSize)+' '+AryChar);
end;
0
 
LVL 20

Expert Comment

by:Madshi
ID: 8208578
One things that speaks pro strings in this case is that the pidl raw data will most probably not cross OS compatible, while the string representation might have better chances there.
0
 

Author Comment

by:ivan_llanas
ID: 8260439

   Sorry, I've been out for a while... It seems that recovering the whole PIDL in a single chunk works. Maybe it is not cross OS compatible, but in the same computer it does, so I'm not going to loose more time in this question... It would be nice using those "::{...}" strings but "my" "0xXXXXXXXXX..." strings are ok also. Thanks to everybody. Points fly to you, Slick812...
0
 
LVL 34

Expert Comment

by:Slick812
ID: 8266220
I don't think the ItemLists would be transferable from one Computer to another anyway (regardless of the OS), , , except maybe the PIDL's which are windows constants, most are based on the File paths
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses
Course of the Month11 days, 5 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question