Link to home
Start Free TrialLog in
Avatar of Arrummzen
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
Avatar of inthedark
inthedark
Flag of United Kingdom of Great Britain and Northern Ireland image

The easy way to do this is use 2 line controls. You can show/hide then as you wish.

line1.x1=2
line1.y1=2
line1.x2=100
line1.y2=100

etc.
Avatar of Benjy
Benjy

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
Avatar of Arrummzen

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
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
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).ScaleHeight
   
    ' Now the rising line
    Line2.X1 = Picture1(Index).ScaleWidth
    Line2.X2 = 0
    Line2.Y1 = 0
    Line2.Y2 = Picture1(Index).ScaleHeight
   
    HideShowLines True

End Sub
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
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.
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.
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
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).ScaleHeight
       
        ' Now the rising line
        Line2.X1 = Picture1(Index).ScaleWidth
        Line2.X2 = 0
        Line2.Y1 = 0
        Line2.Y2 = Picture1(Index).ScaleHeight
       
        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
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).ScaleWidth, Picture1(Index).ScaleHeight), TheColor
    Picture1(Index).Line (0, Picture1(Index).ScaleHeight)-(Picture1(Index).ScaleWidth, 0), TheColor
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
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).ScaleWidth, Picture1(Index).ScaleHeight), TheColor
    Picture1(Index).Line (0, Picture1(Index).ScaleHeight)-(Picture1(Index).ScaleWidth, 0), TheColor
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).ScaleWidth, Picture1(Index).ScaleHeight), vbRed
       Picture1(Index).Line (0, Picture1(Index).ScaleHeight)-(Picture1(Index).ScaleWidth, 0), vbRed
    End If
End Sub
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.
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.
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
ASKER CERTIFIED SOLUTION
Avatar of pierrecampe
pierrecampe

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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
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
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
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