太晕了...待续...因为我没有学过C#,所以我也不知"ImageList"翻译成"图像目录"对不对... 如果楼主觉得可以这样翻译,我才想再翻译下去...不然会误人子弟的...
翻吧,Kyo,你也得干点正事是不?别一天到晚尽发表些对女性乳房的研究论文.
九洲方除百尺冰,映秀又遭蛮牛耕。汽笛嘶鸣国旗半,哀伤尽处是重生。 -老K
治国就是治吏。礼义廉耻,国之四维。四维不张,国之不国。 -毛泽东
太晕了...待续...因为我没有学过C#,所以我也不知"ImageList"翻译成"图像目录"对不对... 如果楼主觉得可以这样翻译,我才想再翻译下去...不然会误人子弟的...
翻吧,Kyo,你也得干点正事是不?别一天到晚尽发表些对女性乳房的研究论文.
go on
解决方案 现在我将要通过使用具有几个静态方法的简单类来向你演示一下如何向你的ImageList里添加图像。ImageList类及其中的五个方法将允许你添加丰富的图像资源。这些资源包括Image或Icon对象,一个外部图像文件和图标文件,一个你项目中的嵌入式图像资源,外部文件图标和文件夹图标还有文件系统扩展图标。下文中对所有这些作了演示和解释。在添加不同资源时用到了大量的方法,但在核心部分用到了win32 API。当添加外部图像文件或Image对象时,首先要通过调用gdi32.dll提供的CreateDIBSection() API来创建一个位的新的位图。并创建获有这个位图句柄的bitmap对象。然后图像就以正确的格式被复制到了句柄所指的内存。最后位图将通过持有ImageList控制器句柄和bitmap对象句柄的ImageList.Add()方法(这里他用了ImageList_Add()好像是内存中编译器对函数转换成的格式,也可能是错写,太底层了,不太清楚)读入到ImageList中。(....实现起来很简单的东西,被他从底层分析就这么复杂了....)当添加Icon文件或Icon对象时,你则可以通过使用Icon类的.Handle属性来正确的添加它们。一但图像被读入到了ImageList中你就可以在工具栏,目录视窗等地方使用它们了。当然图像的所有原有方法还有用并像.Count属性一样正常工作着。
(这段开始真正讲到了技术,人个理解上添加图像的过程中最关键的一步就是要通过API来创建位图.....这样就不会出现他在The Problem这段中所讲的直接用ImageList.Add()来添加的问题,当然这个理解也可能有误,看了源代码会了解的更多些) over...
整理并修正些细节: 向ImageList控制器添加32位混合图像和图标 一篇关于添加阿尔法混合图像和使用组件的文章 引言 时代在进步,随着应用程序各方面的发展,最终用户希望得到更加让振奋的用户界面。除了视觉方面的美观,一个完好的用户还有其他很多的作用。良好的设计并使用优美的图标来表现你的程序也会给使用你的程序的最终用户带来更好的工作体验。这正是我发表这篇文章的目的。好,现在让我我们深入到技术方面。 我们在微软的很多产品中看到了他们所使用的那些漂亮的工具栏图标。它们有阴影,24位真彩,幻灯片等等。这些图片实际上是24位图象通过阿尔粒子通道将他们转换成了32位格式的。这种格式不仅允许使用透明的像素,也允许使用半透明的像素。这将使图像很好的容合在背景中,而不是你有时候所见到的一些劣制的24位图像。倘若你从未在你的应用程序中用过这样的图标或图像,你很快会发现这对你来说是一个出乎意料的挑战,事实上存在着某些你难以克服的障碍。甚至于在.net framework中都存在着一些bug会使你无法正常的显示你的图像。在这篇文章中我会试着解释如何来克服这些障碍,和如何使用ImageList类来解决问题。 从现在开始,我会谈到图标和图像,也会涉及到24位阿尔法估算混合图像。 问题所在 问题所在 在上文中我提到的bug,我个人认为是存在于ImageList类的组件(重点改正)本身的。如果你试着用ImageList托管的image.add()方法或用vs.net集成环境来添加一幅32位图像,你会发现要么阿尔法粒子通道发生错误要么完全丢失了原图像本身。举个例子:创建一个新的Bitmap对象,读取一幅32位的图像文件例如.png文件。然后实现一个Bitmap的新实例:Bitmap bm=new Bitmap(file);然后使用ImageList.add()方法将Bitmap的实例(这里就是bm了)添加到ImageList。就算bm.IsAlphaFormat=true,图像在添加到ImageList容器的过程中也会变的不正确。如果你使用手动的方法来添加(个人理解是通过.net IDE来添加),结果将会导致图像的显示错误。我认为问题在于.Add方法引用了阿尔法粒子通道并将其以位图结构复制到ImageList的过程中。我在这之所以下这个结论是由于通过手动的对一幅图像使用.Add()的方法似乎能产生作用。你会看到我用Icon类中返回一个Widows图标的.FromHandle方法来对图标(.ico 文件)使用这个办法。 现在,如果你试着用上述的方法来添加图像,你会发现由于阿尔法粒子通道的错误,在本应该发生阿尔法混合的地方出现的黑点。万一你用阿尔法粒子通道来添加一幅.png文件,你会发现阿尔法混合确实发生了,但在某些发生了阿尔法混合的地方却存在着细微的颜色错误。这个问题一些个很好的案例是你可以将IE或MSN的图标放大,然后细细观察一下这两个图标的左面。也许在那些32*32像素的图标中你很难发现这种颜色错误,但若是在16*16的图标中,这个错误非常明显。综上所述,ImageList控制器本身对32位阿尔法混合图像的容纳没有问题,但是将图像添加到ImageList容器的方法导致了错误的出现。
解决方案 现在我将要通过使用具有几个静态方法的简单类来向你演示一下如何向你的ImageList里添加图像。ImageList类及其中的五个方法将允许你添加丰富的图像资源。这些资源包括Image或Icon对象,一个外部图像文件和图标文件,一个你项目中的嵌入式图像资源,外部文件图标和文件夹图标还有文件系统扩展图标。下文中对所有这些作了演示和解释。在添加不同资源时用到了大量的方法,但在核心部分用到了win32 API。当添加外部图像文件或Image对象时,首先要通过调用gdi32.dll提供的CreateDIBSection() API来创建一个位的新的位图。并创建获有这个位图句柄的bitmap对象。然后图像就以正确的格式被复制到了句柄所指的内存。最后位图将通过持有ImageList控制器句柄和bitmap对象句柄的ImageList.Add()方法(这里他用了ImageList_Add()好像是内存中编译器对函数转换成的格式,也可能是错写,太底层了,不太清楚)读入到ImageList中。当添加Icon文件或Icon对象时,你则可以通过使用Icon类的.Handle属性来正确的添加它们。一但图像被读入到了ImageList中你就可以在工具栏,目录视窗等地方使用它们了。当然图像的所有原有方法还有用并像.Count属性一样正常工作着。 在使用代码前要注意的 首先,图像要能够被正确的显示你的C#应用程序和各种属性要已经经过了正确的设置。在介绍如何使用类前让我们先来看看这些问题。首先在应用程序中要确保使用.Run方法前已经使用了.EnableVisualStyles()和Application.DoEvents() 方法。另一个需要被设置的极其重要的属性是ImageList.ColorDepth 属性。这个属性一定要被设置为 ColorDepth.Depth32Bit当然你可以使用vs.net集成环境来设置这些属性。同时也请记住,阿尔法粒子混合图像只能被win xp+和.Net framework 1.1+。在早期的windows版本中,以下代码是没有任何作用的。
// // Enabling Visual Styles // static void Main() { // These two calls MUST be made before the // .Run method to enable 32bit icons to be used. Application.EnableVisualStyles(); Application.DoEvents(); // The color depth of the ImageList MUST be set // to 32bit before images can be added to the control. myImagelist.ColorDepth = ColorDepth.Depth32Bit; Application.Run(new Form1()); } ImageList类的公有方法 public sealed class Imagelist { public static void AddFromImage(Image sourceImage, ImageList destinationImagelist) {..} public static void AddFromImage(Icon sourceIcon, ImageList destinationImagelist) {..} public static void AddFromFile(string fileName, ImageList destinationImagelist) {..} public static void AddIconOfFile(string fileName, IconSize iconSize, bool selectedState, bool openState, bool linkOverlay, ImageList destinationImagelist) {..} public static void AddIconOfFile(string fileName, ImageList destinationImagelist) {..} public static void AddIconOfFileExt(string fileExtension, IconSize iconSize, bool selectedState, bool openState, bool linkOverlay , ImageList destinationImagelist) {..} public static void AddIconOfFileExt(string fileExtension, ImageList destinationImagelist) {..} public static void AddEmbeddedResource(string resourceName, ImageList destinationImagelist) {..} } 现在,该做的调用和设置属性都作好了。现在我们来看看相关类的静态方法如何使用。 添加Image或Icon对象。
//
// This example adds a 32bit alphablended image
// to myImagelist using the AddFromImage() method.
// This overloaded method accepts either
// an Image object or Icon object as its source.
//
Narbware.Imagelist.AddFromImage( Image.FromFile("image.png"),
myImagelist );
Bitmap myBitmap = new Bitmap( "image.png" );
Narbware.Imagelist.AddFromImage( myBitmap, myImagelist );
Icon myIcon = new Icon("icon.ico");
Narbware.Imagelist.AddFromImage( myIcon, myImagelist ); 从嵌入资源添加图像 这个方法的重要性在于你可以通过嵌入式资源来预先将图像读入到ImageList中。这意为着当你要预先从将图像读入到ImageList中时不在需要依赖于外部文件。这就是为什么你没办法使用IDE来预先添加图像,因为添加图像一定要用到ImageList.Add()方法。添加嵌入式资源的关键在于在向你的项目添加好资源后要将编译器的Build Action属性设为'Embedded Resource',作了这样的设置这后,下面的代码会告诉你如何将资源添加到ImageList中。
//
// This example adds a 32bit alphablended image from
// an embedded resource to myImagelist
// using the AddEmbeddedResource() method.
//
Narbware.Imagelist.AddEmbeddedResource( "myApplicationName.image.png",
myImagelist ); // where image.png resides in the projects root 从外部文件添加图像 当你想要从你的项目所在目录之外添加已有的文件时,这个方法会为你节约些时间。你不必非要创建一个Image对象,然后将图像文件加载到这个Image对象,然后将这个Image对象添加到ImageList中,取而代之的,你只需要将提供你想要添加的图像文件的文件路径就可以了。
//
// This example adds a 32bit alphablended image from an external
// file to myImagelist using the AddFromFile() method.
//
Narbware.Imagelist.AddFromFile( "c:\\blah\image.png", myImagelist );
Narbware.Imagelist.AddFromFile( "c:\\icons\icon.ico", myImagelist );
引用并添加文件或文件夹图标 这个方法用来引用并添加文件或文件夹图标。这个功能强大的方法是最近被.net framework所支持的,你可以在任何使用了用户界面的应用程序中看到它的表现。这个方法有两个重载,一个默认的简单重载用于添加大尺寸的图标到ImageList。另一个重载则提供给了你可以格式化你所引用的图标的能力。比如添加一个指定的图标,或通过一个链接来引用一个图标等等。
//
// This example extracts and adds 32bit alphablended icons
// from external files and folders
// to myImagelist using the AddIconOfFile() method.
//
// This short overload extracts and adds
// a largs icon (32x32) to and imagelist
Narbware.Imagelist.AddIconOfFile( "c:\\file.mpg",
myImagelist )
// adds the files icons, in this case the systems mpg icon
// This longer method gives you more
// options on the type of icon to extract
Narbware.Imagelist.AddIconOfFile( "c:\\file.mpg",
Narbware.IconSize.Small, false, false,
false, myImagelist );
// This adds a folder icon. It can also extract
// special folder icons such as My Music, My Pictures, etc...
Narbware.Imagelist.AddIconOfFile( "c:\mySpecialFolder",
Narbware.IconSize.Large, false, false,
false, myImagelist );
引用和添加文件类型图标(扩展的) 这个方法和上面的AddIconOfFile() 相似,为你提供了的从系统引用你想要的扩展图标的方法。上面的所有规则也都适用于这个方法。下面是例子....
//
// This example extracts and adds 32bit alphablended file
// extension icons to myImagelist using the AddIconOfFileExt() method.
//
// adds a large sized icon associated with jpeg files.
Narbware.Imagelist.AddIconOfFileExt( "jpg", myImagelist );
Narbware.Imagelist.AddIconOfFileExt( "zip", Narbware.IconSize.Small,
false, false, false, myImagelist );
// adds a small sized zip file icon to the imagelist.
一些有趣的细节 下面是一个用于添加32位图像的私有方法。这其实是解决阿尔法粒子通道错误的本质。记住一个正确格式的IDB对象是基于BITMAPINFO结构被建立的,然后所需的图像通过使用Win32 API被添加到ImageList中。这个方法另外的重载用来引用图标通过创建一个临时的SHFileInfo对象并返回一个带有指向默认ImageList的Image.Add()方法的句柄。
private static void Add( Bitmap bm, ImageList il )
{
IntPtr hBitmap, ppvBits;
BITMAPINFO bmi = new BITMAPINFO();
if ( bm.Size != il.ImageSize )
{
// resize the image to dimensions of imagelist before adding
bm = new Bitmap( bm, il.ImageSize.Width, il.ImageSize.Height );
}
bmi.biSize = 40; // Needed for RtlMoveMemory()
bmi.biBitCount = 32; // Number of bits
bmi.biPlanes = 1; // Number of planes
bmi.biWidth = bm.Width; // Width of our new bitmap
bmi.biHeight = bm.Height; // Height of our new bitmap
bm.RotateFlip( RotateFlipType.RotateNoneFlipY );
// Required due to the way bitmap is copied and read
hBitmap = CreateDIBSection( new IntPtr(0), bmi, 0,
out ppvBits, new IntPtr(0), 0 );
//create our new bitmap
BitmapData bitmapData = bm.LockBits( new Rectangle( 0, 0,
bm.Width, bm.Height ), ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb );
RtlMoveMemory( ppvBits, bitmapData.Scan0,
bm.Height * bitmapData.Stride );
// copies the bitmap
bm.UnlockBits( bitmapData );
ImageList_Add( il.Handle, hBitmap, new IntPtr(0) );
// adds the new bitmap to the imagelist control
}
结论 通过使用ImageList类以及它所拥有的方法从各种各样的资源来添加图像,你现在已经可以在你的C#应用程序中使用32位阿尔法混合图像了。而且在ImageList中添加图像后,你仍能正常的使用ImageList控制器。如果你觉的有错误或误导的地方在这篇文章中,请一定将它们指出来。我也只是个c#的初学者,所以我也还有很多要学习的地方,同时我也会感谢一切指责和建议。 关于作者其人其事..... 这个就不翻了 结束了,这样行了不?