(This seriesArticleOriginal by lemon (lc_mtt), reprinted please indicate the source, thank you ~)
Pidl
Pidl also has the concepts of "absolute path" and "relative path. Pidl indicating the "relative path" (referred to as "relative pidl" in this article) has only one itemidlist structure element to identify the "path" relative to the parent folder "; pidl indicating "absolute path" (referred to as "absolute pidl") has several itemidlist elements. The first element indicates the root folder of the shell namespace ("desktop ") A sub-folder a under, the second element indicates a sub-Folder B under folder A, and other such push. In this way, absolute pidl will save an absolute pidl from a direct sub-folder or file under "desktop", which is the same as that of pidl, the relative pidl of other folders or files is only the last part of the absolute pidl.
Why? Because some functions must use absolute pidl, sample labels. If absolute pidl is not used, some icons cannot be obtained normally (drive, control panel, etc ).
But what we get with enumobjects is relative to pidl. What if we get absolute pidl through relative pidl? I have referenced the pidl class in the open-source project C # filebrowser.
Pidl. CS
Using system;
Using system. Collections. Generic;
Using system. text;
Using system. collections;
Using system. runtime. interopservices;
Namespace winshell
{
Public class pidl
{
Private intptr pidl = intptr. zero;
Public pidl (intptr pidl, bool clone)
{
If (clone)
This. pidl = ilclone (pidl );
Else
This. pidl = pidl;
}
Public pidl (pidl, bool clone)
{
If (clone)
This. pidl = ilclone (pidl. PTR );
Else
This. pidl = pidl. PTR;
}
Public intptr PTR
{
Get {return pidl ;}
}
Public void insert (intptr insertpidl)
{
Intptr newpidl = ilcombine (insertpidl, pidl );
Marshal. freecotaskmem (pidl );
Pidl = newpidl;
}
Public void free ()
{
If (pidl! = Intptr. Zero)
{
Marshal. freecotaskmem (pidl );
Pidl = intptr. zero;
}
}
Private Static int itemidsize (intptr pidl)
{
If (! Pidl. Equals (intptr. Zero ))
{
Byte [] buffer = new byte [2];
Marshal. Copy (pidl, buffer, 0, 2 );
Return buffer [1] * 256 + buffer [0];
}
Else
Return 0;
}
Private Static int itemidlistsize (intptr pidl)
{
If (pidl. Equals (intptr. Zero ))
Return 0;
Else
{
Int size = itemidsize (pidl );
Int nextsize = marshal. readbyte (pidl, size) + (marshal. readbyte (pidl, size + 1) * 256 );
While (nextsize> 0)
{
Size + = nextsize;
Nextsize = marshal. readbyte (pidl, size) + (marshal. readbyte (pidl, size + 1) * 256 );
}
Return size;
}
}
Public static intptr ilclone (intptr pidl)
{
Int size = itemidlistsize (pidl );
Byte [] bytes = new byte [size + 2];
Marshal. Copy (pidl, bytes, 0, size );
Intptr newpidl = marshal. alloccotaskmem (size + 2 );
Marshal. Copy (bytes, 0, newpidl, size + 2 );
Return newpidl;
}
Public static intptr ilcombine (intptr pidl1, intptr pidl2)
{
Int size1 = itemidlistsize (pidl1 );
Int size2 = itemidlistsize (pidl2 );
Intptr newpidl = marshal. alloccotaskmem (size1 + size2 + 2 );
Byte [] bytes = new byte [size1 + size2 + 2];
Marshal. Copy (pidl1, bytes, 0, size1 );
Marshal. Copy (pidl2, bytes, size1, size2 );
Marshal. Copy (bytes, 0, newpidl, bytes. Length );
Return newpidl;
}
}
}
This class implements the copy and Integration Functions of pidl. Now we modify the shellitem class so that it has the ishellfolder of the parent node and provides the attributes for getting absolute pidl:
Private shellitem m_parentitem;
Public shellitem parentitem
{
Get {return m_parentitem ;}
Set {m_parentitem = value ;}
}
/** // <Summary>
/// Absolute pidl
/// </Summary>
Public pidl pidlfull
{
Get
{
Pidl pidlfull = new pidl (pidl, true );
Shellitem current = parentitem;
While (current! = NULL)
{
Pidlfull. insert (current. pidl );
Current = current. parentitem;
}
Return pidlfull;
}
}
Get icon
Now that we have obtained the absolute pidl, it is very easy to get the icon. We use the shgetfileinfo API:
[Dllimport ("shell32", entrypoint = "shgetfileinfo", exactspelling = false,
Charset = charset. Auto, setlasterror = true)]
Public static extern intptr shgetfileinfo (
Intptr ppidl,
File_attribute dwfileattributes,
Ref shfileinfo SFI,
Int cbfileinfo,
Shgfi uflags );
[Dllimport ("shell32.dll", charset = charset. Auto)]
Public static extern intptr shgetfileinfo (
String path,
File_attribute fileattributes,
Out shfileinfo SFI,
Int cbfileinfo, shgfi flags );
Here we provide an overload. You can choose whether to use pidl or the path to get the icon (if it is a path, you can only get the folder/file icon ).
/** //
// obtain the small icon index
///
Public static int getsmalliconindex (string strfilename)
{< br> shfileinfo psfi = new shfileinfo ();
intptr ipicon = shgetfileinfo (strfilename, 0, out psfi, Marshal. sizeof (psfi),
shgfi. icon | shgfi. smallicon | shgfi. sysiconindex);
return psfi. iicon;
}< br>
Public static int getsmalliconindex (intptr ipidlist)
{< br> shfileinfo psfi = new shfileinfo ();
intptr ipicon = shgetfileinfo (ipidlist, 0, ref psfi, Marshal. sizeof (psfi),
shgfi. icon | shgfi. pidl | shgfi. smallicon | shgfi. sysiconindex);
return psfi. iicon;
}
You may wonder how to use the int returned by getsmalliconindex?
Actually, it is true that getsmalliconindex only returns the index of the icon in the system image list (system imagelist. We only need to get the pointer of the system image list and associate it with your Treeview or listview. Then we can display the icon through the icon index.
Intptr m_ipsmallsystemimagelist;
Intptr m_iplargesystemimagelist;
// Obtain the system imagelist
Shfileinfo shfi = new shfileinfo ();
M_ipsmallsystemimagelist = API. shgetfileinfo ("", 0, out shfi, Marshal. sizeof (typeof (shfileinfo )),
Shgfi. sysiconindex | shgfi. smallicon | shgfi. usefileattributes );
M_iplargesystemimagelist = API. shgetfileinfo ("", 0, out shfi, Marshal. sizeof (typeof (shfileinfo )),
Shgfi. sysiconindex | shgfi. largeicon | shgfi. usefileattributes );
// Associate the system imagelist with Treeview and listview.
Api. sendmessage (tree1.handle, Api. tvm_setimagelist, Api. tvsil_normal, m_ipsmallsystemimagelist );
Api. sendmessage (lvfile. Handle, Api. lvm_setimagelist, Api. lvsil_normal, m_iplargesystemimagelist );
OK. We can modify the previous example to display the icon on the tree node:
Shellitem = new shellitem (pidlsub, isub, sitem );
Int imgindex = API. getsmalliconindex (shellitem. pidlfull. PTR );
Treenode nodesub = new treenode (name, imgindex, imgindex );
(Note: For some struct or constants in the text, you can refer to msdn on your own. If you have limited energy, you cannot describe them one by one .)
Let's take a look at the effect:
In fact, thisCodeA lot of changes are involved in the next section, so the code will be thrown out in the next section...