Arrummzen
asked on
Un-Drawing in VB
I am using this subroutine to draw a red X over a picture box when a usere clicks on it.
__________________________ __________ __________ __________ __
Private Sub Picture1_Click()
Me.AutoRedraw = True
Picture1.AutoRedraw = True
Picture1.Line (0, 0)-(Picture1.ScaleWidth, Picture1.ScaleHeight), vbRed
Picture1.Line (Picture1.ScaleWidth, 0)-(0, Picture1.ScaleHeight), vbRed
End Sub
__________________________ __________ __________ __________ __
I need to have the red X go away after the user has clicked on it a second time. Is there any way to Undraw the lines?
Thank you,
Arrummzen
__________________________
Private Sub Picture1_Click()
Me.AutoRedraw = True
Picture1.AutoRedraw = True
Picture1.Line (0, 0)-(Picture1.ScaleWidth, Picture1.ScaleHeight), vbRed
Picture1.Line (Picture1.ScaleWidth, 0)-(0, Picture1.ScaleHeight), vbRed
End Sub
__________________________
I need to have the red X go away after the user has clicked on it a second time. Is there any way to Undraw the lines?
Thank you,
Arrummzen
or set autoredraw to false before you draw the lines and when you want them to go away set picture1.picture = picture1.image
hi arrummzen,
The standard way to undraw a line is to draw a line over it with the background color. Since your red X is over a picture that would not work. You could just reload the original picture without the X, but that is not an answer to your question. If you want to draw the line with pixels then you can capture each pixel from the picture befor you draw the red pixel. save the picture pixels in an array and then redraw the line with the picture pixels. I think that is the standard way to undraw something you have drawn over a picture...if you wish I can get you the code to capture picture pixels and then redraw them.
leo
The standard way to undraw a line is to draw a line over it with the background color. Since your red X is over a picture that would not work. You could just reload the original picture without the X, but that is not an answer to your question. If you want to draw the line with pixels then you can capture each pixel from the picture befor you draw the red pixel. save the picture pixels in an array and then redraw the line with the picture pixels. I think that is the standard way to undraw something you have drawn over a picture...if you wish I can get you the code to capture picture pixels and then redraw them.
leo
ASKER
Ok let me explain some more. I have a form with one large picture with 32 trees on it. There are 16 on the top and 16 on the bottom. Now I am going to put an empty image box over each tree. When one of these invisible image boxes are clicked on I need a red x to appear in the box.
-------------------------- ---------- ---------- ---------- --
Private Sub Picture1_Click()
Picture1.AutoRedraw = true
Picture1.Line (0, 0)-(Picture1.ScaleWidth, Picture1.ScaleHeight), vbRed
Picture1.Line (Picture1.ScaleWidth, 0)-(0, Picture1.ScaleHeight), vbRed
End Sub
-------------------------- ---------- ---------- ---------- --
The above code draws a line when the image box is clicked. I cant set atoredraw to false because if I do an the user goes to another window for a few seconds the x will go away. I can’t put another line across the old one because then the large picture box in the background will look bad. I don’t want to use line objects because then I have to specify the X and Y locations because I want to be able to resize the image boxes for use on other pages.
This might be hard to do. I will increase the points by 50 to 150.
Thank you for your time,
Arrummzen
--------------------------
Private Sub Picture1_Click()
Picture1.AutoRedraw = true
Picture1.Line (0, 0)-(Picture1.ScaleWidth, Picture1.ScaleHeight), vbRed
Picture1.Line (Picture1.ScaleWidth, 0)-(0, Picture1.ScaleHeight), vbRed
End Sub
--------------------------
The above code draws a line when the image box is clicked. I cant set atoredraw to false because if I do an the user goes to another window for a few seconds the x will go away. I can’t put another line across the old one because then the large picture box in the background will look bad. I don’t want to use line objects because then I have to specify the X and Y locations because I want to be able to resize the image boxes for use on other pages.
This might be hard to do. I will increase the points by 50 to 150.
Thank you for your time,
Arrummzen
Try this, it will still work however picture1 has been resized:
Form_Load()
HideShowLines False
End Sub
Private Sub Picture1_Click()
Set Line1.Container = Picture1
Set Line2.Container = Picture1
' Do the dropping line
Line1.X1 = 0
Line1.X2 = Picture1.ScaleWidth
Line1.Y1 = 0
Line1.Y2 = Picture1.ScaleHeight
' Now the rising line
Line2.X1 = Picture1.ScaleWidth
Line2.X2 = 0
Line2.Y1 = 0
Line2.Y2 = Picture1.ScaleHeight
HideShowLines True
End Sub
Sub HideShowLines(SetVisible as Boolean)
Line1.Visible = SetVisible
Line2.Visible = SetVisible
End Sub
Form_Load()
HideShowLines False
End Sub
Private Sub Picture1_Click()
Set Line1.Container = Picture1
Set Line2.Container = Picture1
' Do the dropping line
Line1.X1 = 0
Line1.X2 = Picture1.ScaleWidth
Line1.Y1 = 0
Line1.Y2 = Picture1.ScaleHeight
' Now the rising line
Line2.X1 = Picture1.ScaleWidth
Line2.X2 = 0
Line2.Y1 = 0
Line2.Y2 = Picture1.ScaleHeight
HideShowLines True
End Sub
Sub HideShowLines(SetVisible as Boolean)
Line1.Visible = SetVisible
Line2.Visible = SetVisible
End Sub
I expect you are using an array of picture boxes:
Private Sub Picture1_Click(Index As Integer)
' these 2 lines next are the giant leap forward:
Set Line1.Container = Picture1(Index)
Set Line2.Container = Picture1(Index)
' Do the dropping line
Line1.X1 = 0
Line1.X2 = Picture1(Index).ScaleWidth
Line1.Y1 = 0
Line1.Y2 = Picture1(Index).ScaleHeigh t
' Now the rising line
Line2.X1 = Picture1(Index).ScaleWidth
Line2.X2 = 0
Line2.Y1 = 0
Line2.Y2 = Picture1(Index).ScaleHeigh t
HideShowLines True
End Sub
Private Sub Picture1_Click(Index As Integer)
' these 2 lines next are the giant leap forward:
Set Line1.Container = Picture1(Index)
Set Line2.Container = Picture1(Index)
' Do the dropping line
Line1.X1 = 0
Line1.X2 = Picture1(Index).ScaleWidth
Line1.Y1 = 0
Line1.Y2 = Picture1(Index).ScaleHeigh
' Now the rising line
Line2.X1 = Picture1(Index).ScaleWidth
Line2.X2 = 0
Line2.Y1 = 0
Line2.Y2 = Picture1(Index).ScaleHeigh
HideShowLines True
End Sub
ASKER
Hmm. Your code looks like it should work but for some reason on I receive a Object required (Error 424) on line the following lines:
Line1.Visible = SetVisible
Line2.Visible = SetVisible
I have tried running the subroutine in a lone module and in the forms main code block. I don’t know what to do.
When I click on the picture box I get the following error Object required (Error 424). I don’t know. I think I am putting the code in rite. This error occurs on the line Set Line1.Container = Picture1(Index)
Tell me if you need any more information.
Thank you for your help,
Arrummzen
Line1.Visible = SetVisible
Line2.Visible = SetVisible
I have tried running the subroutine in a lone module and in the forms main code block. I don’t know what to do.
When I click on the picture box I get the following error Object required (Error 424). I don’t know. I think I am putting the code in rite. This error occurs on the line Set Line1.Container = Picture1(Index)
Tell me if you need any more information.
Thank you for your help,
Arrummzen
Find the toolbox and you will see the line control.
Draw two of them on your form.
I suspect that this could be the problem.
Draw two of them on your form.
I suspect that this could be the problem.
Line controls are strange as they don't have any events.
After you have placed the line controls on the form change the properties so that color and size are set as desired.
After you have placed the line controls on the form change the properties so that color and size are set as desired.
ASKER
Ok. Now there is another problem. I want to click on one picture box and have it draw a x over the picture box and when I click on it again for the x to go away however rite now if I click on a picture box a x appears and when I click on it again nothing happens and then when I click on a different picture box the x moves to the other box. I think I can get this to work with individual boxes however I will give you a extra 10 points if you give me source code to get it to work as I explained above with a control array.
Thank you for your time,
Arrummzen
Thank you for your time,
Arrummzen
So you have to detect if the X is already on a picture.
I think I understand that you want to toggle the X on/off. Click once to turn on. Click again to remove.
You can use and indicator array or the Tag property.
In your form load you need to set:
LastIndex = -1
Private Sub Picture1_Click(Index As Integer)
' is the x on show on a different picture
If LastIndex >= 0 And LastIndex <> Index Then
Picture1(LastIndex).Tag = ""
End If
If Len(Picture1(Index).Tag) = 0 Then
Picture1(Index).Tag = "X" ' set the x on show indicator
' these 2 lines next are the giant leap forward:
Set Line1.Container = Picture1(Index)
Set Line2.Container = Picture1(Index)
' Do the dropping line
Line1.X1 = 0
Line1.X2 = Picture1(Index).ScaleWidth
Line1.Y1 = 0
Line1.Y2 = Picture1(Index).ScaleHeigh t
' Now the rising line
Line2.X1 = Picture1(Index).ScaleWidth
Line2.X2 = 0
Line2.Y1 = 0
Line2.Y2 = Picture1(Index).ScaleHeigh t
HideShowLines True ' show X
Else
Picture1(Index).Tag = "" ' clear then x on show indicator
HideShowLines True ' hide X
End If
LastIndex = Index
End Sub
I think I understand that you want to toggle the X on/off. Click once to turn on. Click again to remove.
You can use and indicator array or the Tag property.
In your form load you need to set:
LastIndex = -1
Private Sub Picture1_Click(Index As Integer)
' is the x on show on a different picture
If LastIndex >= 0 And LastIndex <> Index Then
Picture1(LastIndex).Tag = ""
End If
If Len(Picture1(Index).Tag) = 0 Then
Picture1(Index).Tag = "X" ' set the x on show indicator
' these 2 lines next are the giant leap forward:
Set Line1.Container = Picture1(Index)
Set Line2.Container = Picture1(Index)
' Do the dropping line
Line1.X1 = 0
Line1.X2 = Picture1(Index).ScaleWidth
Line1.Y1 = 0
Line1.Y2 = Picture1(Index).ScaleHeigh
' Now the rising line
Line2.X1 = Picture1(Index).ScaleWidth
Line2.X2 = 0
Line2.Y1 = 0
Line2.Y2 = Picture1(Index).ScaleHeigh
HideShowLines True ' show X
Else
Picture1(Index).Tag = "" ' clear then x on show indicator
HideShowLines True ' hide X
End If
LastIndex = Index
End Sub
Sorry at the end:
HideShowLines False ' hide X
HideShowLines False ' hide X
Private Sub Picture1_Click(Index As Integer)
Dim CrossIsThere As Boolean
Dim BakColor As Long
Dim CrossColor As Long
Dim TheColor As Long
BakColor = Picture1(Index).Point(2 * Screen.TwipsPerPixelX, 0)
CrossColor = vbRed
CrossIsThere = Picture1(Index).Point(0, 0) = CrossColor
If CrossIsThere Then
TheColor = BakColor
Else
TheColor = CrossColor
End If
Picture1(Index).Line (0, 0)-(Picture1(Index).ScaleW idth, Picture1(Index).ScaleHeigh t), TheColor
Picture1(Index).Line (0, Picture1(Index).ScaleHeigh t)-(Pictur e1(Index). ScaleWidth , 0), TheColor
End Sub
Dim CrossIsThere As Boolean
Dim BakColor As Long
Dim CrossColor As Long
Dim TheColor As Long
BakColor = Picture1(Index).Point(2 * Screen.TwipsPerPixelX, 0)
CrossColor = vbRed
CrossIsThere = Picture1(Index).Point(0, 0) = CrossColor
If CrossIsThere Then
TheColor = BakColor
Else
TheColor = CrossColor
End If
Picture1(Index).Line (0, 0)-(Picture1(Index).ScaleW
Picture1(Index).Line (0, Picture1(Index).ScaleHeigh
End Sub
or you could just save the crossed/not crossed state in the picture's tag property
that way you wont even have to test if point(0,0) is red
that way you wont even have to test if point(0,0) is red
and now that i think of it, you probably even know the background color of the picturebox,so you dont even have to look for it
Private Sub Picture1_Click(Index As Integer)
Dim TheColor As Long
If Picture1(Index).Tag = "Cross" Then
TheColor = &H80000005 ' the color you gave at design-time
Picture1(Index).Tag = "NoCross"
Else
TheColor = vbRed
Picture1(Index).Tag = "Cross"
End If
Picture1(Index).Line (0, 0)-(Picture1(Index).ScaleW idth, Picture1(Index).ScaleHeigh t), TheColor
Picture1(Index).Line (0, Picture1(Index).ScaleHeigh t)-(Pictur e1(Index). ScaleWidth , 0), TheColor
End Sub
Dim TheColor As Long
If Picture1(Index).Tag = "Cross" Then
TheColor = &H80000005 ' the color you gave at design-time
Picture1(Index).Tag = "NoCross"
Else
TheColor = vbRed
Picture1(Index).Tag = "Cross"
End If
Picture1(Index).Line (0, 0)-(Picture1(Index).ScaleW
Picture1(Index).Line (0, Picture1(Index).ScaleHeigh
End Sub
easier still and works even when there is a background picture:
Private Sub Picture1_Click(Index As Integer)
If Picture1(Index).Tag = "Cross" Then
Picture1(Index).Tag = "NoCros"
Picture1(Index).Cls
Else
Picture1(Index).Tag = "Cross"
Picture1(Index).Line (0, 0)-(Picture1(Index).ScaleW idth, Picture1(Index).ScaleHeigh t), vbRed
Picture1(Index).Line (0, Picture1(Index).ScaleHeigh t)-(Pictur e1(Index). ScaleWidth , 0), vbRed
End If
End Sub
Private Sub Picture1_Click(Index As Integer)
If Picture1(Index).Tag = "Cross" Then
Picture1(Index).Tag = "NoCros"
Picture1(Index).Cls
Else
Picture1(Index).Tag = "Cross"
Picture1(Index).Line (0, 0)-(Picture1(Index).ScaleW
Picture1(Index).Line (0, Picture1(Index).ScaleHeigh
End If
End Sub
ASKER
Ok, I need the picture boxes to be invisible but when I set visible to false the Xs stop working. I have a background and I am using these little invisible picture/image boxes (which ever works) to draw a red x ware it is and to mark a global variable that the box was selected.
I have trees on the background. I want to click on a tree and have an X appear over the tree and the global variable marked. I want to be able to click on a tree with an X on it and have the global set to false and for the X to go away. I want have one background and I am thinking of putting an invisible image/picture box over each tree so that I can tell when each tree is clicked on. I know I am asking for a lot so I am increasing the points to 250.
I have trees on the background. I want to click on a tree and have an X appear over the tree and the global variable marked. I want to be able to click on a tree with an X on it and have the global set to false and for the X to go away. I want have one background and I am thinking of putting an invisible image/picture box over each tree so that I can tell when each tree is clicked on. I know I am asking for a lot so I am increasing the points to 250.
When you make the picture box not visible it wont handle any events. So you need to place another, empty, picture box under the picture box that is not visible.
The empty boxes should be display ordered like:
picEmpty(Index).Zorder 1 ' this will force the box
Hope this helps.
The empty boxes should be display ordered like:
picEmpty(Index).Zorder 1 ' this will force the box
Hope this helps.
Woops, clicked to early....
picEmpty(Index).Zorder 1 ' this will force the box under the main box when it is visible.
Give picEmpty the same click event code and dimensions as picture1
picEmpty(Index).Zorder 1 ' this will force the box under the main box when it is visible.
Give picEmpty the same click event code and dimensions as picture1
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
oh yes place the labels ON the picturebox, do NOT place them on the form and then move them over the picturebox
That's a good point pierrecampe, label boxes could be usefull in the case of one picture with hot spots.
If you wish to use line controls, place them on your picture.
Here are some other tips:
At design time give the labels a border and send all label elements in form load like:
Sub Form_load()
dim c as long
For C=0 to MaxLabelElements
Label1(c).BorderStyle = 0
next c
End Sub
Private Sub Label1_Click(Index As Integer)
If Len(Label1(Index).Tag) = 0 Then
Label1(Index).Tag = "X" ' set the x on show indicator
' Do the dropping line
Line1.X1 = Label1(Index).Left
Line1.X2 = Label1(Index).Left + Label1(Index).Width
Line1.Y1 = Label1(Index).Top
Line1.Y2 = Label1(Index).Top + Label1(Index).Height
' Now the rising line
Line2.X1 = Label1(Index).Left + Label1(Index).Width
Line2.X2 = Label1(Index).Left
Line2.Y1 = Label1(Index).Top
Line2.Y2 = Label1(Index).Top + Label1(Index).Height
HideShowLines True ' show X
Else
Label1(Index).Tag = "" ' clear then x on show indicator
HideShowLines False ' hide X
End If
End Sub
If you wish to use line controls, place them on your picture.
Here are some other tips:
At design time give the labels a border and send all label elements in form load like:
Sub Form_load()
dim c as long
For C=0 to MaxLabelElements
Label1(c).BorderStyle = 0
next c
End Sub
Private Sub Label1_Click(Index As Integer)
If Len(Label1(Index).Tag) = 0 Then
Label1(Index).Tag = "X" ' set the x on show indicator
' Do the dropping line
Line1.X1 = Label1(Index).Left
Line1.X2 = Label1(Index).Left + Label1(Index).Width
Line1.Y1 = Label1(Index).Top
Line1.Y2 = Label1(Index).Top + Label1(Index).Height
' Now the rising line
Line2.X1 = Label1(Index).Left + Label1(Index).Width
Line2.X2 = Label1(Index).Left
Line2.Y1 = Label1(Index).Top
Line2.Y2 = Label1(Index).Top + Label1(Index).Height
HideShowLines True ' show X
Else
Label1(Index).Tag = "" ' clear then x on show indicator
HideShowLines False ' hide X
End If
End Sub
yes i think the method with line controls is probably better, because the paintpicture method is dependant of the kind of picture thats in the picturebox and of the autoredraw property
if autoredraw is true picture1.image will not work you will have to use picture1.picture
picture1.image will work independant of what kind of picture (bitmap,metafile etc...)but only if autoredraw is false
picture1.picture will probably not work with metafiles
for picture1.picture to work, the visual picture in the picturebox has to have exactly the same dimensions as the real picture,what is seldom the case with metafiles
if using the line control system i would suggest making them array's to, also i suggest not using global variables,you can always check if a tree is crossed by looping trouch their tag property's
if autoredraw is true picture1.image will not work you will have to use picture1.picture
picture1.image will work independant of what kind of picture (bitmap,metafile etc...)but only if autoredraw is false
picture1.picture will probably not work with metafiles
for picture1.picture to work, the visual picture in the picturebox has to have exactly the same dimensions as the real picture,what is seldom the case with metafiles
if using the line control system i would suggest making them array's to, also i suggest not using global variables,you can always check if a tree is crossed by looping trouch their tag property's
Yes and, if you need to have more then one item X'ed at the same time you will have to use an array of line controls. Like: line1(Index) and Line2(Index)....
Hi
Dim pic As StdPicture
'........
'Before drawing cross:
Set pic = Picture1.Picture
'Draw cross
'To restore:
Picture1.Picture = pic
Picture1.refresh
Cheers
Dim pic As StdPicture
'........
'Before drawing cross:
Set pic = Picture1.Picture
'Draw cross
'To restore:
Picture1.Picture = pic
Picture1.refresh
Cheers
ASKER
Thank you very much every one for your help. By the way I know it was because I didn’t explain my question well. I don’t know if points mean anything to any of you. I just wanted to try to make up for my bad explanation. Anyhow thanks a lot.
Thank you for your time,
Arrummzen
Thank you for your time,
Arrummzen
line1.x1=2
line1.y1=2
line1.x2=100
line1.y2=100
etc.