Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Print picturebox with transparent background image 2

Status
Not open for further replies.

waytech2003

Programmer
Jul 14, 2003
316
US
I am trying to print the contents of a Picturebox, named Pic, that contains a gif with a transparent background.

I find that in using the PaintPicture method the transparency fails. It results in the image with a white rectangle the size of the picture control.

The reason I need this to be transparent is the first thing I do when creating this page is place a differant faint picture on the page as a watermark. I then print all the text over that. The printed text is working fine, it's just the second printed picturebox that is not working the way I want.

Is there some transparency setting that I am missing?

Printer.PaintPicture Pic.Picture, X1, Y1, Pic.ScaleWidth,Pic.ScaleHeight


 
>a Picturebox, named Pic, that contains a gif with a transparent background

Sadly, it doesn't. LoadPicture converts your source into a Windows bitmap. And a Windows bitmap contains no transparancy information. And neither does PaintPicture. So,

>Is there some transparency setting that I am missing?

No.

Hmm, you say, but Windows can draw transparent images - cursors, icons, that sort of thing. How does it do that? Well, the overview of the traditional method is that it takes the original image and a mask of the original image (the mask shows which bits of the original image are opaque - 0 - and which bits are transparent - 1). You then do three bitblts. The first XORs the source image into the destination (if you looked at the image now it would look vaguely like a colour negative of your source), the second ANDs the mask into the destination which results in the transparent areas being untouched and the opaque areas become black. In The third bitblt we once again XOR the source into the destination. This causes the trasparent areas to revert to their original state (i.e whatever was originally in the destination), whilst the black areas assume the values from the source. Et voila, you have created the illusion of transparency.

You'll find a number of examples of this technique if you do a keyword search in this forum

But it seems a lot of work. Is there any way we can get Windows to do any of it for us? Well of course ...

Right, our first challenge seems to be how we generate the mask from our source image. If only VB could do that for us. Well, it can, using the ImageList control. Ah, and the Imagelist control has a Draw function that can take a parameter that tells it to draw transpaently, thus neatly wrapping all of those bitblts into a single call.

So, all you need to know is the colour being used to represent trasparency and set the ImageList control's MaskColor property to that. Then load your source image into the ImageList instead of into a PictureBox or Image

And finally replace

Printer.PaintPicture Pic.Picture, X1, Y1, Pic.ScaleWidth,Pic.ScaleHeight

with

ImageList.ListImages(1).Draw Printer.hDC, X1, Y1, imlTransparent

(note that whilst there appears to be no way of scaling the image via the Draw method this can actually be achieved by setting the ImageWidth and ImageHeight properties of the ImageList to the desired size prior to loading your image into the imagelist; this will resize your image for you)

 
thanks strongm

I placed an ImageList1 control on my form.
Now I need to load the ImageList1 control on my form with the picture from my PictureBox.

In looking at Help for the ImageList I find this is the way to add a picture at runtime.

ImageList1.ListImages.Add(, , Pic.Picture)

Add of course this will not work. Further reading I find that I must SET this object, so then I found...

Set imgX = ImageList1.ListImages.Add(, , Pic.Picture)

What am I to Dim imgX as?
I tried Image and Picturebox and that does not work.

 
ImageList1.ListImages.Add , , Pic.Picture

or

Call ImageList1.ListImages.Add(, , Pic.Picture)
 

strongm, you never cease to amaze me!

[gray]Experience is something you don't get until just after you need it.[/gray]
 
With further testing this morning, I found that this does not do exactly what I need. Yes it is transparent when drawing on a form, as it lets the color of the background form show through.

However as I stated in my OP, I am printing this picture over a faint watermark picture on my printer. I still can not get it to be transparent there. It draws the new image, but with a white rectangle as it's background. Am I doing something wrong, or do I need a different solution?
 
That is sadly indicating a limitation in the device driver for your printer (a fair number of printer drivers suffer the same problem).

Unfortunately, the only real way around this that I am aware of is to compose your entire image in a memory DC, where blitting is fully supported to create the blended proof, and then blit that in it's entirety to the preinter hDC.
 
(oh, and don't blame the printer driver too much; technically one isn't really supposed to blit between different the DCs of different types of device)
 
Thanks for you help.

I will look into your "Memory DC" suggestion. Any clues as to where I might learn about this technique?
 
Search box at the top of the page using 'memory dc' brings up a number of recent posts, including thread222-1387082 and thread222-1423165 (amongst others). You can also try
___________________________________________________________
If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
Steam Engine Prints
 
For wayward printers a call to the following API may be worth a try. Works for me when printing text over a previously printed graphic (Font.transparent does not always work), could be it may work for you when printing one graphic over another.

Public Declare Function SetBkMode Lib "gdi32" (ByVal hdc As Long, ByVal nBkMode As Long) As Long
Public Const TRANSPARENT = 1

call with;

'code to print graphic

SetBkMode Printer.hdc, TRANSPARENT 'otherwise overprinted text may print with solid background

'code to print my text (your graphic)
 
Won't help*. SetBkMode only affects how text, hatched brushes, and non-solid pen styles that are are rendered, not bitmaps.

One approach worth trying before resorting to the memory DCs might be to to use the low-level icon drawing routines rather than ImageList's .Draw method. Again this isn't really hard work. We need to declare one API call, and a constant

Private Declare Function DrawIconEx Lib "user32" Alias "DrawIconEx" (ByVal hdc As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long
Public Const DI_NORMAL = &H3

After which the drawing routine changes from

ImageList.ListImages(1).Draw Printer.hDC, X1, Y1, imlTransparent

to

DrawIconEx Printer.hDC, X1, Y1, , ImageList1.ListImages(1).ExtractIcon.Handle, Width, Height, 0&, 0, DI_NORMAL


*Some (a very, very few; I've never actually found one) video device drivers have an automatic transparent blitting capability that can be activated by setting SetBkMode to NEWTRANSPARENT. You can test for the capability by checking the C1_TRANSPARENT bit of the CAPS1 capability word returned by the GetDeviceCaps function. If the capability is supported then the background colour of the destination is used to define what colour in the source image will be treated as transparent during a blit.
 
Strongm again shows his encyclopedic grasp of matters obscure and arcane... :) Well done, strongm, another star.
 
HughLerwill
Thanks, yes I know about that text problem and have that in all my printing applications.

strongm
No luck. I have tried the following in all 7 Printer.Scalemodes. Nothing of the image gets drawn on the page.

DrawIconEx Printer.hdc, _
1, 1, _
ImageList1.ListImages(1).ExtractIcon.Handle, _
ImageList1.ListImages(1).Picture.Width, _
ImageList1.ListImages(1).Picture.Height, _
0&, 0, DI_NORMAL
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top