65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Mobile - 吸引人的 UI 第二部分

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.43/5 (8投票s)

2009 年 10 月 30 日

GPL3

2分钟阅读

viewsIcon

36077

downloadIcon

60

Windows Mobile - 吸引人的 UI 第二部分

引言

在我的 第一篇博客 中,我承诺会推出第二部分。这里就是第二部分。我们将深入研究 AlphaImage 控件。

Using_AlphaButton.jpg

第一个问题是:.NET CF 不支持图像透明度。因此,无论何时我们请求透明颜色,它都会被转换为白色。更糟糕的是,带有透明背景的 GIF 图像在这里也无法工作。

AlphaMobileControls 包含一个名为“AlphaPictureBox”的控件,它继承自 AlphaControl。如果使用该控件,就可以解决透明度问题。

如何使用

只需将一个 AlphaPictureBox 控件放置到您的窗体上。在窗体构造函数中设置要在PictureBox中显示的图像。

alphaPictureBox1.Image = AlphaImage.CreateFromResource("mConcierge.Resources.backgroundNormal.jpg");

完成了。如果您需要背景透明度,则图像应该是一个具有正常透明背景的 GIF 图像。

内部原理

AlphaPictureBox 控件暴露的图像属性是一个 AlphaImage。

这个 AlphaImage 是从普通图像创建的。

///
/// Creates a new AlphaImage from the given memory stream.
///
public static AlphaImage CreateFromStream(MemoryStream stream)
{
PlatformAPI.IImaging.IImagingFactory factory = CreateFactory();
AlphaImage alphaImage = new AlphaImage();
byte[] pbBuf = stream.GetBuffer();
uint cbBuf = (uint)stream.Length;
factory.CreateImageFromBuffer(pbBuf, cbBuf, PlatformAPI.IImaging.BufferDisposalFlag.BufferDisposalFlagNone, out alphaImage._image);
}

IImagingFactory 接口定义了本机 (COM) 操作系统操作,如下所示

[ComImport, Guid("327ABDA7-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
public interface IImagingFactory
{
uint CreateImageFromStream(IStream stream, out IImage image);
uint CreateImageFromFile(string filename, out IImage image);
uint CreateImageFromBuffer([MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint size, BufferDisposalFlag disposalFlag, out IImage image);
uint CreateNewBitmap(uint width, uint height, PixelFormatID pixelFormat, out IBitmapImage bitmap); uint CreateBitmapFromImage(IImage image, uint width, uint height, PixelFormatID pixelFormat, InterpolationHint hints, out IBitmapImage bitmap); uint CreateBitmapFromBuffer(BitmapData bitmapData, out IBitmapImage bitmap); uint CreateImageDecoder(); uint CreateImageEncoderToStream(); uint CreateImageEncoderToFile(); uint GetInstalledDecoders(); uint GetInstalledEncoders(); uint InstallImageCodec(); uint UninstallImageCodec(); }

剩下的事情都比较简单。由于 AlphaPictureBox 控件继承自 AlphaControl 基类,它重写了 AlphaControl 的绘制方法。这反过来又调用 AlphaImage 的绘制方法。AlphaImage 内部的绘制方法通过调用此处定义的 COM 函数在窗体上绘制图像。

[ComImport, Guid("327ABDA9-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [ComVisible(true)]
        public interface IImage
        {
uint GetPhysicalDimension(out Size size); uint GetImageInfo(out ImageInfo info); uint SetImageFlags(uint flags); uint Draw(IntPtr hdc, ref Rectangle dstRect, IntPtr srcRect);
uint PushIntoSink(); // pominięte uint GetThumbnail(uint thumbWidth, uint thumbHeight, out IImage thumbImage); }

难以入眠的夜晚

当我计划聚会时,我遇到了问题。当我导航窗体时,我的应用程序开始出现异常。我到处寻找解决方案,但花了很长时间才从 codeplex 上找到一个。

问题在于一个托管数组被传递给 COM 对象。一旦垃圾回收器决定释放/移动这个数组,就会出现问题。

解决方法

在 IImagingFactory.cs 中,替换为

    // We need the MarshalAs attribute here to keep COM interop from sending the buffer down as a Safe Array.
    uint CreateImageFromBuffer([MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint
    size, BufferDisposalFlag disposalFlag, out IImage image);

有了

    uint CreateImageFromBuffer(IntPtr buffer, uint size, BufferDisposalFlag disposalFlag, out IImage image);    

在 AlphaImage.cs 中,在文件顶部添加

using System.Runtime.InteropServices;

并替换为

 factory.CreateImageFromBuffer(pbBuf, cbBuf,BufferDisposalFlag.BufferDisposalFlagNone,
    out alphaImage._image);

有了

    // Copy stream data into an unmanaged global buffer that will be freed by the factory
    once image is decoded
// note that we cannot pass pbBuf directly since it might be moved around or freed by the gc. IntPtr p = Marshal.AllocHGlobal((int)cbBuf); Marshal.Copy(pbBuf, 0, p, (int)cbBuf); factory.CreateImageFromBuffer(p, cbBuf, BufferDisposalFlag.BufferDisposalFlagGlobalFree, out alphaImage._image);

代码和控件可以在 这里 下载。

© . All rights reserved.