Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Transparent Image Copy to Clipboard Adds Blue BG
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  16 messages - Expand all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Bill Henning  
View profile  
 More options Dec 17 2005, 3:03 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Bill Henning" <j...@at-actipro.software.com>
Date: Sat, 17 Dec 2005 15:03:50 -0500
Local: Sat, Dec 17 2005 3:03 pm
Subject: Transparent Image Copy to Clipboard Adds Blue BG
Hi there... I am running in the .NET 1.0 framework have an object that has
an Image property.  Upon a certain event, I want to copy the Image to the
Clipboard.  This is easy enough:
Clipboard.SetDataObject(image)

However, if the Image has a transparent background, when I go to paste the
Image into a drawing app like Paint or Photoshop, the transparent area of
the Image has been replaced by a blue color.  So it seems that the Image
isn't telling the clipboard what parts need to be transparent.  This doesn't
make sense since it can draw the Image transparent areas fine.

Can anyone explain what is wrong here and if this is some sort of .NET
framework limitation, provide either C# or VB.NET code to work around it?

Thanks in advance!

Bill


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Phillips, Jr.  
View profile  
 More options Dec 17 2005, 3:52 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m>
Date: Sat, 17 Dec 2005 15:52:39 -0500
Local: Sat, Dec 17 2005 3:52 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
The CF_DIBV5 clipboard format preserves the alpha channel
by design.

This clipboard format requires that you create
a packed DIB from a DIBSECTION created with the BITMAPV5HEADER.

You can use P-INVOKE with CreateDIBSection for your bitmap
and then transfer the bits with LockBits, BitBlt or DrawImage.

You create a global memory object to represent the packed DIB.
This packed DIB will include the BITMAPV5HEADER and the bitmap's
bits.

Place the global memory handle on the clipboard.

Clipboard.SetDataObject(image) places a BI_RGB bitmap
on the clipboard.  Per the documentation, the high byte in each
DWORD is not used.

There is no way for an aplication to natively know that the bitmap
that is retrieved from the clipboard with a CF_DIB or
CF_BITMAP clipboard format has an alpha channel.

An application could test but a CF_DIBV5 clipboard format
advertises that an alpha channel is present!

"Bill Henning" <j...@at-actipro.software.com> wrote in message

news:%23Qdy%23T0AGHA.2676@TK2MSFTNGP11.phx.gbl...


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bill Henning  
View profile  
 More options Dec 18 2005, 9:55 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Bill Henning" <j...@at-actipro.software.com>
Date: Sun, 18 Dec 2005 21:55:03 -0500
Local: Sun, Dec 18 2005 9:55 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
Thanks for the reply Michael.  I'm not an expert with the GDI APIs so can
you help me out?  Here's what I wrote so far:

internal void CopyAlphaBitmapToClipboard(Bitmap image) {
 BITMAPV4HEADER bih = new BITMAPV4HEADER();
 bih.bV5Size   =
System.Runtime.InteropServices.Marshal.SizeOf(typeof(BITMAPV4HEADER));
 bih.bV5Width  = image.Width;
 bih.bV5Height  = image.Height;
 bih.bV5Planes  = 1;
 bih.bV5BitCount  = 32;
 bih.bV5Compression = 0;
 bih.bV5RedMask  = 0x00FF0000;
 bih.bV5GreenMask = 0x0000FF00;
 bih.bV5BlueMask  = 0x000000FF;
 bih.bV5AlphaMask = 0xFF000000;
 BITMAPINFO bi  = new BITMAPINFO();
 bi.bmiHeader  = bih;

 Graphics g = Graphics.FromImage(image);
 IntPtr imageHdc = g.GetHdc();

 IntPtr hdc = NativeMethods.CreateCompatibleDC(imageHdc);

 // Create the DIB section with an alpha channel
 IntPtr ppvBits = IntPtr.Zero;
 const int DIB_RGB_COLORS = 0;
 IntPtr hBitmap = NativeMethods.CreateDIBSection(hdc, bi, DIB_RGB_COLORS,
out ppvBits, IntPtr.Zero, 0);

 const int SRCCOPY = 0x00CC0020;
 NativeMethods.BitBlt(hdc, 0, 0, image.Width, image.Height, imageHdc, 0, 0,
SRCCOPY);  // SRCCOPY
 NativeMethods.DeleteDC(hdc);

 g.ReleaseHdc(imageHdc);
 g.Dispose();

    // TODO: Do more stuff here

}

Is that correct so far or do you see any bugs with bad initializations or
memory leaks?  I used the V4 header since I think it has the alpha stuff I
need and was less to define. :)

What I think I have in the procedure above is a handle to a bitmap (hBitmap)
that is still open.  Somehow I need to send that to a SetClipboardData API
call.  But I think I need a global memory handle as you said.  What do I
need to add to get that working?

Thanks so much for your help!

Bill

"Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m> wrote in message
news:uDNOSv0AGHA.2040@TK2MSFTNGP14.phx.gbl...


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Phillips, Jr.  
View profile  
 More options Dec 19 2005, 3:04 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m>
Date: Mon, 19 Dec 2005 15:04:04 -0500
Local: Mon, Dec 19 2005 3:04 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
I suggest the following:

public const uint BI_BITFIELDS = 3;
public const uint LCS_WINDOWS_COLOR_SPACE = 2;
public const uint LCS_GM_IMAGES = 4;
public const uint CF_DIBV5 = 17;
public const uint GMEM_MOVEABLE = 0x00000002;
public const uint GMEM_ZEROINIT = 0x00000040;
public const uint GMEM_DDESHARE = 0x00002000;
public const uint GHND = GMEM_MOVEABLE | GMEM_ZEROINIT;

[StructLayout(LayoutKind.Sequential)]
public struct CIEXYZ
{
      public uint ciexyzX; //FXPT2DOT30
 public uint ciexyzY; //FXPT2DOT30
 public uint ciexyzZ; //FXPT2DOT30

}

[StructLayout(LayoutKind.Sequential)]
public struct CIEXYZTRIPLE
{
 public CIEXYZ ciexyzRed;
 public CIEXYZ ciexyzGreen;
 public CIEXYZ ciexyzBlue;

}

[StructLayout(LayoutKind.Sequential)]
public struct BITFIELDS
{
 public uint BlueMask;
 public uint GreenMask;
 public uint RedMask;

}

[StructLayout(LayoutKind.Explicit)]
public struct BITMAPV5HEADER
{
 [FieldOffset(0)] public uint   bV5Size;
 [FieldOffset(4)] public int    bV5Width;
 [FieldOffset(8)] public int    bV5Height;
 [FieldOffset(12)]public ushort   bV5Planes;
 [FieldOffset(14)]public ushort   bV5BitCount;
 [FieldOffset(16)]public uint   bV5Compression;
 [FieldOffset(20)]public uint   bV5SizeImage;
 [FieldOffset(24)]public int    bV5XPelsPerMeter;
 [FieldOffset(28)]public int    bV5YPelsPerMeter;
 [FieldOffset(32)]public uint   bV5ClrUsed;
 [FieldOffset(36)]public uint   bV5ClrImportant;
 [FieldOffset(40)]public uint   bV5RedMask;
 [FieldOffset(44)]public uint   bV5GreenMask;
 [FieldOffset(48)]public uint   bV5BlueMask;
 [FieldOffset(52)]public uint   bV5AlphaMask;
 [FieldOffset(56)]public uint   bV5CSType;
 [FieldOffset(60)]public CIEXYZTRIPLE bV5Endpoints;
 [FieldOffset(96)]public uint   bV5GammaRed;
 [FieldOffset(100)]public uint        bV5GammaGreen;
 [FieldOffset(104)]public uint        bV5GammaBlue;
 [FieldOffset(108)]public uint        bV5Intent;
 [FieldOffset(112)]public uint        bV5ProfileData;
 [FieldOffset(116)]public uint        bV5ProfileSize;
 [FieldOffset(120)]public uint        bV5Reserved;

}

[DllImport("user32.dll")]
static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport("user32.dll")]
static extern bool EmptyClipboard();

[DllImport("user32.dll")]
static extern bool CloseClipboard();

[DllImport("user32.dll")]
static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);

[DllImport("kernel32.dll")]
static extern IntPtr GlobalAlloc(uint uFlags, uint dwBytes);

[DllImport("kernel32.dll")]
static extern IntPtr GlobalLock(IntPtr hMem);

[DllImport("kernel32.dll")]
static extern bool GlobalUnlock(IntPtr hMem);

public IntPtr CreatePackedDIBV5( Bitmap bm )
{
 BitmapData bmData = bm.LockBits( new Rectangle(0,0,bm.Width, bm.Height),
    ImageLockMode.ReadOnly, bm.PixelFormat);
 uint bufferLen = (uint)(Marshal.SizeOf(typeof(BITMAPV5HEADER)) +
    (Marshal.SizeOf(typeof(uint)) * 3) + bmData.Height * bmData.Stride);
 IntPtr hMem = GlobalAlloc(GHND | GMEM_DDESHARE, bufferLen);
 IntPtr packedDIBV5 = GlobalLock(hMem);
 BITMAPV5HEADER bmi = (BITMAPV5HEADER)Marshal.PtrToStructure( packedDIBV5,
typeof(BITMAPV5HEADER));
 bmi.bV5Size = (uint)Marshal.SizeOf(typeof(BITMAPV5HEADER));
 bmi.bV5Width = bmData.Width;
 bmi.bV5Height = bmData.Height;
 bmi.bV5BitCount = 32;
 bmi.bV5Planes = 1;
 bmi.bV5Compression = BI_BITFIELDS;
 bmi.bV5XPelsPerMeter = 0;
 bmi.bV5YPelsPerMeter = 0;
 bmi.bV5ClrUsed = 0;
 bmi.bV5ClrImportant = 0;
 bmi.bV5BlueMask = 0x000000FF;
 bmi.bV5GreenMask = 0x0000FF00;
 bmi.bV5RedMask = 0x00FF0000;
 bmi.bV5AlphaMask = 0xFF000000;
 bmi.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
 bmi.bV5GammaBlue = 0;
 bmi.bV5GammaGreen = 0;
 bmi.bV5GammaRed = 0;
 bmi.bV5ProfileData = 0;
 bmi.bV5ProfileSize = 0;
 bmi.bV5Reserved = 0;
 bmi.bV5Intent = LCS_GM_IMAGES;
 bmi.bV5SizeImage = (uint)(bmData.Height * bmData.Stride);
 bmi.bV5Endpoints.ciexyzBlue.ciexyzX =
 bmi.bV5Endpoints.ciexyzBlue.ciexyzY =
 bmi.bV5Endpoints.ciexyzBlue.ciexyzZ = 0;
 bmi.bV5Endpoints.ciexyzGreen.ciexyzX =
 bmi.bV5Endpoints.ciexyzGreen.ciexyzY =
 bmi.bV5Endpoints.ciexyzGreen.ciexyzZ = 0;
 bmi.bV5Endpoints.ciexyzRed.ciexyzX =
 bmi.bV5Endpoints.ciexyzRed.ciexyzY =
 bmi.bV5Endpoints.ciexyzRed.ciexyzZ = 0;
 Marshal.StructureToPtr(bmi, packedDIBV5, false);

 BITFIELDS Masks = (BITFIELDS)Marshal.PtrToStructure(
(IntPtr)(packedDIBV5.ToInt32() + bmi.bV5Size), typeof(BITFIELDS));
 Masks.BlueMask = 0x000000FF;
 Masks.GreenMask = 0x0000FF00;
 Masks.RedMask = 0x00FF0000;
 Marshal.StructureToPtr(Masks, (IntPtr)(packedDIBV5.ToInt32() +
bmi.bV5Size), false);

 long offsetBits = bmi.bV5Size + Marshal.SizeOf(typeof(uint)) * 3;
 IntPtr bits = (IntPtr)(packedDIBV5.ToInt32() + offsetBits);

 for ( int y = 0; y < bmData.Height; y++ )
 {
  IntPtr DstDib = (IntPtr)(bits.ToInt32() + (y* bmData.Stride));
  IntPtr SrcDib = (IntPtr)(bmData.Scan0.ToInt32() + ((bmData.Height-1-y)*
bmData.Stride));

  for ( int x = 0; x < bmData.Width; x++ )
  {
   Marshal.WriteInt32(DstDib, Marshal.ReadInt32(SrcDib));
   DstDib = (IntPtr)(DstDib.ToInt32() + 4);
   SrcDib = (IntPtr)(SrcDib.ToInt32() + 4);
  }
 }

 bm.UnlockBits(bmData);

 GlobalUnlock(hMem);

 return hMem;

}

An example on how to use this function follows:
IntPtr packedDIBV5 = CreatePackedDIBV5(AlphaBitmap);
OpenClipboard(this.Handle);
EmptyClipboard();
SetClipboardData(CF_DIBV5, packedDIBV5);
CloseClipboard();

I hope this helps!

"Bill Henning" <j...@at-actipro.software.com> wrote in message

news:OiZybeEBGHA.2656@tk2msftngp13.phx.gbl...


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bill Henning  
View profile  
 More options Dec 19 2005, 4:29 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Bill Henning" <j...@at-actipro.software.com>
Date: Mon, 19 Dec 2005 16:29:23 -0500
Local: Mon, Dec 19 2005 4:29 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
Thanks Michael, I tried it out however when I paste an image that was copied
using this procedure, it seems that the pixels of the icons are offset to
the right a couple pixels and the transparent area is black.

I'm pasting using the .NET classes so is that perhaps the problem since
maybe Clipboard.GetDataObject messes up some of the data?  I'm using
DataFormats.Bitmap as the format to retrieve.

Thanks again for your help.  The code you posted is exactly what I want to
do to get the data to the clipboard.  Now I just need to retrieve it again
into an Image class and have it render the same as when it was copied.

Bill

"Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m> wrote in message
news:%23zCmbdNBGHA.2644@TK2MSFTNGP09.phx.gbl...

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Phillips, Jr.  
View profile  
 More options Dec 19 2005, 5:02 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m>
Date: Mon, 19 Dec 2005 17:02:58 -0500
Local: Mon, Dec 19 2005 5:02 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
The clipboard will synthesize the following formats
in addition to the CF_DIBV5:
CF_DIB and CF_BITMAP

The clipboard may not synthesize the other formats correctly.

A CF_DIBV5 containes a BITMAPV5HEADER + 3 DWORD bitfields +
the image's bits.  The image compression is marked as BI_BITFIELDS
and therefore must contain a color table with 3 DWORDS for the mask.

This is redundant since the BITMAPV5HEADER contains the masks.

For 32bpp images, it is normally assumed that the image uses
the default masks with the compression set to BI_RGB.

You can try editing the code to use BI_RGB compression and get rid of the
bitfields.  The result will be no offset of the image by 3 DWORDs.

The packed dib will look like the following:
BITMAPV5HEADER <---BI_RGB compression
bitmap bits

The MSDN documentation

"Bill Henning" <j...@at-actipro.software.com> wrote in message

news:O%23u%23JNOBGHA.1028@TK2MSFTNGP11.phx.gbl...

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bill Henning  
View profile  
 More options Dec 21 2005, 7:38 am
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Bill Henning" <j...@at-actipro.software.com>
Date: Wed, 21 Dec 2005 07:38:58 -0500
Local: Wed, Dec 21 2005 7:38 am
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
Getting closer.... removing the 3 bitfield offsets and changing to BI_RGB
fixed the offset problem with the pasted image.  So now the image matches up
however the transparent background of the copied image still renders as
black when I paste it.  Any ideas?

Bill

"Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m> wrote in message
news:%23SPp3fOBGHA.3916@TK2MSFTNGP10.phx.gbl...

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Phillips, Jr.  
View profile  
 More options Dec 21 2005, 10:07 am
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m>
Date: Wed, 21 Dec 2005 10:07:15 -0500
Local: Wed, Dec 21 2005 10:07 am
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
When you paste a CF_DIBV5 image, you get a handle to
a packed DIB.

If the application is GDI based, that application must create
a bitmap with CreateDIBSection and then pre-multiply the alpha
channel against the colors and use the GDI AlphaBlend function
for rendering.

If the application is Gdiplus based, that application must create
a PixelFormat32bppARGB bitmap object and use DrawImage
for rendering.

For a BI_RGB bitmap, the high order byte (i.e., Alpha ) is not
used.  If that byte is 0x00 (i.e., transparent ), then it will be rendered
as opaque.  The background for the transparent portion of the bitmap
will be rendered as black.

The original Windows Bitmap 3.1 specification did not include a
provision for an alpha channel.  Any application that receives
a paste of an alpha channel bitmap must be aware that the alpha
channel exists and render it accordingly.

That application can either explicitly test for the presence of an
alpha channel or can use the BITMAPV5HEADER structure
to ascertain whether or not that bitmap was created with an
alpha channel.

If you look further in this newsgroup, you will see an
algorithm that I posted to test for an alpha channel
bitmap with only a handle (i.e., HBITMAP ) as the
source.

"Bill Henning" <j...@at-actipro.software.com> wrote in message

news:OqhuEuiBGHA.2040@TK2MSFTNGP14.phx.gbl...

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bill Henning  
View profile  
 More options Dec 21 2005, 11:36 am
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Bill Henning" <j...@at-actipro.software.com>
Date: Wed, 21 Dec 2005 11:36:09 -0500
Local: Wed, Dec 21 2005 11:36 am
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
Here's something I tried as an experiment and it worked... It captured the
alpha transparency fine.  The only problem is that it flipped the image
over. So I added code to flip it back.  Not sure why that happened.  But do
you see any issues with doing this like memory leaks or anything?

Note: Our DrawingHelper.DrawImage method allows us to do a flip.

internal static Bitmap PasteAlphaBitmapFromClipboard() {
 NativeMethods.OpenClipboard(IntPtr.Zero);
 IntPtr hMem = NativeMethods.GetClipboardData(CF_DIBV5);
 if (hMem == IntPtr.Zero) {
  NativeMethods.CloseClipboard();
  return null;
 }

 IntPtr packedDIBV5 = NativeMethods.GlobalLock(hMem);
 BITMAPV5HEADER bmi = (BITMAPV5HEADER)Marshal.PtrToStructure(packedDIBV5,
typeof(BITMAPV5HEADER));

 Bitmap bitmap = new Bitmap(bmi.bV5Width, bmi.bV5Height,
(int)(bmi.bV5SizeImage / bmi.bV5Height), PixelFormat.Format32bppArgb,
  new IntPtr(packedDIBV5.ToInt32() + bmi.bV5Size));

 Bitmap outputBitmap = new Bitmap(bmi.bV5Width, bmi.bV5Height,
PixelFormat.Format32bppArgb);
 Graphics g = Graphics.FromImage(outputBitmap);
 DrawingHelper.DrawImage(g, bitmap, 0, 0, bmi.bV5Width, bmi.bV5Height, 1.0f,
RotateFlipType.RotateNoneFlipY);
 g.Dispose();

 bitmap.Dispose();

 NativeMethods.GlobalUnlock(hMem);
 NativeMethods.CloseClipboard();

 return outputBitmap;

}

"Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m> wrote in message
news:%23wmw4AkBGHA.3936@TK2MSFTNGP12.phx.gbl...

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Phillips, Jr.  
View profile  
 More options Dec 21 2005, 12:39 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m>
Date: Wed, 21 Dec 2005 12:39:16 -0500
Local: Wed, Dec 21 2005 12:39 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
No issues, that is exactly how I do it in my own code.

Instead of:
DrawingHelper.DrawImage(g, bitmap, 0, 0, bmi.bV5Width, bmi.bV5Height, 1.0f,

> RotateFlipType.RotateNoneFlipY);

Try this:
// note the negative stride
Bitmap bitmap = new Bitmap(bmi.bV5Width, bmi.bV5Height, -
 (int)(bmi.bV5SizeImage / bmi.bV5Height), PixelFormat.Format32bppArgb,
 new IntPtr(packedDIBV5.ToInt32() + bmi.bV5Size + (bmi.bV5Height-1)*
(int)(bmi.bV5SizeImage / bmi.bV5Height)));

Using a negative stride flips the orientation of the bitmap.  Scan0 must
point to the
end of the bits.

"Bill Henning" <j...@at-actipro.software.com> wrote in message

news:O5ZemykBGHA.1032@TK2MSFTNGP11.phx.gbl...

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bill Henning  
View profile  
 More options Dec 21 2005, 1:12 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Bill Henning" <j...@at-actipro.software.com>
Date: Wed, 21 Dec 2005 13:12:34 -0500
Local: Wed, Dec 21 2005 1:12 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
Aha... you're the man!  That did it perfectly... thanks for all your help!

Bill

"Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m> wrote in message
news:uV2M1VlBGHA.3936@TK2MSFTNGP12.phx.gbl...

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bill Henning  
View profile  
 More options Dec 22 2005, 3:52 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Bill Henning" <j...@at-actipro.software.com>
Date: Thu, 22 Dec 2005 15:52:57 -0500
Local: Thurs, Dec 22 2005 3:52 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG

Ok, while I had the cutting and pasting of images working fine within my application, I've found some new issues.  

1) If I copy an image from my app and paste it into Paint, it looks corrupted.
2) If I copy an image from Paint and paste it into my app, it looks corrupted.
3) If I copy an image from my app and paste it into Word while customizing toolbars and using the customize menu's "Paste Button Image", it looks corrupted.  (Similar to #1)
4) If I copy an image from Word while customizing toolbars and using the customize menu's "Copy Button Image" and paste it into my app, it looks corrupted.  (Similar to #2)

I need to get all those scenarios working with transparency.  Here's my complete code listing so far for the Copy and Paste methods but if you'd like I could even write a small project to demo the issue:

/// <summary>
/// Copies the specified <see cref="Bitmap"/> to the clipboard using alpha information.
/// </summary>
/// <param name="bm">The <see cref="Bitmap"/> to copy.</param>
internal static void CopyAlphaBitmapToClipboard(Bitmap bm) {
 BitmapData bmData = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadOnly, bm.PixelFormat);
 // uint bufferLen = (uint)(Marshal.SizeOf(typeof(BITMAPV5HEADER)) + (Marshal.SizeOf(typeof(BITFIELDS))) + bmData.Height * bmData.Stride);
 uint bufferLen = (uint)(Marshal.SizeOf(typeof(BITMAPV5HEADER)) + bmData.Height * bmData.Stride);
 IntPtr hMem = GlobalAlloc(GHND | GMEM_DDESHARE, bufferLen);
 IntPtr packedDIBV5 = NativeMethods.GlobalLock(hMem);
 BITMAPV5HEADER bmi = (BITMAPV5HEADER)Marshal.PtrToStructure(packedDIBV5, typeof(BITMAPV5HEADER));
 bmi.bV5Size = (uint)Marshal.SizeOf(typeof(BITMAPV5HEADER));
 bmi.bV5Width = bmData.Width;
 bmi.bV5Height = bmData.Height;
 bmi.bV5BitCount = 32;
 bmi.bV5Planes = 1;
 bmi.bV5Compression = BI_RGB;  // BI_BITFIELDS;
 bmi.bV5XPelsPerMeter = 0;
 bmi.bV5YPelsPerMeter = 0;
 bmi.bV5ClrUsed = 0;
 bmi.bV5ClrImportant = 0;
 bmi.bV5BlueMask = 0x000000FF;
 bmi.bV5GreenMask = 0x0000FF00;
 bmi.bV5RedMask = 0x00FF0000;
 bmi.bV5AlphaMask = 0xFF000000;
 bmi.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
 bmi.bV5GammaBlue = 0;
 bmi.bV5GammaGreen = 0;
 bmi.bV5GammaRed = 0;
 bmi.bV5ProfileData = 0;
 bmi.bV5ProfileSize = 0;
 bmi.bV5Reserved = 0;
 bmi.bV5Intent = LCS_GM_IMAGES;
 bmi.bV5SizeImage = (uint)(bmData.Height * bmData.Stride);
 bmi.bV5Endpoints.ciexyzBlue.ciexyzX = bmi.bV5Endpoints.ciexyzBlue.ciexyzY = bmi.bV5Endpoints.ciexyzBlue.ciexyzZ = 0;
 bmi.bV5Endpoints.ciexyzGreen.ciexyzX = bmi.bV5Endpoints.ciexyzGreen.ciexyzY = bmi.bV5Endpoints.ciexyzGreen.ciexyzZ = 0;
 bmi.bV5Endpoints.ciexyzRed.ciexyzX = bmi.bV5Endpoints.ciexyzRed.ciexyzY = bmi.bV5Endpoints.ciexyzRed.ciexyzZ = 0;
 Marshal.StructureToPtr(bmi, packedDIBV5, false);

 BITFIELDS Masks = (BITFIELDS)Marshal.PtrToStructure((IntPtr)(packedDIBV5.ToInt32() + bmi.bV5Size), typeof(BITFIELDS));
 Masks.BlueMask = 0x000000FF;
 Masks.GreenMask = 0x0000FF00;
 Masks.RedMask = 0x00FF0000;
 Marshal.StructureToPtr(Masks, (IntPtr)(packedDIBV5.ToInt32() + bmi.bV5Size), false);

 // long offsetBits = bmi.bV5Size + Marshal.SizeOf(typeof(BITFIELDS));
 long offsetBits = bmi.bV5Size;
 IntPtr bits = (IntPtr)(packedDIBV5.ToInt32() + offsetBits);

 for (int y = 0; y < bmData.Height; y++) {
  IntPtr DstDib = (IntPtr)(bits.ToInt32() + (y* bmData.Stride));
  IntPtr SrcDib = (IntPtr)(bmData.Scan0.ToInt32() + ((bmData.Height - 1 - y)* bmData.Stride));

  for (int x = 0; x < bmData.Width; x++) {
   Marshal.WriteInt32(DstDib, Marshal.ReadInt32(SrcDib));
   DstDib = (IntPtr)(DstDib.ToInt32() + 4);
   SrcDib = (IntPtr)(SrcDib.ToInt32() + 4);
  }
 }

 bm.UnlockBits(bmData);

 NativeMethods.GlobalUnlock(hMem);

 NativeMethods.OpenClipboard(IntPtr.Zero);
 NativeMethods.EmptyClipboard();
 NativeMethods.SetClipboardData(CF_DIBV5, hMem);
 NativeMethods.CloseClipboard();  

}

/// <summary>
/// Pastes a <see cref="Bitmap"/> from the clipboard.
/// </summary>
/// <returns>The <see cref="Bitmap"/> that was pasted.</returns>
internal static Bitmap PasteAlphaBitmapFromClipboard() {
 NativeMethods.OpenClipboard(IntPtr.Zero);
 IntPtr hMem = NativeMethods.GetClipboardData(CF_DIBV5);
 if (hMem == IntPtr.Zero) {
  NativeMethods.CloseClipboard();  
  return null;
 }

 IntPtr packedDIBV5 = NativeMethods.GlobalLock(hMem);
 BITMAPV5HEADER bmi = (BITMAPV5HEADER)Marshal.PtrToStructure(packedDIBV5, typeof(BITMAPV5HEADER));

 Bitmap bitmap = new Bitmap(bmi.bV5Width, bmi.bV5Height, -(int)(bmi.bV5SizeImage / bmi.bV5Height), PixelFormat.Format32bppArgb,
  new IntPtr(packedDIBV5.ToInt32() + bmi.bV5Size + (bmi.bV5Height - 1) * (int)(bmi.bV5SizeImage / bmi.bV5Height)));

 Bitmap outputBitmap = new Bitmap(bmi.bV5Width, bmi.bV5Height, PixelFormat.Format32bppArgb);
 Graphics g = Graphics.FromImage(outputBitmap);
 g.DrawImage(bitmap, 0, 0, bmi.bV5Width, bmi.bV5Height);
 g.Dispose();

 bitmap.Dispose();

 NativeMethods.GlobalUnlock(hMem);
 NativeMethods.CloseClipboard();  

 return outputBitmap;


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Phillips, Jr.  
View profile  
 More options Dec 22 2005, 5:19 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m>
Date: Thu, 22 Dec 2005 17:19:51 -0500
Local: Thurs, Dec 22 2005 5:19 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG

> BITFIELDS Masks = (BITFIELDS)Marshal.PtrToStructure((IntPtr)(packedDIBV5.ToInt32() + bmi.bV5Size), typeof(BITFIELDS));
> Masks.BlueMask = 0x000000FF;
> Masks.GreenMask = 0x0000FF00;
> Masks.RedMask = 0x00FF0000;
> Marshal.StructureToPtr(Masks, (IntPtr)(packedDIBV5.ToInt32() + bmi.bV5Size), false);

Since you are creating a BI_RGB packed DIB, you need to comment out the above code!

If an application follows the bitmap specification correctly, that application should
be able to read and/or accept from the clipboard any bitmap format ( i.e., CF_DIB,CF_DIBV5,CF_BITMAP, etc.)

That includes correctly identifying where the bits begin for a BI_RBG versus a BI_BITFIELDS bitmap.

The Microsoft clipboard will synthesize the other bitmap formats if an application does not
explicity place that format on the clipboard.  However, it appears that the clipboard will synthesize
the missing formats incorrectly if a BI_BITFIELDS 32bpp image is placed on the clipboard.

You are safe by placing a BI_RGB 32bpp bitmap on the clipboard.

Paint and Word should be able to paste any available clipboard format without
corruption.

Before I posted the code, I tested it with Paint, Office and other image applications.

All of the applications display the pasted bitmap correctly.  However, only an application
that recognizes the existance of an alpha channel when it receives a paste will display
the image with transparency.  Eventhough the CF_DIBV5 clipboard format and the
BITMAPV5HEADER will explicitly tell an application that an alpha channel is present,
most applications ignore it!

An example of a "smart" "alpha channel aware" component is Microsoft's ImageList.

The ImageList will correctly ascertain that the bitmap has an alpha channel!

My advice is to not only test your code with the applications that you mentioned but
to try and place CF_BITMAP, CF_DIB and CF_DIBV5 versions of your image on the
clipboard and to try to obtain from the clipboard and paste all of these formats
to see if your code works without image corruption.

Example scenarios:
1) Create a DIB with CreateDIBSection with the BITMAPV5HEADER and place
    the HBITMAP on the clipboard.
2) Create a packed DIB with a BITMAPINFOHEADER (i.e., BI_RGB 32bpp with alpha
    channel) and place that global memory handle on the clipboard with CF_DIB.
3) Create a packed DIBV5 with a BITMAPV5HEADER (i.e., BI_RGB 32bpp with alpha
    channel) and place that global memory handle on the clipboard with CF_DIBV5.
4) Grab the above from the clipboard and put them in a Microsoft ImageList.
    The ImageList will correctly identify the images
    with an alpha channel.  Check with Microsoft's ImageList.GetItemFlags
    with the ILIF_ALPHA flag.

  "Bill Henning" <j...@at-actipro.software.com> wrote in message news:OTfDymzBGHA.412@TK2MSFTNGP15.phx.gbl...
  Ok, while I had the cutting and pasting of images working fine within my application, I've found some new issues.  

  1) If I copy an image from my app and paste it into Paint, it looks corrupted.
  2) If I copy an image from Paint and paste it into my app, it looks corrupted.
  3) If I copy an image from my app and paste it into Word while customizing toolbars and using the customize menu's "Paste Button Image", it looks corrupted.  (Similar to #1)
  4) If I copy an image from Word while customizing toolbars and using the customize menu's "Copy Button Image" and paste it into my app, it looks corrupted.  (Similar to #2)

  I need to get all those scenarios working with transparency.  Here's my complete code listing so far for the Copy and Paste methods but if you'd like I could even write a small project to demo the issue:

  /// <summary>
  /// Copies the specified <see cref="Bitmap"/> to the clipboard using alpha information.
  /// </summary>
  /// <param name="bm">The <see cref="Bitmap"/> to copy.</param>
  internal static void CopyAlphaBitmapToClipboard(Bitmap bm) {
   BitmapData bmData = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadOnly, bm.PixelFormat);
   // uint bufferLen = (uint)(Marshal.SizeOf(typeof(BITMAPV5HEADER)) + (Marshal.SizeOf(typeof(BITFIELDS))) + bmData.Height * bmData.Stride);
   uint bufferLen = (uint)(Marshal.SizeOf(typeof(BITMAPV5HEADER)) + bmData.Height * bmData.Stride);
   IntPtr hMem = GlobalAlloc(GHND | GMEM_DDESHARE, bufferLen);
   IntPtr packedDIBV5 = NativeMethods.GlobalLock(hMem);
   BITMAPV5HEADER bmi = (BITMAPV5HEADER)Marshal.PtrToStructure(packedDIBV5, typeof(BITMAPV5HEADER));
   bmi.bV5Size = (uint)Marshal.SizeOf(typeof(BITMAPV5HEADER));
   bmi.bV5Width = bmData.Width;
   bmi.bV5Height = bmData.Height;
   bmi.bV5BitCount = 32;
   bmi.bV5Planes = 1;
   bmi.bV5Compression = BI_RGB;  // BI_BITFIELDS;
   bmi.bV5XPelsPerMeter = 0;
   bmi.bV5YPelsPerMeter = 0;
   bmi.bV5ClrUsed = 0;
   bmi.bV5ClrImportant = 0;
   bmi.bV5BlueMask = 0x000000FF;
   bmi.bV5GreenMask = 0x0000FF00;
   bmi.bV5RedMask = 0x00FF0000;
   bmi.bV5AlphaMask = 0xFF000000;
   bmi.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
   bmi.bV5GammaBlue = 0;
   bmi.bV5GammaGreen = 0;
   bmi.bV5GammaRed = 0;
   bmi.bV5ProfileData = 0;
   bmi.bV5ProfileSize = 0;
   bmi.bV5Reserved = 0;
   bmi.bV5Intent = LCS_GM_IMAGES;
   bmi.bV5SizeImage = (uint)(bmData.Height * bmData.Stride);
   bmi.bV5Endpoints.ciexyzBlue.ciexyzX = bmi.bV5Endpoints.ciexyzBlue.ciexyzY = bmi.bV5Endpoints.ciexyzBlue.ciexyzZ = 0;
   bmi.bV5Endpoints.ciexyzGreen.ciexyzX = bmi.bV5Endpoints.ciexyzGreen.ciexyzY = bmi.bV5Endpoints.ciexyzGreen.ciexyzZ = 0;
   bmi.bV5Endpoints.ciexyzRed.ciexyzX = bmi.bV5Endpoints.ciexyzRed.ciexyzY = bmi.bV5Endpoints.ciexyzRed.ciexyzZ = 0;
   Marshal.StructureToPtr(bmi, packedDIBV5, false);

   BITFIELDS Masks = (BITFIELDS)Marshal.PtrToStructure((IntPtr)(packedDIBV5.ToInt32() + bmi.bV5Size), typeof(BITFIELDS));
   Masks.BlueMask = 0x000000FF;
   Masks.GreenMask = 0x0000FF00;
   Masks.RedMask = 0x00FF0000;
   Marshal.StructureToPtr(Masks, (IntPtr)(packedDIBV5.ToInt32() + bmi.bV5Size), false);

   // long offsetBits = bmi.bV5Size + Marshal.SizeOf(typeof(BITFIELDS));
   long offsetBits = bmi.bV5Size;
   IntPtr bits = (IntPtr)(packedDIBV5.ToInt32() + offsetBits);

   for (int y = 0; y < bmData.Height; y++) {
    IntPtr DstDib = (IntPtr)(bits.ToInt32() + (y* bmData.Stride));
    IntPtr SrcDib = (IntPtr)(bmData.Scan0.ToInt32() + ((bmData.Height - 1 - y)* bmData.Stride));

    for (int x = 0; x < bmData.Width; x++) {
     Marshal.WriteInt32(DstDib, Marshal.ReadInt32(SrcDib));
     DstDib = (IntPtr)(DstDib.ToInt32() + 4);
     SrcDib = (IntPtr)(SrcDib.ToInt32() + 4);
    }
   }

   bm.UnlockBits(bmData);

   NativeMethods.GlobalUnlock(hMem);

   NativeMethods.OpenClipboard(IntPtr.Zero);
   NativeMethods.EmptyClipboard();
   NativeMethods.SetClipboardData(CF_DIBV5, hMem);
   NativeMethods.CloseClipboard();  
  }

  /// <summary>
  /// Pastes a <see cref="Bitmap"/> from the clipboard.
  /// </summary>
  /// <returns>The <see cref="Bitmap"/> that was pasted.</returns>
  internal static Bitmap PasteAlphaBitmapFromClipboard() {
   NativeMethods.OpenClipboard(IntPtr.Zero);
   IntPtr hMem = NativeMethods.GetClipboardData(CF_DIBV5);
   if (hMem == IntPtr.Zero) {
    NativeMethods.CloseClipboard();  
    return null;
   }

   IntPtr packedDIBV5 = NativeMethods.GlobalLock(hMem);
   BITMAPV5HEADER bmi = (BITMAPV5HEADER)Marshal.PtrToStructure(packedDIBV5, typeof(BITMAPV5HEADER));

   Bitmap bitmap = new Bitmap(bmi.bV5Width, bmi.bV5Height, -(int)(bmi.bV5SizeImage / bmi.bV5Height), PixelFormat.Format32bppArgb,
    new IntPtr(packedDIBV5.ToInt32() + bmi.bV5Size + (bmi.bV5Height - 1) * (int)(bmi.bV5SizeImage / bmi.bV5Height)));

   Bitmap outputBitmap = new Bitmap(bmi.bV5Width, bmi.bV5Height, PixelFormat.Format32bppArgb);
   Graphics g = Graphics.FromImage(outputBitmap);
   g.DrawImage(bitmap, 0, 0, bmi.bV5Width, bmi.bV5Height);
   g.Dispose();

   bitmap.Dispose();

   NativeMethods.GlobalUnlock(hMem);
   NativeMethods.CloseClipboard();  

   return outputBitmap;
  }


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bill Henning  
View profile  
 More options Dec 23 2005, 9:51 am
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Bill Henning" <j...@at-actipro.software.com>
Date: Fri, 23 Dec 2005 09:51:01 -0500
Local: Fri, Dec 23 2005 9:51 am
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
Hi Michael,

I'm sorry to be such a pain on this issue, it's just no matter what I try,
it doesn't work right.

You're right that I should have had the BITFIELDS commented out.  Also, I
made a mistake in my posting before so let me post all the scenarios again.
I'm starting over with a clean project.  I created a tiny sample project
that maybe you could download and try:
http://www.actiprosoftware.com/ClipboardBitmap.zip

It's simply a Form with several buttons on them.  It loads and shows a
transparent image on startup and has buttons for copying and pasting.  I
have a button for copying using BI_RGB and one for using BI_BITFIELDS.  I
have a paste button that uses the API code that we discussed too.  Both the
copy and paste use CF_DIBV5.  I also have copy/paste buttons for .NET
framework code, but ignore those.

So here's the scenarios using my test app:
1) Copy from my app using BI_RGB and paste in my app:  the pasted image
looks perfect.
2) Copy from my app using BI_BITFIELDS and paste in my app:  the pasted
image is offset to the right about two pixels and wraps to the left side.
But other than that, it looks good.
3) Copy from my app using BI_RGB and paste in Paint:  the pasted image looks
good but has a black background where the transparent region should be.
Maybe Paint just isn't transparency aware, which is actually ok for my
purposes.
4) Copy from my app using BI_BITFIELDS and paste in Paint:  the pasted image
is a combination of #2 and #3... it's offset to the right with a black
background.  Also there's a little red, green, and then blue pixel at the
bottom.  This makes me think it's pulling in the masks data as bitmap data.
5) Copy from Paint and past in my app:  The image looks completely garbled,
like a fuzzy TV.
6) Copy from my app using BI_RGB and paste in Word customize mode for a
button:  Same results as #2... image looks good but black background.  I do
need transparency working in Word.
7) Copy from my app using BI_BITFIELDS and paste in Word customize mode for
a button:  Same results as #4... image is offset with black background and
shows 3 RGB pixels at bottom.
8) Copy from Word customize mode for a button and paste in my app:  The "new
Bitmap()" call in my paste method blows up with an "Invalid parameter used"
exception.

Anyhow, that's everything I need to get working.  It seems like we're so
close.  From the above scenarios, here's the remaining issues as I see them:
1) My BI_BITFIELDS copy code is slightly wrong somewhere.  It seems like
it's reading the wrong area of the bitmap data (in the masks area) and maybe
is therefore off by a scanline or so.
2) Pasting a CF_DIBV5 image from my app into Word doesn't retain
transparency.  I need that working one way or another.
3) Pasting from Paint into my app needs fixing since it's all garbled.
4) Pasting from Word into my app needs fixing since it throws an exception.

I'd really appreciate it if you could check out my sample project and modify
it however necessary to get those things functioning.  That's probably
easier than you posting what I should change and then me still not getting
it right with my limited knowledge of this stuff. :)

I'll be happy to post the resulting code in the newsgroup for everyone
else's benefit as well.

Thanks and Happy Holidays,
Bill


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Phillips, Jr.  
View profile  
 More options Dec 23 2005, 12:40 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: "Michael Phillips, Jr." <mphillip...@nospam.jun0.c0m>
Date: Fri, 23 Dec 2005 12:40:00 -0500
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
I made changes to your code and provided comments for those changes.

Send me an email with your correct email address and I will send you the
zip.

Of course, you must make changes to my email address to resolve the obvious
spam prevention alterations that are a necessary evil!

Word will correctly identify an alpha channel bitmap and display it,
if you load or drag and drop an image with an alpha channel.

Word will not correctly identify an alpha channel bitmap if it receives
a paste from the clipboard.  There are several clipboard formats
available on the clipboard for any application (i.e., CF_BITMAP, CF_DIB,
CF_DIBV5, etc.).

Which format an application requests and uses, is up to the application!

It is a good practice to place CF_BITMAP, CF_DIB and CF_DIBV5 versions of
your
images on the clipboard.  If you don't, they will be synthesized by the
clipboard.

Since your application knows ahead of time that the image has an alpha
channel,
placing your version of these clipboard formats obviates the clipboard from
synthesizing the missing formats incorrectly.

It is up to the application to interpret what it receives from the
clipboard!  Most applications
don't bother trying to ascertain whether or not an alpha channel bitmap
format is present
on the clipboard.  That is why you see a black background in Paint and Word.

They render with an opaque background!  Some applications are smart and test
for the presence of an alpha channel.  The Microsoft ImageList used on
WindowsXP
is an example.

Happy Holidays
Michael

"Bill Henning" <j...@at-actipro.software.com> wrote in message

news:eJE1JB9BGHA.2356@tk2msftngp13.phx.gbl...


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Kooijman  
View profile  
 More options Feb 9 2006, 1:52 pm
Newsgroups: microsoft.public.dotnet.framework.drawing
From: Ben Kooijman <benkooij...@discussions.microsoft.com>
Date: Thu, 9 Feb 2006 10:52:28 -0800
Local: Thurs, Feb 9 2006 1:52 pm
Subject: Re: Transparent Image Copy to Clipboard Adds Blue BG
Hello,

I'm facing the exact same problems as Bill (albeit for another purpose) and
am not getting anywhere.

I was wondering if you could send me your last changes or tips on this.
--
----
Ben Kooijman


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »