Solved

User Control issue

Posted on 2012-03-14
13
194 Views
Last Modified: 2012-03-15
I’m fairly certain that this is NOT what the person who told me to use a UserControl for this had in mind, but I couldn’t figure out how to reference other controls on the main form from the user control.
 
SOOO
In my windows forms project, I have a frmMain.  
On that I have placed a user control that consists of 12 buttons. It’s a number pad.  0 – 9, a decimal point and a clear button.
The code below all works fine…. With one exception.
I cannot figure out how to “Hide” the user Control again.  At least not consistently.

I have the pnlData_Click function below, and set that to fire when the background panel on the main form is clicked, but that is not always done because there are multiple other controls on the main form that can be clicked instead.  I have also tried to add an event for when the usercontrol loses focus also... its not working.

Any ideas?


In the frmMain I have the following code.
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        AddHandler UcNumPad1.btn0.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn1.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn2.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn3.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn4.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn5.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn6.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn7.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn8.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btn9.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btnClear.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.btnDec.Click, AddressOf UcNumPad1_Click
        AddHandler UcNumPad1.VisibleChanged, AddressOf UcNumPad1_VisibleChanged
        AddHandler UcNumPad1.Leave, AddressOf UcNumPad1_VisibleChanged
    End Sub

    Private Sub txtItemQty_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Try
            Dim temTextBox As New TextBox
            temTextBox = sender
            _CurrentTextBox = sender.Name
            pnlData.Controls.Add(UcNumPad1)
            UcNumPad1.Location = New System.Drawing.Point(280, temTextBox.Location.Y + 20)
            UcNumPad1.BringToFront()
            UcNumPad1.Visible = True
            UcNumPad1.Focus()

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub
    Private Sub UcNumPad1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim txtTextBox() As Control = pnlData.Controls.Find(_CurrentTextBox, True)
        Select Case sender.name
            Case "btnClear"
                txtTextBox(0).Text = ""
            Case "btn1"
                txtTextBox(0).Text = txtTextBox(0).Text & "1"
            Case "btn2"
                txtTextBox(0).Text = txtTextBox(0).Text & "2"
            Case "btn3"
                txtTextBox(0).Text = txtTextBox(0).Text & "3"
            Case "btn4"
                txtTextBox(0).Text = txtTextBox(0).Text & "4"
            Case "btn5"
                txtTextBox(0).Text = txtTextBox(0).Text & "5"
            Case "btn6"
                txtTextBox(0).Text = txtTextBox(0).Text & "6"
            Case "btn7"
                txtTextBox(0).Text = txtTextBox(0).Text & "7"
            Case "btn8"
                txtTextBox(0).Text = txtTextBox(0).Text & "8"
            Case "btn9"
                txtTextBox(0).Text = txtTextBox(0).Text & "9"
            Case "btn0"
                txtTextBox(0).Text = txtTextBox(0).Text & "0"
            Case "btnDec"
                txtTextBox(0).Text = txtTextBox(0).Text & "."
        End Select
    End Sub

    Private Sub UcNumPad1_VisibleChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
        If Visible = True Then
            Dim txtTextBox() As Control = pnlData.Controls.Find(_CurrentTextBox, True)
            txtTextBox(0).BackColor = Color.Plum
        Else
            Dim txtTextBox() As Control = pnlData.Controls.Find(_CurrentTextBox, True)
            txtTextBox(0).BackColor = Color.White
        End If
    End Sub

    Private Sub pnlData_Click(sender As System.Object, e As System.EventArgs) Handles pnlData.Click, Panel1.Click
        UcNumPad1.Visible = False
    End Sub

Open in new window

0
Comment
Question by:ScottParker
  • 5
  • 4
  • 3
  • +1
13 Comments
 
LVL 8

Expert Comment

by:Crashman
ID: 37721698
you can try use the lost focus event
0
 
LVL 3

Author Comment

by:ScottParker
ID: 37722012
I already tried to add an event for when the usercontrol loses focus.  No luck.
I think its because the buttons on the user control itself is what has focus.
0
 
LVL 8

Expert Comment

by:Crashman
ID: 37722226
Could you post a example, to work with it
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 37722239
Here is more what I meant:
Public Class Form1

    Private _CurrentTextBox As TextBox = Nothing

    Private Sub TB_GotFocus(sender As Object, e As System.EventArgs) Handles TextBox1.GotFocus, TextBox2.GotFocus, TextBox3.GotFocus
        _CurrentTextBox = sender
    End Sub

    Private Sub UcNumPad1_Clear() Handles UcNumPad1.Clear
        If Not IsNothing(_CurrentTextBox) Then
            _CurrentTextBox.Clear()
        End If
    End Sub

    Private Sub UcNumPad1_Character(value As String) Handles UcNumPad1.Character
        If Not IsNothing(_CurrentTextBox) Then
            _CurrentTextBox.SelectedText = value
        End If
    End Sub

End Class

Open in new window


Public Class UcNumPad

    Public Event Clear()
    Public Event Character(ByVal value As String)

    Private Sub btn_Click(sender As Object, e As System.EventArgs) Handles _
        btn0.Click, btn1.Click, btn2.Click, btn3.Click, btn4.Click, btn5.Click, _
        btn6.Click, btn7.Click, btn8.Click, btn9.Click, btnDec.Click, btnClear.Click

        If sender Is btnClear Then
            RaiseEvent Clear()
        Else
            RaiseEvent Character(DirectCast(sender, Button).Text)
        End If
    End Sub

End Class

Open in new window

0
 
LVL 38

Expert Comment

by:PaulHews
ID: 37722258
If you have a look at MSDN LostFocus documentation you will see that Microsoft recommends using Enter and Leave events rather than GotFocus and LostFocus.
0
 
LVL 8

Expert Comment

by:Crashman
ID: 37722264
the event is fired when you click another part of the form or not?
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 500 total points
ID: 37722330
Here's one way to make the NumPad disappear when you click outside of it:
Public Class UcNumPad

    Public Event Clear()
    Public Event Character(ByVal value As String)

    Private WithEvents _MyFilter As MyFilter

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        _MyFilter = New MyFilter
        Application.AddMessageFilter(_MyFilter)
    End Sub

    Private Sub btn_Click(sender As Object, e As System.EventArgs) Handles _
        btn0.Click, btn1.Click, btn2.Click, btn3.Click, btn4.Click, btn5.Click, _
        btn6.Click, btn7.Click, btn8.Click, btn9.Click, btnDec.Click, btnClear.Click

        If sender Is btnClear Then
            RaiseEvent Clear()
        Else
            RaiseEvent Character(DirectCast(sender, Button).Text)
        End If
    End Sub

    Private Sub _MyFilter_MouseDown() Handles _MyFilter.MouseDown
        If Me.Visible Then
            Dim RC As Rectangle = Me.RectangleToScreen(Me.ClientRectangle)
            If Not RC.Contains(Cursor.Position) Then
                Me.Visible = False
            End If
        End If
    End Sub

    Private Class MyFilter
        Implements IMessageFilter

        Public Event MouseDown()

        Private Const WM_LBUTTONDOWN As Integer = &H201

        Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
            Select Case m.Msg
                Case WM_LBUTTONDOWN
                    RaiseEvent MouseDown()

            End Select
            Return False
        End Function

    End Class

End Class

Open in new window

0
 
LVL 3

Author Comment

by:ScottParker
ID: 37722351
Idle_Mind

Ok, that code does make more sense now.
The only thing I think its missing is how to "Show" and "Hide" the user control.

I assume to show it, I would just add the visible = true command to the TB_GotFocus function you mentioned.   I can also put the location code there.. i.e. where on the screen I want the user control to show up.

But when the user is done, and touches (touch screen monitor) another part of the screen how do I make the user control "Hide" again.

edit( you posted while I was typing this)

Crashman,
yes the event is fired when another part of the form is clicked.. UNLESS the point of the click hapens to be on top of another control that is on the form.  That is what makes this so ugly.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 37722627
Exactly...just set the Visible() property to True and make its Location() property what you want.

The second post I made makes the NumPad automatically hide itself when the user clicks (or touches) somewhere outside the control.  This magic is accomplished using IMessageFilter to trap the WM_LBUTTONDOWN message and then compare the current screen coords to that of the UserControl.
0
 
LVL 3

Author Closing Comment

by:ScottParker
ID: 37724531
Thank you once again.  Your code worked perfectly.  I even kind of understand it now.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 37724542
"I even kind of understand it now."

That's the best part.  =)

Do you still have any questions about the code that I can answer?
0
 
LVL 3

Author Comment

by:ScottParker
ID: 37724630
No, I think I got the idea now...

I added
AddHandler UcNumPad1.VisibleChanged, AddressOf UcNumPad1_VisibleChanged

to the main form so that way I could change the background color of the _CurrentTextBox.

I also looked at the _MyFilter_MouseDown() and noticed how you picked a rectangle that is where the user control is, and if the mouse is outside of that rectangle, then turn the visible to false.  

I don't pretend to understand exactly how the MyFilter class works, but it does so for now I am happy.

All in all in the last 2 days I learned a lot about User Controls and have decided to now add another one to this project to handle a different issue.

Thanks again
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 37724671
IMessageFilter allows your application to trap and filter windows messages before they get dispatched to the current form/control.  It's a low level technique that doesn't need to be used very often, as a solution can usually be derived by overriding WndProc() for a specific form/control.  In this case, though, we needed to know when the mouse was clicked anywhere on the form so I needed a common area outside any specific form/control; IMessageFilter fits the bill perfectly for this situation.
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

1.0 - Introduction Converting Visual Basic 6.0 (VB6) to Visual Basic 2008+ (VB.NET). If ever there was a subject full of murkiness and bad decisions, it is this one!   The first problem seems to be that people considering this task of converting…
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now