|
I'd love to be able to convert, or access the system image list, but my (albeit feeble) efforts to do so have lead nowhere - I wonder if there's any shell guru's out there who want to take on the challenge?
As for your file list view, for now all I can do is give you this piece of code which caches icons by their path into a hashtable. You will probably want to change this to work by file extension rather than path, and add some checks for extensions that have unique icons such as .exe and .lnk
Hope this helps!
<br />
using System;<br />
using System.Collections;<br />
using System.Runtime.InteropServices;<br />
using System.Drawing;<br />
using System.Windows.Forms;<br />
<br />
#region ExtractIcons Class<br />
<br />
public class ExtractIcons<br />
{<br />
private Hashtable shellIcons;<br />
private Hashtable fileIcons;<br />
<br />
#region Constructor<br />
<br />
public ExtractIcons()<br />
{<br />
shellIcons = new Hashtable();<br />
fileIcons = new Hashtable();<br />
}<br />
<br />
#endregion<br />
<br />
#region Structs & Enum<br />
<br />
[StructLayout(LayoutKind.Sequential)]<br />
private struct SHFILEINFO<br />
{<br />
public SHFILEINFO(bool b)<br />
{<br />
hIcon=IntPtr.Zero;iIcon=0;dwAttributes=0;szDisplayName="";szTypeName="";<br />
}<br />
public IntPtr hIcon;<br />
public int iIcon;<br />
public uint dwAttributes;<br />
[MarshalAs(UnmanagedType.LPStr, SizeConst=260)]<br />
public string szDisplayName;<br />
[MarshalAs(UnmanagedType.LPStr, SizeConst=80)]<br />
public string szTypeName;<br />
};<br />
<br />
private enum SHGFI<br />
{<br />
SHGFI_ICON = 0x000000100,
SHGFI_DISPLAYNAME = 0x000000200,
SHGFI_TYPENAME = 0x000000400,
SHGFI_ATTRIBUTES = 0x000000800,
SHGFI_ICONLOCATION = 0x000001000,
SHGFI_EXETYPE = 0x000002000,
SHGFI_SYSICONINDEX = 0x000004000,
SHGFI_LINKOVERLAY = 0x000008000,
SHGFI_SELECTED = 0x000010000,
SHGFI_ATTR_SPECIFIED = 0x000020000,
SHGFI_LARGEICON = 0x000000000,
SHGFI_SMALLICON = 0x000000001,
SHGFI_OPENICON = 0x000000002,
SHGFI_SHELLICONSIZE = 0x000000004,
SHGFI_PIDL = 0x000000008,
SHGFI_USEFILEATTRIBUTES = 0x000000010
}<br />
<br />
#endregion<br />
<br />
#region Get File / Folder Icons<br />
<br />
<br />
[DllImport("Shell32.dll")]<br />
private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, <br />
out SHFILEINFO psfi, uint cbfileInfo, SHGFI uFlags );<br />
<br />
public int GetIcon(string strPath, bool large, bool selected, ImageList imageList)<br />
{<br />
if(fileIcons.ContainsKey(strPath + large.ToString()))<br />
{<br />
imageList.Images.Add((Icon)fileIcons[strPath + large.ToString()]);<br />
return imageList.Images.Count - 1;<br />
}<br />
else<br />
{<br />
try<br />
{<br />
SHFILEINFO info = new SHFILEINFO(true);<br />
int cbFileInfo = Marshal.SizeOf(info);<br />
SHGFI flags;<br />
if(large)<br />
{<br />
if (!selected)<br />
flags = SHGFI.SHGFI_ICON|SHGFI.SHGFI_LARGEICON;<br />
else<br />
flags = SHGFI.SHGFI_ICON|SHGFI.SHGFI_LARGEICON|SHGFI.SHGFI_OPENICON;<br />
}<br />
else<br />
{<br />
if (!selected)<br />
flags = SHGFI.SHGFI_ICON|SHGFI.SHGFI_SMALLICON;<br />
else<br />
flags = SHGFI.SHGFI_ICON|SHGFI.SHGFI_SMALLICON|SHGFI.SHGFI_OPENICON;<br />
}<br />
<br />
SHGetFileInfo(strPath, 256, out info,(uint)cbFileInfo, flags);<br />
<br />
Icon icn;<br />
icn = (Icon)Icon.FromHandle(info.hIcon).Clone();<br />
User32.DestroyIcon( info.hIcon ); <br />
<br />
fileIcons.Add(strPath + large.ToString(), icn);<br />
<br />
imageList.Images.Add(icn);<br />
return imageList.Images.Count - 1;<br />
}<br />
catch<br />
{<br />
return -1;<br />
}<br />
}<br />
}<br />
<br />
#endregion<br />
<br />
#region Get Specific Shell Icon<br />
<br />
<br />
[DllImport("Shell32.dll", CharSet=CharSet.Auto)]<br />
private static extern int ExtractIconEx(<br />
string lpszFile, int nIconIndex, IntPtr[] phiconLarge, IntPtr[] phiconSmall, int nIcons );<br />
<br />
public Icon GetShellIcon(int iconIndex)<br />
{<br />
if(shellIcons.ContainsKey(iconIndex))<br />
{<br />
return (Icon)shellIcons[iconIndex];<br />
}<br />
else<br />
{<br />
Icon icn;<br />
IntPtr[] handlesIconLarge = new IntPtr[1];<br />
IntPtr[] handlesIconSmall = new IntPtr[1];<br />
int i = ExtractIconEx(Environment.SystemDirectory + "\\shell32.dll", iconIndex, <br />
handlesIconLarge, handlesIconSmall, 1);<br />
if(handlesIconSmall.Length > 0 && handlesIconSmall[0] != IntPtr.Zero)<br />
{<br />
icn = (Icon)Icon.FromHandle(handlesIconSmall[0]).Clone();<br />
User32.DestroyIcon( handlesIconSmall[0] ); <br />
}<br />
else<br />
{<br />
icn = null;<br />
}<br />
shellIcons.Add(iconIndex, icn);<br />
return icn;<br />
}<br />
}<br />
<br />
#endregion<br />
<br />
}<br />
<br />
#region Destroy Icon<br />
public class User32<br />
{<br />
[DllImport("User32.dll")]<br />
public static extern int DestroyIcon( IntPtr hIcon );<br />
}<br />
#endregion<br />
<br />
#endregion<br />
|
|
|
|
|
:confusedconfusedHi all.
I want a right to left treeview for a right to left treeview.
is anyone to help me.
thanks.
|
|
|
|
|
Using the concept of "Mirroring" i have done it.
Search for it in msdn.
But there are no other ways to do it.
Even i have create my own flipped control from Scratch with out using
windows api.
Srinivas
|
|
|
|
|
Since you're already interop'ing with Shell32.dll, why not just use the BrowseForFolder property? Currently, this is what many projects do. Here is some sample code, assuming you created the interop assembly for Shell32.dll:
Shell32.ShellClass shell = new Shell32.ShellClass();
Shell32.Folder2 folder = (Shell32.Folder2)shell.BrowserForFolder(
this.Handle, "Browse for Folder", 0, 0);
string path = folder.Self.Path;
You could still wrap this in a class (like having a CLS-compliant enumeration for all the startup-directories), but all the UI is taken care of for you. You can still provide a callback (in the form of a delegate) to customize the UI, too.
"Well, I wouldn't say I've been missing it, Bob." - Peter Gibbons
|
|
|
|
|
Correct me if I'm wrong, but all that will do is create a BrowseForFolder dialog, which is not the required result here.
|
|
|
|
|
I'd like to solve the problem with the desktop shellfolder, but I've gone as far as I can with the code provided. I noticed the Interop.shell32.dll file, and I'm curious where it came from, and if its possible to get the code for it. It looks like a very useful wrapper for shell32.dll, and I'd love to know how it was written, not to mention the fact that if I understand how it works, I may be able to figure out this problem with the desktop.
Thanks.
|
|
|
|
|
If you add a reference to a COM library in vs.net it automatically wraps them up with a Interop.*.dll - that's all I can tell you I'm afraid, don't know anything else about it.
As far as the FolderTreeView, I will be posting a major update to this soon - I have solved the desktop namespace problem (it was actually embarassingly simple), and am adding a couple of features to it, such as a DrillToFolder method. Stay tuned
|
|
|
|
|
While your into updating the control, I have a request. I noticed that you repeatedly add icons to the controls imagelist. If its a folder icon, its possible that it will be added hundreds of times, possibly more depending on how far down and around you drill. You can watch memory usage go up in taskmanager as more icons are added.
Is there any way you could use the systems imagelist, and just grab the image id's from it, rather than building one dynamically? That would be great if you could, and if not, no problem, I'm working on an interop library of my own for shell32.dll, comctl32.dll, and uxtheme.dll, which will provide access to the system imagelist. Its just going to take me a good long while to learn the API's for all three DLL's and figure out how to create a custom inderop library for them.
|
|
|
|
|
Jon Rista wrote:
I'm working on an interop library of my own for shell32.dll, comctl32.dll, and uxtheme.dll, which will provide access to the system imagelist
The next revision has been finished, Chris should be updating the article over the next couple of days. V1.1 now properly starts at the Desktop namespace, showing My Computer, Network Neighborhood, Recycle Bin etc. I have also added a startup folder driller, but the imagelist works just the same as before. I had thought to write code to manage the icons better, but I guess I was just too lazy to save the 1KB here and there
If you are willing to share some of your code, perhaps you can help make this control better
|
|
|
|
|
DOH!! LOL Just found this in shell32 documentation:
HRESULT SHGetDesktopFolder(
IShellFolder **ppshf
);
Anyway, I'd be glad to share my code. This is currently a learning project, but eventually I want to provide an interop library that lets you call all the unmanaged functions included in Shell32.dll, Comctl32.dll, and uxtheme.dll. Shell32.dll contains a lot of COM objects and interfaces, but there is also a whole list of static functions that you can't call when you add shell32.dll as a reference. Great stuff like SHGetImageList, which returns an IImageList interface to the system imagelist.
|
|
|
|
|
I've emailed Chris the version 1.11 code, demo, image and html to update this article, I guess he must be busy.. It fixes the known issues with this control, bar the image list bloat you've noted. Your project sounds very interesting, I'm curious to see it applied to this control - and possibly some others I'm working on..
|
|
|
|
|
some code such as my computer,my neighbor could not displayed.
|
|
|
|
|
In fact, comparing to Windows Explorer, what the tree control is missing is the actual Explorer namespaces.
Fortunately, they are easy to lookup. See this article[^].
In short, default namespaces (MyComputer, MyDocuments, Recyclebin, network neighbourhood, Internet Explorer, and Control panel) are all accessed through this registry scheme :
HKEY_LOCAL_MACHINE
Software
Microsoft
Windows
CurrentVersion
Explorer
Virtual Folder Name
Namespace
{Extension CLSID}
sometimes it helps to look at the IL generated code
a MS guy on develop.com "answering" .NET issues
|
|
|
|
|
StephaneRodriguez wrote:
In short, default namespaces (MyComputer, MyDocuments, Recyclebin, network neighbourhood, Internet Explorer, and Control panel) are all accessed through this registry scheme :
You may use this to get some of them Environment.SpecialFolder with GetFolderPath from Environment namespace.
Best Regards,
Laurent Kempé [Microsoft .NET MVP]
Visit my web site Tech Head.
---
Old programmers never die, they just branch to a new address.
|
|
|
|
|
Thanks for the feedback Laurent and Stephane, I am familiar with both of the methods provided, but both methods only provide me with a string path, not a Shell32.FolderItem object, which is what I need.
Of course, if I knew how to create a Shell32.FolderItem object from a string path, then both methods would work just fine, and my problem would be solved
|
|
|
|
|
Hi,
This is an excellent tree control.
Here is a simple way to display "Control panel" also in the tree control...
All one has to do is simply comment out this line
if(item.IsFileSystem && item.IsFolder && item.IsBrowsable)
in the ExpandBranch method of ShellOperations
class . Of course selecting control panel in this tree control may have some wanted/unwanted behaviour..
Cheers
|
|
|
|
|