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 Shaun E on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem working with transparent control

Status
Not open for further replies.

MikeBronner

Programmer
May 9, 2001
756
US
Hi all,

I was wondering if someone has come across this problem and has found a solution:

I have a transparent control, which when click, should add a shape control at the spot that is clicked. This works fine if I have the backstyle set to opaque, everything works as expected. However, if I have it set at transparent, it only works on the first click, at which point it turns transparent. After that I can't click on anything anymore.

Any ideas? Here's the code to mess with:
Code:
Option Explicit

Dim lngDownX As Long
Dim lngDownY As Long

Private Sub UserControl_Click()
    Call Load(arrCircle(arrCircle.Count))
    arrCircle(arrCircle.Count - 1).Left = lngDownX - (arrCircle(arrCircle.Count - 1).Width / 2)
    arrCircle(arrCircle.Count - 1).Top = lngDownY - (arrCircle(arrCircle.Count - 1).Height / 2)
    arrCircle(arrCircle.Count - 1).Visible = True
    Call arrCircle(arrCircle.Count - 1).ZOrder(0)
End Sub

Private Sub UserControl_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    lngDownX = X
    lngDownY = Y
End Sub

Thanks for any and all help :)

Take Care,
Mike
 

Since you are adding a control to where it is I bet your problem is with the ZOrder. Try bringing your control to the front as see if that works.

Good Luck


 
Try setting UserControl.Visible = False and see what happens.

The reason for that suggestion is because of the following from MSDN: Three graphical layers are associated with forms and containers. The back layer is the drawing space where the results of the graphics methods are displayed. Next is the middle layer where graphical objects and Label controls are displayed. The front layer is where all nongraphical controls like CommandButton, CheckBox, or ListBox are displayed. Anything contained in a layer closer to the front covers anything contained in the layer(s) behind it. ZOrder arranges objects only within the layer where the object is displayed.

So I wonder which layers the two controls are being drawn in. Maybe arrCircle is in the middle layer and UserControl is in the front layer.

Cheers.

"Life is full of learning, and then there is wisdom"
 
Thanks for the feedback, guys. However:

I have am bringing the shape object to the front using the zOrder call at the end of UserControl_Click().

When I UserControl.Visible to false, nothing gets drawn.

From my observations, its not that the UserControl is drawn in front of the shape object, rather that when the UserControl is transparent, it won't register any clicks on it. I tested this using a MsgBox(); when I set UserControl.BackStyle=Opaque the MsgBox always pops up, when I set the backstyle to transparent, it doesn't.

Take Care,
Mike
 
By the way the X & Y in the MouseDown event are relative to the control, whereas the .Left and .Top properties are relative to the form as are the parameters for the Move method.

Also, try Me.Refresh after you set the Zorder.

What happens?

Greg.

"Life is full of learning, and then there is wisdom"
 
The .left and .top are the respective coordinates of the shape object array element. What I'm doing there is positioning the shape so that it is centered under the mouse.

The Me.Refresh didn't help, unfortunately.

I'm thinking I'll have to write a few public functions in the usercontrol, then get the click event and coordinates from the underlying object, and update the control via the public functions.

Take Care,
Mike
 
Mike,

Re: X and Y, if the mouse is positioned at the top left hand corner of the UserControl then both X and Y will equal zero.

I think the code should be
Code:
arrCircle(arrCircle.Count - 1).Left = UserControl.Left + lngDownX - (arrCircle(arrCircle.Count - 1).Width / 2)

arrCircle(arrCircle.Count - 1).Top = UserControl.Top + lngDownY - (arrCircle(arrCircle.Count - 1).Height / 2)

BTW: Does the UserControl have any constituent controls?

Also, if arrCircle is a constituent control then ignore my code above.

If UserControl does have constituent control(s) then the UserControl will only receive the click event when the mouse is click over a part of the control not covered by the constituent control.

Is this helping or am I off track?

Cheers ... Greg.

"Life is full of learning, and then there is wisdom"
 
Thanks for the effort, Greg. However, all this code is code within the usercontrol, and the .left/.top works as intended. the arrCircle control is contained within the UserControl. Sorry if I wasn't clear on that.

Basically you should be able to create a new UserControl, then copy/paste my code above into it, and run it.

Take Care,
Mike
 
Mike,

I understand.

In your first post you wrote: However, if I have it set at transparent, it only works on the first click, at which point it turns transparent. I am afraid I do not understand.

Can you please re-post. Thanks, Greg.

"Life is full of learning, and then there is wisdom"
 
Mike,

One other thought, what happens when you list all the constituent control names - do you get the "Loaded" arrCircle.

Like this:
Code:
dim x as Object
For Each x In UserControl.ParentControls
        debug.print x.Name
Next

Cheers, Greg.

"Life is full of learning, and then there is wisdom"
 
Greg, thanks for your follow-ups. :)

it seems that when I test the control in internet explorer, it doesn't initialize to transparent. But once I click on it (maybe it has to have focus?) it turns transparent.

No, it doesn't even create the loaded arrCircle, since it doesn't register the click event, i.e. UserControl_Click() never gets executed. That's what makes me think that setting it to transparent actualy causes the mouse events to "pass through" it onto the underlying object.

Take Care,
Mike
 
Mike,

Have a look at this MSDN article, it talks about capturing mouse events in a transparent User Control.

Is it a help?

Greg.


HOWTO: Use the HitTest Event and HitBehavior Property
ID: Q185882



--------------------------------------------------------------------------------
The information in this article applies to:

Microsoft Visual Basic Learning, Professional, and Enterprise Editions for Windows, version 6.0

--------------------------------------------------------------------------------


SUMMARY
This article discusses a new Event-Property pair available for UserControls created using Visual Basic 6.0. The general purpose of the HitTest Event, and the HitBehavior Property is to give greater flexibility in responding to UserControl events. Specifically, this article demonstrates how to build a transparent UserControl that responds to mouse events. This was not possible in previous versions of Visual Basic.



MORE INFORMATION
Using HitTest is relatively straightforward. "HitResult" is a value that is passed into the HitTest event by the system. By examining the value of HitResult, you can determine on which area of the control the mouse event occurred. Based on that information, you can reset the value of HitResult to have the control respond in the desired manner. You can instruct the control to process the mouse event, or you can instruct the control to pass the event on to the container. The default settings for the HitBehavior Property do not need to be changed for these examples.

For the examples used here, there are two different scenarios depending on whether or not the UserControl has been masked using MaskPicture and MaskColor. If your UserControl does not have a masked area please see the section entitled "Capturing Mouse Events on a Transparent UserControl." If your UserControl has a masked area, please see the section entitled "Capturing Mouse Events on a Masked Usercontrol."

It is important to note that the HitTest event occurs only on a Windowless UserControl with the BackStyle property set to Transparent. Windowless UserControls are also new to Visual Basic 6.0.


Capturing Mouse Events on a Transparent UserControl
Create a New Standard EXE project.


Add a UserControl to the project. (You may receive a warning that the UserControl can not be Public in this type of project. Choose OK in response to this message.)


Set the BackStyle property of the UserControl to Transparent.


Set the Windowless property of the UserControl to True.


Add the following code to the UserControl's module:

Private Sub UserControl_Click()
Debug.Print "Usercontrol Click"
End Sub

Private Sub UserControl_DblClick()
Debug.Print "Usercontrol Doubleclick"
End Sub

Private Sub UserControl_HitTest(X As Single, Y As Single, _
HitResult As Integer)

'Instruct the UserControl to behave as if the click occurred on a
' painted region of the control.
If HitResult = vbHitResultOutside Then
HitResult = vbHitResultHit
End If

End Sub




Place the UserControl on Form1. You may wish to draw a rectangle or other shape around the control since the control will not be visible.


Run the project.


Clicking or double-clicking the UserControl should result in the display of the message boxes.


Capturing Mouse Events on a Masked UserControl
This example requires a UserControl set up to use the MaskPicture and MaskColor Properties.

For more information on using the MaskPicture and MaskColor properties, please see the article listed in the REFERENCES section.

Create a bitmap with a white background that contains a filled red circle.


Perform steps 1-4 from the previous section.


Set the following properties for the UserControl:

BackStyle: 0 - Transparent
MaskColor: &H00FFFFFF& 'White
MaskPicture: The bitmap created in Step 1.
BackColor: &H000000FF& 'Red




Add the following code to the UserControl:

Private Sub UserControl_Click()
Debug.Print "Usercontrol Click"
End Sub




Add the following code to Form1:

Private Sub Form_Click()
Debug.Print "Form Click"
End Sub




Run the project. Click the masked (or visible) portion of the UserControl. You should see the "UserControl Click" message box. Clicking the transparent area of the control should cause the "Form Click" message box to display. This is the default behavior of a masked control - events on the painted area will be processed by the control and events on the transparent area will be forwarded to the container.


The event process behavior can be modified at this point to create separate responses based on which area of the UserControl received the Mouse event.


Add the following code to the General Section of the UserControl's module:

Private HitTestFlag As Integer

Private Sub UserControl_HitTest(X As Single, Y As Single, _
HitResult As Integer)
HitTestFlag = HitResult
'Set the UserControl to respond to the event.
HitResult = vbHitResultHit
End Sub




Replace the UserControl_Click event created in step 2 with the following:

Private Sub UserControl_Click()
If HitTestFlag = vbHitResultOutside Then
Debug.Print "usercontrol transparent area click"
ElseIf HitTestFlag = vbHitResultHit Then
Debug.Print "usercontrol painted area click"
End If
End Sub




Run the project. Clicking the Masked area of the control should display the "painted area click" message. Clicking the transparent area of the control should display the "transparent area click" message.


Using X and Y Coordinates with HitTest
Along with the HitResult argument, the X and Y coordinates of the mouse event are also passed into the HitText Event. The ability to determine whether the event occurred on a transparent area of the control or a masked area of the control can be sufficient in many cases. However, it may be necessary to determine if the event occurred on a specific area on the control. The X and Y coordinates can be used to accomplish this. The following example demonstrates a simple scenario.

For the example, we will determine over which quadrant of a UserControl the mouse pointer is currently positioned.

Start a new Standard EXE project in Visual Basic 6.0.


Add a Usercontrol to the project.


Set the Windowless property of the UserControl to True.


Set the BackStyle property of the UserControl to Transparent.


Add the following code to the UserControl module:

Private Sub UserControl_HitTest(X As Single, Y As Single, _
HitResult As Integer)

Dim txtDisplay As String
With UserControl
If Y < .Height / 2 Then
txtDisplay = "Upper "
Else
txtDisplay = "Lower "
End If
If X < .Width / 2 Then
txtDisplay = txtDisplay & "Left"
Else
txtDisplay = txtDisplay & "Right"
End If
End With

Parent.Label1.Caption = txtDisplay

End Sub




Add a Label to the Form.


Add the UserControl to Form1. You may wish to draw a square or rectangle around the control since it will not be visible. You may also want to display a picture on the form using the form's Picture property.


Set the BackStyle of the Label to Transparent.


Run the Project. As you move the mouse over the UserControl, the text in the Label control changes as you move from one quadrant to another.


The HitBehavior Property
The HitBehavior is settable at design time or run-time, and controls how HitTest works. There are three options, which are explained in Online Help. Since HitBehavior has the potential to effect logical evaluations in your code, it is important to understand the differences and determine which HitBehavior is desirable before you write the code.

Summary
HitTest and HitBehavior are new features in Visual Basic 6.0. These features allow event handling on transparent UserControls that was not possible in previous versions. There are many possible combinations when using HitTest, HitBehavior, and XY coordinates. They could be used to create any number of behaviors, ToolTips or HotSpots for example. Keep in mind that these properties and events are available for Windowless, Transparent UserControls only.



REFERENCES
For additional information on using the MaskPicture and MaskColor properties, please see the following article(s) in the Microsoft Knowledge Base:


Q174216 : TransparentPaint Backstyle Option Unavailable

Additional query words: kbDSupport kbDSD kbCtrlCreate kbVBp600 kbVBp

Keywords : kbGrpVB
Version :
Platform : WINDOWS
Issue type : kbhowto



Last Reviewed: January 5, 2000



&quot;Life is full of learning, and then there is wisdom&quot;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top