Windows Mobile - Attractive UI Part-II






2.43/5 (8 votes)
Windows Mobile - Attractive UI Part-II
- Download source code - 47.3 KB (contains updated
AlphaMobileControls
with some additional functionality plus a set of new controls)
Introduction
On my first blog I promised of Part II. Here is the Part – II. We shall look deep inside into the AlphaImage Control here.
The first problem is: .NET CF does not support image transparency. So, when ever we ask for transparent color it is translated as white. To add to this the gif images with transparent background won’t work here.
AlphaMobileControls has a control “AlphaPictureBox” which derives from AlphaControl. If we use this one then it would fix the transparency prolem.
How to use
Just place an alphapicturebox control to your form. At the constructor of the form set the image that would be displayed in the picture box:
alphaPictureBox1.Image = AlphaImage.CreateFromResource("mConcierge.Resources.backgroundNormal.jpg");
You are done. If you need backgroung transparency then the image shound a normal background transparent gif.
What’s happening Inside
The image property that is exposed by AlphaPicture box is a AlphaImage.
This Alpha Image is created form a normal image.
///
/// 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 interface defines native (COM) OS operations as shown below:
[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(); }
Rest of things are Pretty simple. As alphapicturebox controls derives from alphacontrol base class, it overrides the draw method of alphacontrol. This inturn calls draw method of alphaimage. Draw method inside alpha image draws the image on the form calling a COM function as defined here :
[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); }
Sleepless Nights
The shock came to me when I was planning for a party. My application started to get excetions when I was navigating through the forms. I reached everywhere for a solution but it took long time to find one from codeplex.
The problem is because a managed array is passed to the COM object. Once the garbage collector decides to free/move this array all hell break loose.
Here’s a fix:
In IImagingFactory.cs, replace:
// 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);
With:
uint CreateImageFromBuffer(IntPtr buffer, uint size, BufferDisposalFlag disposalFlag, out IImage image);
In AlphaImage.cs add this in the top of the file:
using System.Runtime.InteropServices;
And replace:
factory.CreateImageFromBuffer(pbBuf, cbBuf,BufferDisposalFlag.BufferDisposalFlagNone, out alphaImage._image);
With:
// 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);
The code and the controls could be here here