Allow user to draw on Image Box or Picture Box

I am stuck between a rock & a hard place:
Situation: I have a form with 18 tiles of image boxes. 9 of which lie on top of the other 9 and have transparent parts so that the underlying tiles show through. I want to allow the user to be able to draw on these image boxes.
What I tried to do: I found through some reading that the PSet command will not work for drawing on image boxes, so I tried using pictureboxes instead; however, now I cannot see through the first layer of picture boxes so that I can see the bottom layer. PSet works fine on the picture boxex.
Summary: So what I need is a way (without BitBlt, cuz any code I get from anybody on this does not work) to be able to draw on a picture which is a composite of two pictures. Any ideas? I do not understand how to get the Overlay function to work either...I need complete code, not reference to general theories or www.tutorial.com stuff. Thanks so much.

I am trying to draw on the top image. Yeah, I thought of that...problem is that I really need the top image to be able to be drawn on, and also have a BackStyle of transparent. Am curious if XGlassPicture Control is what I am looking for, and if so where to get it. I may have to create my on User Control, something I nothing about. Hmmmmm, what a world. Thanks.

Oh Dear...User Control, eh? I have just begun to scratch the surface of how to create a User Control, and each attempt fails miserably (Vingamel <----new at this). Any chance you could give me a quick rundown on creating the UserControl and how to wrap the picturebox. Thanks gobs. --Vingamel

To Sendoh: No, the imagebox has no BackStyle property. I premade pictures with transparent parts and plopped them into image boxes. Which is great until I try to do anything similar to PSet on the imageboxes (that is, allow the user to draw on the imagebox)...sooooo, I am going to work with mdlilly's proposal and see if it works, but I still open to any other ideas (the main objective: User be able to draw on an image or picture which you can see through). Thanks Sendoh. --Vingamel

Yes indeed, I do need some help with this UserControl/wrapped picturebox procedure. I am increasing the points a bit to hopefully get complete step-by-step help here...like:
1) How do I create the UserControl and wrap the Picture box in it?
2) Where does the code mentioned above get put? Declarations? UserControl_GotFocus? Form_Load?
Thank ya. --Vingamel

What follows is the code for a picture box, wrapped in a user control, that supports transparency. I only give this because I cost me 3 weeks of pain and about 5 calls to Microsoft tech support to totally hash this out. There are limitations, but it does transparency (a feat that Microsoft at first claimed was impossible *brag, brag*). Anyways...

The process ...
1) create an new user control
2) place a picture box on the control (I named it "Pic")
3) place an image list on the control (I named it "Images")
4) normally run the "Add usercontrol wizard" (to add the default functionality of the control you are wrapping, but I have already done this.
5) add a handler for the Pic's on paint function. to do all the drawing.
6) you will need to turn the "AutoRedraw" property of the usercontrol off (you will get some terrible flicker otherwise.
7) the "ColorPic" property is a string which needs to be the file name (full path) of the picture you want be transparent. The transparent color is true black &h00000000 where the mask pic is true white &hffffffff
8) the "MaskPic" is a monochrome mask of the picture you want to be transparent. True White is for the transparent region, and true black is for the non-opaque region.
9) the property "Transparent" is a boolean flag for whether to use transparency or not.
10) There are some limitations with this method, such as it only
will do transparency between this custom control and it's parent.

The basic concept here is that I to a straight copy of the background onto the picture box, then I bitwise AND the mask picture onto the picture box (black in the mask picture blacks the image, white leaves it intact). Then I bitwise OR the color picture onto the picture box, black in the picture box OR the color = the color, background image OR black is the background image.

If you have more questions about this control post them and I will check back regularly to answer them. There may be some peices of this control that may not make sence, this is because in my control I implement several interfaces for use in an application, and my not have deleted all the interface crap, sorry if that happens :)

You will also have to look up some of the API Calls and constants that I use, or if you have alot of trouble finding them ask and I will post them too.

'Get the mouse's position on the screen and the picture's position on the screen,
'then calculate the mouse's position relative to the picture
Call GetCursorPos(pt)
Call GetWindowRect(Pic.hwnd, Box)
pt.x = pt.x - Box.Left
pt.y = pt.y - Box.Top
'Get the pixel at the mouse's cordinates from the mask picture and compare that color to
'black (aka 0), if they match we are in the mask, or inother words in the non tranparent
'portion of the image.
If GetPixel(myMaskDC, pt.x, pt.y) = 0 Then
isInMask = True
Else
isInMask = False
End If
GoTo Final
Catch:
Call Err.Raise(Err.Number, ERR_MSG, Str(Err.Number) + " " + Err.Description)
Final:
End Function

''WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
''MappingInfo=UserControl,UserControl,0,Width
Public Property Get Width() As Long
On Error GoTo Catch
Width = UserControl.Width
GoTo Final
Catch:
Call Err.Raise(Err.Number, ERR_MSG, Str(Err.Number) + " " + Err.Description)
Final:
End Property

'create the dc and bmp for the dc and bmp to use to refresh the picture
If myFinishedDC <> 0 Then
Call DeleteDC(myFinishedDC)
End If
myFinishedDC = CreateCompatibleDC(Pic.hdc)
If myFinishedBMP <> 0 Then
Call DeleteObject(myFinishedBMP)
End If
myFinishedBMP = CreateCompatibleBitmap(Pic.hdc, Pic.Width, Pic.Height)
Refresh
GoTo Final
Catch:
Call Err.Raise(Err.Number, ERR_MSG, Str(Err.Number) + " " + Err.Description)
Final:
End Sub

Okay...bear with me here...for me this is like, "son, this is particle accelerator...put it together". Lemme see...LR_LOADFROMFILE came up with Variable Not Defined, so I commented it out.
Call DeleteDC came up with Sub or Function not defined.
Your step 5, add a handler for the Pic's paint function...is this in the code or is this something I need to add?
I apologize but all of this UserControl stuff is brand-spankin' new, and I want to learn it, but at the same time I don't want to be a pest.
Do I save the user control (once functional) and plop it onto a new form to begin? Thanks. If I get this working I'll up the points even more because this is the longest I've been stalled in my project. --Vingamel Brady.Boyd@Yellowcorp.com

Hey don't sweat it, I busted my butt for what seems like forever on trying to get transparency in VB.

The Pic_Paint function is already in there, I was just explaining the process I went through to do what I did. Since it is the Pic_Paint function that gets called whenever windows sends a paint message to that picture box, it will be the function you will do most of your "hard core coding" in when it comes to graphics.

Once you have a working control, you can compile it into and ocx and then load it like you would any control and then plop it on any old form you would like, and hopefully (fingers crossed) it will do what you want it to do.

If you have any more questions, or if I still am missing some code, just tell me and I'll do my best to rectify the situation.

M. David Lilly

place this code in a module:
Public Const LR_LOADFROMFILE = &H10
Public Const LR_MONOCHROME = &H1
Public Const LR_SHARED = &H8000&
Public Const IMAGE_BITMAP = 0

'Delete DC's if you create them
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
'Creates a bitmap that is compatible with a given DC
Public Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long) As Long
'Creates a DC that is compatible to a given dc
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
'Delete DC's if you create them
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
'Used for tiling
'Gets the window rectangle in screen cordinates
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long
'Creates a handle to a bitmap in memory from a bitmap file
Public Declare Function LoadImage Lib "user32" Alias _
"LoadImageA" (ByVal hInst As Long, _
ByVal lpsz As String, _
ByVal un1 As Long, _
ByVal n1 As Long, _
ByVal n2 As Long, _
ByVal un2 As Long) As Long
'Selects an object to use on a DC and returns the last object (should be saved to restore it)
Public Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, _
ByVal hObject As Long) As Long

Here is another module I added sorry forgot about it earlier:
Option Explicit

'This function requres that the VB project include the control that has ImageList in it
'Probably Microsoft Common Controls 6.0
'This function uses a mask and a color picture to tranparently put the color picture onto a
'picture box
'Limitations:
'- must have the tranparent color on the color pic be black
'- must have a black and white picture that serves as a mask where the visible portion of the
' color picture is black and the invisible portion is white.
Public Sub paintBlt(ByVal aColorPic As String, _
ByVal aColorKey As String, _
ByVal aMaskPic As String, _
ByVal aMaskKey As String, _
ByRef aImageList As MSComctlLib.ImageList, _
ByRef aPic As PictureBox)
On Error GoTo Catch
If isAvailable(aMaskPic) And aImageList.ListImages.Count > 0 Then
'Bitwise AND the mask picture with the background, since the mask is black and white
'the result will be a picture with a black hole where the color image will be put, and
'since white (RGB == 1) anything and 1 is anything
Call aPic.PaintPicture(aImageList.ListImages(aMaskKey).Picture, _
0, _
0, _
, _
, _
, _
, _
, _
, _
vbSrcAnd) 'vbSrcAnd is the AND flag
End If

If isAvailable(aColorPic) And aImageList.ListImages.Count > 0 Then
'Bitwise OR the color picture onto the picturebox. Since the transparent color is
'black (RGB == 0) anything OR anything is anything, and since there is a black hole
'where the color picture will be the color picture OR the black hole becomes the color
'picture.
Call aPic.PaintPicture(aImageList.ListImages(aColorKey).Picture, _
0, _
0, _
, _
, _
, _
, _
, _
, _
vbSrcPaint) 'vbSrcPaint is the OR flag
End If
GoTo Final
Catch:
Call Err.Raise(Err.Number, ERR_MSG, Str(Err.Number) + " " + Err.Description)
Final:
End Sub

Okay, plopped first part into 1st module, and second part into second module, and got error message: Ambiguous Name detected:
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Thanks. --Vingamel

Okay, plopped first part into 1st module, and second part into second module, and got error message: Ambiguous Name detected:
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Thanks. --Vingamel

Okay, plopped first part into 1st module, and second part into second module, and got error message: Ambiguous Name detected:
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Thanks. --Vingamel

Oh...you had it listed twice (see above) and I didn't notice it...just cut & paste it now. Now I have message: User-Defined type not defined:
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

sorry to keep bugging you, and normally I would just debug this stuff, but being new to API stuff, I'm like a baboon trying to set the time on the VCR

Oh...you had it listed twice (see above) and I didn't notice it...just cut & paste it now. Now I have message: User-Defined type not defined:
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

sorry to keep bugging you, and normally I would just debug this stuff, but being new to API stuff, I'm like a baboon trying to set the time on the VCR

Oh...you had it listed twice (see above) and I didn't notice it...just cut & paste it now. Now I have message: User-Defined type not defined:
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

sorry to keep bugging you, and normally I would just debug this stuff, but being new to API stuff, I'm like a baboon trying to set the time on the VCR

Oh...you had it listed twice (see above) and I didn't notice it...just cut & paste it now. Now I have message: User-Defined type not defined:
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

sorry to keep bugging you, and normally I would just debug this stuff, but being new to API stuff, I'm like a baboon trying to set the time on the VCR

Oh...you had it listed twice (see above) and I didn't notice it...just cut & paste it now. Now I have message: User-Defined type not defined:
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

sorry to keep bugging you, and normally I would just debug this stuff, but being new to API stuff, I'm like a baboon trying to set the time on the VCR

Oh...you had it listed twice (see above) and I didn't notice it...just cut & paste it now. Now I have message: User-Defined type not defined:
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

sorry to keep bugging you, and normally I would just debug this stuff, but being new to API stuff, I'm like a baboon trying to set the time on the VCR

Oh...you had it listed twice (see above) and I didn't notice it...just cut & paste it now. Now I have message: User-Defined type not defined:
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

sorry to keep bugging you, and normally I would just debug this stuff, but being new to API stuff, I'm like a baboon trying to set the time on the VCR

Oh...you had it listed twice (see above) and I didn't notice it...just cut & paste it now. Now I have message: User-Defined type not defined:
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

sorry to keep bugging you, and normally I would just debug this stuff, but being new to API stuff, I'm like a baboon trying to set the time on the VCR

There is a tool you can use it is called something like API viewer or somesuch you should be able to get to it by clicking on Add-ins->Add-in Manager you can use this to get API stuff when you know what to look for, else you can just do it manually from help *ooooo help* :P

You'll need to put these in a module:
Public Type POINTAPI
x As Long
y As Long
End Type

Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type

Mr. Lilly: You have been very patient with me on this. I will only have time tomorrow to work on this some more...do you want the points I have offered now or would you prefer to wait until I get this working (in which I will throw in some more points). Regarding your OS/Compiler question: I am not certain what this means...I am on Windows 95 at home and NT at work, and I use the compiler I guess that comes with VB 6.0. Thanks!! --Vingamel

As far as to points go ... really they are not that big of a deal to me, so what ever/when ever you want is fine. If you have any more questions feel free. I still remember a few months ago when I posted a similar question ang got zero usable responces.

Maybe I am doing something wrong. I have all the code in place as you have here, the ImageList & Picturebox on the form and named correctly. I then hit RUN and get error: Compile Error: User-Defined Type Not Defined. This is in Module 1, Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long. Am I doing something wrong. Thanks. --Vingamel

I commented out the line noted above and hit RUN and now I get a SUB or FUNCTION not DEFINED on this code:
Private Function SetMaskPic(ByVal aMaskPic As String, _
ByVal anImageListKey As String, _
ByRef aMaskDC As Long, _
ByRef aMaskBMP As Long) As Boolean
On Error GoTo Catch
If isAvailable(aMaskPic) Then...

Okay, got that done, but still having same problem with GetWindowRectLIB where it shows User-Defined Type not Defined. So I commented it out again just to check for other things and got a Sub or Function not defined on the RECT in the following:
Private Sub Pic_Paint()
On Error GoTo Catch
If isTransparent Then 'we are using tranparency
Pic.Picture = Nothing 'clear the current picture
If Not isPainted Then 'the current image needs to be updated not just reloaded
Dim kid As RECT
I assume this is because of the line I had to comment out...
Also, when I run this it opens Internet Explorer with the following address: C:\Program Files\Microsoft Visual Studio\VB98\UserControl1.html with a blank screen.

Okay, got that done, but still having same problem with GetWindowRectLIB where it shows User-Defined Type not Defined. So I commented it out again just to check for other things and got a Sub or Function not defined on the RECT in the following:
Private Sub Pic_Paint()
On Error GoTo Catch
If isTransparent Then 'we are using tranparency
Pic.Picture = Nothing 'clear the current picture
If Not isPainted Then 'the current image needs to be updated not just reloaded
Dim kid As RECT
I assume this is because of the line I had to comment out...
Also, when I run this it opens Internet Explorer with the following address: C:\Program Files\Microsoft Visual Studio\VB98\UserControl1.html with a blank screen.

The default way to debug controls in VB is through IE, what you need to do so that you get something, is to fill out the DEF_COLOR_IMAGE (or PIC I don't recal) property. But for more ture functionality you need to place this control on a form. Do this by adding a form to your project then setting the starup object as that form. You will also need to switcht the project type from ActiveX control to Standard .EXE

Yes, I know I have it (BitBlt Function)saved on my computer at home, but if you have it handy I can plop it in now and give 'er a test run. I have increased the points. You deserve it for your patience and beyond-the-call-of-duty assistance. --Ving

'Delete DC's if you create them
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
'Creates a bitmap that is compatible with a given DC
Public Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long) As Long
'Creates a DC that is compatible to a given dc
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
'Delete DC's if you create them
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
'Used for tiling
'Gets the window rectangle in screen cordinates
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long
'Creates a handle to a bitmap in memory from a bitmap file
Public Declare Function LoadImage Lib "user32" Alias _
"LoadImageA" (ByVal hInst As Long, _
ByVal lpsz As String, _
ByVal un1 As Long, _
ByVal n1 As Long, _
ByVal n2 As Long, _
ByVal un2 As Long) As Long
'Selects an object to use on a DC and returns the last object (should be saved to restore it)
Public Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, _
ByVal hObject As Long) As Long

Already had those in, Sir, per earlier stuff you sent me. I found GetPixel at http://www.perplexed.com/GPMega/vb/ddtut02.htm
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
So next I need to find the GetCursorPos Function.
We're so close...my program that will help me take over the whole world is almost there. :-) I am going to accept your answer now...I hope you can still answer any questions as I tweak this thing. Thank you.
--Vingamel AKA Brady.Boyd@Yellowcorp.com

Just as irony/humor/sucks to be me side, today we had some MS senior consultants in, and they were looking over my code, and they informed me of a supposed WAY better method, but I have not had a chance to try it out yet. If you are interested it involves the OnHitTest event which I didn't know existed, but ... per senior MS consultants is the STUFF! Well, there is a tip, I don't know how good of a tip, but it (along with some other stuff) cost the company in excess of $1000 this morning :)

And now I found the GetCursorPos at:http://www.vb-world.net/tips/tip65.html
I compiled, and got no errors. Cheers!!! Whew, I can only imagine the hell you went through to get all this info in the first place. My hats off to you. You have my E-Mail address if you are interested in play-testing my strategy game once it is ready. Thanks. --Brady Boyd

Say, Mr. Lilly: I am hitting a wall on a couple of things.
1) When I try to change UserControl Transparent property to True I get a Stack 28 error.
2) Second, I can't figure out how to use the darn thing now that I have it working. How do I get layers of images into the usercontrol so that I can get the same effect as Overlay (see original question). Thanks. --Vingamel

Introduction
In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function. While writing that article I realized that no o…

As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…

Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…