在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Obtaining (and managing) file and folder icons using SHGetFileInfo in C#
作者:Paul Ingles 翻译:小新0574 审校:Allen Lee
原文链接(及代码):http://www.codeproject.com/csharp/fileicon.asp
Introduction This article is based upon code from the MSDN Cold Rooster Consulting case study. Included in part of the CRC Rich Client is support for file icons, something I wanted to do myself. This article and classes are the result of my attempts to use the MSDN code in my own application.
这篇文章基于MSDN Cold Rooster Consulting case study上的代码(译注:我打不开文章提供的链接L)。(代码)包含在CRC Rich Client的一部分里,用来支持文件图标,这也正是我自己想做的事。这篇文章和相关类是我尝试使用MSDN里的代码到我自己的程序里去的结果。
The MSDN article explains how functions from Shell32 and User32 were wrapped in detail, but here's a short clip from the article:
那篇MSDN article详细解释了怎么包装Shell32和User32里的函数,这是那篇文章里的一小段:
"Interoperability with interfaces exposed by COM objects and the .NET Framework is handled via a proxy called the Runtime Callable Wrapper (RCW). The majority of the marshalling work is handled automatically by the .NET Framework.
“在.NET Framework中,与COM对象所提供的接口的互操作性是通过一个叫做“运行时可调用封装器” (Runtime Callable Wrapper (RCW))的代理单元完成的。主要的数据封送工作都是由.NET Framework自动完成的。”
C-style functions exported from an unmanaged library are a different matter. They are not wrapped automatically because information about the parameters required by the function is not as rich as the information provided by a COM type library. To call C-style functions exported from an unmanaged library, such as the Microsoft Windows® Shell32 API, you use the Platform Invocation Services (PInvoke)..."
“非托管类库提供的C风格函数却是另外一回事。由于函数需要的参数并不像COM类型库提供的信息那么丰富,所以它们并不能自动被封装。为了调用非托管类库提供的C风格的函数,比如说Microsoft Windows® Shell32 API,你就要使用Platform Invocation Services (PInvoke)…”
The code was left largely unchanged from the original article, although only SHGetFileInfo and DestroyIcon were retained.
尽管只有SHGetFileInfo 和 DestroyIcon 被保留了,其实从原始文章拿来的代码大多数都没有变过。 I personally found it quite hard to incorporate the MSDN code in my own application and after a few hours of wrestling with the masses of code and still getting errors when trying to build my own project I decided I would try and build up some classes around the Shell32 and User32 wrapped functions that I could use myself.
从我个人的角度讲,我发现要使MSDN里的代码融入到我自己的程序很困难。与大量代码挣扎了几小时后,还是发现产生错误。当我尝试建立自己的程序的时候,我决定我要试试建一些包装Shell32和User32里的函数的类,那样我自己就可以用了。
After looking back at the MSDN article the architecture of my solution and theirs is pretty similar, however I found it easier to develop my own classes and incorporate them into my own project. 在回顾MSDN的文章和我自己的解决方案的结构以后,发现它们是这么相似,然而,我发现开发自己的类然后让他们融入到自己的工程却来得更简单。
This article explains how I modified the MSDN article's code so that it can be used to retrieve icons as a stand-alone class in the form of the IconReader type, and then the IconListManager type which can be used to maintain ImageLists of file icons. It shields you from having to call the IconReader type's members directly, instead adding file icons to specified image lists. To prevent icons for the same file type being added more than once, a HashTable is used to store the file's extension at the time of adding the icon to the ImageList.
这篇文章解释了我怎么修改MSDN的文章的代码,以便它以IconReader 类型的形式作为一个单独的类能用来取得图标,而IconListManager 类型可以用来保存文件图保的图象列表。它可以使你免于直接调用IconReader类型的成员,取而代之的是增加文件图标到一个指定的图像列表。为了防止多次加入同样文件类型的图标,就用一个HashTable 在增加图标到ImageList的时候储存文件的扩展名。
Top Level View
The end result is two classes which make use of .NET's Interoperability to call the Win32 API to obtain icons for specified files and or folders. The IconReader class enables the caller to obtain icons directly (which may be all you need). However, an IconListManager class is then created which maintains icons within two ImageList types and shields you from retrieving icons directly.
最后的结果是两个类,这两个类使用.NET的互操作性来调用Win32API为特定的文件或者文件夹取得图标。 IconReader 类允许调用者直接取得图标(也许你们需要)。然而,可以创建一个IconListManager类,这样图标就保存在两个ImageList类型里,避免你直接取得图标。
IconReader - GetFileIcon Explanation
GetFileIcon is used to obtain icons for files, and uses three parameters:
GetFileIcon方法用来取得文件图标,使用三个参数:
It is a static member function since it doesn't need to store any state, and is intended primarily as an added layer of abstraction. If I needed to obtain a file's icon in the future (and not store it in an ImageList etc.) then I could do so using this class. Once I had a type that wrapped up the necessary API functions to obtain file icons I would then build another type to manage large and small ImageLists that would enable me to make a single call to add an icon, and if it was already added, return the index that the icon was in the ImageList.
这是一个静态成员函数,因此它不需要保存任何状态,主要作为一个增加的抽象层。如果我将来需要得到一个文件的图标(不储存在一个ImageList里等),我就可以使用这个类来做到。一旦我拥有了一个用来取得文件图标的必要API函数,我就建立另一个类型来管理大小图象列表,这能使我能够通过一个单独的调用来添加图标,如果它已经被加进来了,就返回这个图标在ImageList里的索引。
public static System.Drawing.Icon GetFileIcon(string name, IconSize size,
bool linkOverlay) Firstly, a SHFILEINFO structure is created from the following definition: 首先,一个SHFILEINFO结构使用以下定义创建:
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
The SHFILEINFO struct includes an attribute to define a formatted type, which is "a structure or class member annotated with the StructLayoutAttribute to ensure predictable layout information to its members." This ensures that the unmanaged code we call receives the struct as it is intended - i.e. in the order that the members are declared. More details on passing structures are on MSDN
SHFILEINFO 结构包含一个属性来定义一个被格式化的类型,这个类型是“一个结构或者一个类使用StructLayoutAttribute 来评注,这个属性保证结构或者类的成员以可预知它们的成员布局信息。”这样就保证我们调用的非托管代码得到就像它原来期望得到的结构。关于传递结构的更多细节在MSDN上。
Once the SHFILEINFO struct is created, flags are then set specifying how SHGetFileInfo should behave and what type of icon to retrieve. The code for this part is pretty self explanatory.
一旦创建了SHFILEINFO 结构,flags就被设置,来指出SHGetFileInfo 该怎么表现以及该得到哪种类型的图标。这部分的代码具有很强的自解释性。
全部评论
|
请发表评论