Passing the value from curElement to another private sub - vb.net

Hi I have a For Each inside a Private sub and I want to pass the value of the cuElement to another Private sub.
Dim theAnchorsCollection As HtmlElementCollection = Nothing
theAnchorsCollection = WebBrowser1.Document.GetElementsByTagName("a")
For Each curElement As HtmlElement In theAnchorsCollection
curElement.Style = "style code here"
AddHandler curElement.Click, AddressOf OnaClick
Next
And I want to pass the value to this other sub:
Private Sub OnaClick(sender As Object, e As HtmlElementEventArgs)
Dim endereco As String
endereco = curElement.GetAttribute("href").ToString()
'Do other things
End Sub
I want to know if in this sub I can use something to get the value of the other's curElement.

Never mind, I found the answer it was (sender) the variable that I wanted.
As I found in the MSDN Forums
As you use Addhandler to subscribe for a given event, you pass required arguments of event to the procedure with AddressOf that delegates , whose argument signature "must" be same as event's.
A demo:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AddHandler Button1.MouseDown, AddressOf btn_MouseDown
End Sub
Sub btn_MouseDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs)
MsgBox(e.Button.ToString)
End Sub
End Class
Using Addhandler, we're subscribing MouseDown event of button, and specifiying the procedure which gonna be called on the follow. The passed arguments are object(sender) and MouseEventArgs (e), and you can use this in your event sub like above. (eg: To get mousebutton that was down.)

Related

Working sample of Control.VisibleChanged Event in vb.net

I'm struggling to make the MSDN code sample for the Control.VisibleChanged event work: I don't see the MsgBox.
Private Sub Button_HideLabel(ByVal sender As Object, ByVal e As EventArgs)
myLabel.Visible = False
End Sub 'Button_HideLabel
Private Sub AddVisibleChangedEventHandler()
AddHandler myLabel.VisibleChanged, AddressOf Label_VisibleChanged
End Sub 'AddVisibleChangedEventHandler
Private Sub Label_VisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("Visible change event raised!!!")
End Sub 'Label_VisibleChanged
You need to "wire up" the events to the event handlers.
To start with, to get the code in HideLabel_Click to be called you need it to respond to a click on the button named "HideLabel".
There are two ways to do that: you can use AddHandler or the Handles clause.
To demonstrate the latter:
Option Strict On
Public Class Form1
Private Sub HideLabel_Click(sender As Object, e As EventArgs) Handles HideLabel.Click
myLabel.Visible = False
End Sub
Private Sub myLabel_VisibleChanged(sender As Object, e As EventArgs) Handles myLabel.VisibleChanged
MessageBox.Show("Visible change event raised!!!")
End Sub
End Class
However, you will notice that the message is shown even before the form appears. That is because of what goes on behind the scenes to create the form.
To avoid that happening, you can add the handler after the form has been shown:
Option Strict On
Public Class Form1
Private Sub HideLabel_Click(sender As Object, e As EventArgs) Handles HideLabel.Click
myLabel.Visible = False
End Sub
Private Sub myLabel_VisibleChanged(sender As Object, e As EventArgs)
MessageBox.Show("Visible change event raised!!!")
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
AddHandler myLabel.VisibleChanged, AddressOf myLabel_VisibleChanged
End Sub
End Class
Another way, in VB2015 and later, is to use a "lambda expression" instead of a separate method, although then you cannot disassociate the handler from the event with RemoveHandler:
Option Strict On
Public Class Form1
Private Sub HideLabel_Click(sender As Object, e As EventArgs) Handles HideLabel.Click
myLabel.Visible = False
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
AddHandler myLabel.VisibleChanged, Sub() MessageBox.Show("Visible change event raised!!!")
End Sub
End Class
Craig was kind enough to [and I quote verbatim] call attention to the importance of Option Strict when you add handlers manually using AddHandler. Without it, the "relaxed delegate convention" may allow adding handlers which don't exactly match the event signature that you won't be able to remove later.
Having said that, Option Strict On isn't a complete safeguard: notice how my last example compiles and works even with the wrong method signature for the handler.
[I suspect that the MSDN code sample was first created in C# as part of a larger example, so some parts have been lost in the translation and excerption.]
I get this is old but came across this post when looking for more information on VisibleChanged and couldn't help but notice that the accept answer may be misleading. If you are using a designer to create your Form and place objects on it, then the accepted answer will be fine. In fact you can get rid of the addHandler because the designer handles that for you. All you would need to do is use a handles clause with your label.
Private Sub Button_HideLabel(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
myLabel.Visible = False
End Sub 'Button_HideLabel
Private Sub Label_VisibleChanged(ByVal sender As Object, ByVal e As EventArgs) Handles myLabel.VisibleChanged
MessageBox.Show("Visible change event raised!!!")
End Sub 'Label_VisibleChanged
Where the issue lies with the accepted answer is if you arn't using a designer. Adding handle clauses to "wire up" simply won't work (we can make it work and if anyone is interested in that I'll be happy to post a code snippet of that, but it's not how the accepted answer lays it out). In your case all you need to do is call AddVisibleChangedEventHandler() to set up the handler. that's it. you could have done this by calling it in MyBase.Load
Private Sub Load_Form(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
AddVisibleChangedEventHandler()
End Sub
Private Sub Button_HideLabel(ByVal sender As Object, ByVal e As EventArgs)
myLabel.Visible = False
End Sub 'Button_HideLabel
Private Sub Label_VisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("Visible change event raised!!!")
End Sub 'Label_VisibleChanged
Private Sub AddVisibleChangedEventHandler()
AddHandler myLabel.VisibleChanged, AddressOf Label_VisibleChanged
End Sub
Once again I know this is dated but couldn't help but notice that (more or less assuming) that you are trying to get a msgBox to appear when you click a label. That is you click a label and then toggled the visibility of another label. The other label is the one where the event handler is on for visibility change. So that inevitably gets called when clicking the original label. IF you only want this msgBox to appear when clicking that label and not when the form loads as well, you should change the addHandler statement so that you are adding a handler on the click event.
Private Sub Load_Form(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
AddVisibleChangedEventHandler()
End Sub
Private Sub Label_VisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("Visible change event raised!!!")
End Sub 'Label_VisibleChanged
Private Sub AddVisibleChangedEventHandler()
AddHandler otherLabel.Click, AddressOf Label_VisibleChanged
End Sub 'AddVisibleChangedEventHandler
Also Option Strict On has nothing to do with addhandler (From my understanding, could be wrong. please enlighten me if that is the case). Option Strict On is only checking to see that you arn't implicitly typecasting. So for example:
Dim a As Double
Dim b As Integer
a = 10
b = a
results in an error when Option Strict is On but is totally legal if it is off. So in the case of you leaving off the handles clause, you'll never be implicitly typecasting and therefore is not needed.
Hope this helps anyone who sees this question

Why isn't my thread doing anything?

I have the following code in a form called Fetch.vb:
Imports System.ComponentModel ' might not be needed?
Imports System.Threading
Public Class Fetch
Public Sub New()
InitializeComponent()
backgroundWorker1.WorkerReportsProgress = True
backgroundWorker1.WorkerSupportsCancellation = True
End Sub
Private Sub btnFetch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFetch.Click
Dim ctrl As Control
For Each ctrl In Me.Controls
If TypeName(ctrl) = "TextBox" Then
If ctrl.Text.Length = (Not 0) Then
tbList.Add(ctrl.Text)
MsgBox(tbList.Item(0).ToString)
Exit For
End If
End If
Next
' ProcessLinks()
btnFetch.Enabled = False
BackgroundWorker1.RunWorkerAsync()
End Sub
Public Sub backgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
AddHandler BackgroundWorker1.DoWork, AddressOf backgroundWorker1_DoWork
ProcessLinks()
End Sub
End Class
Now process links is a module with a public sub in with the code I am trying to run, I don't need any arguments passed to it, and it doesn't do anything that (I think) could affect this, I think I'm just doing the threading code wrong. I have backgroundworker1 in my fetch.vb form, and when I click btn Fetch, the program does nothing.
Any help and guidance or reading material would be greatly appreciated.
EDIT Here is my LinkProcess module.
Public Module LinkProcess
Private Sub backgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles Fetch.BackgroundWorker1.DoWork
ProcessLinks()
End Sub
Public Sub ProcessLinks()
Dim tbContent As String
For Each tbContent In Fetch.tbList
Process.Start(tbContent)
Next
End Sub
End Module
What does your ProcessLinks() method do? Is it accessing any UI elements - like setting some text in label, or adding text a TextBox, etc.? If that is the case, then that won't work. You should not access the UI elements from inside your BackgroundWorker DoWork.
Here is a small post I wrote about how to use the BackgroundWorker correctly. This might help you.
http://www.vbforums.com/showthread.php?680130-Correct-way-to-use-the-BackgroundWorker

Me.FormClosing works on some forms but not others

I wish in my code to handle the case when the red X at the upper right of the form is clicked. To this end I consulted this and created an event handler thus:-
Private Sub DoFoo (sender As System.Object, e As System.EventArgs) _
Handles Me.FormClosing
' Do things
End Sub
but I have found (from setting breakpoints) that on certain forms this event handler is not invoked when the red X is clicked, whereas on others it is. The forms are all of type System.Windows.Forms.Form but naturally are different in most respects. Does anyone know what might be causing this and what to do about it?
Edit
In answer to Vitor's question, the form that isn't working is created thus:-
If my_form Is Nothing Then
my_form = New MyForm(parameters)
my_form.Title = "Contour Plot Options"
Else
my_form.BringToFront
End If
my_form.Show
Those that are behaving as expected are created like this:-
If my_working_form Is Nothing Then
my_working_form = New MyWorkingForm
End If
my_working_form.Show
I can't see any Visible property to set or clear anywhere.
Your parameters aren't quite right. A FormClosing event has a FormClosingEventArgs argument:
Private Sub DoFoo(ByVal sender As Object, ByVal e As FormClosingEventArgs) _
Handles Me.FormClosing
    If (e.CloseReason = CloseReason.UserClosing) Then
    End If
End Sub
You can inspect the e variable for the property `CloseReason', which would include a UserClosing enum, which means the user closed the form.
Each form should handle its own FormClosing event. Instead of subscribing to the event, I find it better to just override it like this:
Protected Overrides Sub OnFormClosing(ByVal e As FormClosingEventArgs)
If (e.CloseReason = CloseReason.UserClosing) Then
End If
MyBase.OnFormClosing(e)
End Sub
If you are instantiating your form you need to remember to AddHandler for the event you want to subscribe to.
my_form = New MyForm(parameters)
my_form.Title = "Contour Plot Options"
AddHandler my_form.Closing, AddressOf MyForm_Closing
'...
Sub MyForm_Closing(s As Object, ByVal e As FormClosingEventArgs)
'...
End Sub
Of course, to avoid memory leaks you should do it like this:
'global code
Private myFormClosingEventHandler As FormClosedEventHandler = Nothing
'...
Private Sub CreateForm
my_form = New MyForm(parameters)
my_form.Title = "Contour Plot Options"
myFormClosingEvent = New FormClosedEventHandler(AddressOf MyForm_Closing)
AddHandler my_form.Closing, myFormClosingEventHandler
'...
End Sub
Sub MyForm_Closing(s As Object, ByVal e As FormClosingEventArgs)
RemoveHandler my_form.Closing, myFormClosingEventHandler
'...
End Sub
Alternatively you can have it all pre-initalized for you by doing this in your class instead:
Private WithEvents my_form1 As Form = New Form()
Private WithEvents my_form2 As Form = New Form()
'... etc.
Now you can add in your code handlers using the Handle keyword as usual without using the AddHandler and RemoveHandler.
Protected Sub my_form1_Closing(s as object, e as FormClosingEventArgs) _
Handles my_form1.Closing
'...
End Sub

Second form not showing value stored in first form when called

Hey all i am trying to figure out why my 2nd form is not displaying the value i recived in my first form.
The code for the first form is:
Private Sub scannerOnCom_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
responceBack = scannerOnCom.ReadLine
Call frm1110.clickButton(responceBack)
End Sub
The second form code is this:
Public Sub clickButton(ByRef theResponse As String)
txtNumber.Text = theResponse
'Call cmdNextFinish_Click(Nothing, Nothing)
End Sub
However, when i debug it to make sure there is something stored for theResponse, there is but for some reason it does not put it into the textbox. It's blank.
Any help would be great!
David
UPDATE
Ok so Form1:
Dim tmpForm3020 As New frm3020
Private Sub cmd3020_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd3020.Click
tmpForm3020.Show()
Me.WindowState = FormWindowState.Minimized
End Sub
Private Sub scannerOnCom_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
responceBack = scannerOnCom.ReadLine
tmpForm3020.txtNumber.Text = responceBack
End Sub
If thats correct then i get an error on line:
xForm.txtNumber.Text = responceBack
Saying:
Cross-thread operation not valid: Control 'txtNumber' accessed from a thread other than the thread it was created on.
Are you explicitly creating an instance of your second form, or relying on the default instance? I.e. is "frm1110" the second form's class name, or an instance that you have new'd up? Make sure in either case that it is the same instance that is actually being displayed.
Dim tmpForm3020 As New frm3020
Private Sub cmd3020_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd3020.Click
tmpForm3020.Show()
Me.WindowState = FormWindowState.Minimized
End Sub
Private Sub scannerOnCom_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
responceBack = scannerOnCom.ReadLine
TestData(responceBack)
End Sub
Private Sub TestData(ByVal xVal As String)
If InvokeRequired Then
Me.Invoke(New MethodInvoker(AddressOf TestData))
' change Me to tmpForm3020 (if it does not work)
' tmpForm3020.Invoke(New MethodInvoker(AddressOf TestData))
Else
tmpForm3020.txtNumber.Text = xVal
End If
End Sub

Is it possible to detect a Form mouseclick from a User Control

I have created a User Control and would like to be able to detect when the user clicks on the Form.
I have seen this question which is related but the suggestion to use the the Leave event doesn't always do what I want because the focus doesn't necessarily change when the user clicks the Form (my control could be the only control on the Form in which case focus stays with my control).
Any ideas?
I want to be able to do something like this from within the User Control:
Private Sub ParentForm_Click(sender As Object, e As System.EventArgs) _
Handles Me.Parent.Click
End Sub
I would do it slightly differently:
Private _form As Control
Private Sub UserControl_ParentChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.ParentChanged
If _form IsNot Nothing Then
RemoveHandler _form.Click, AddressOf ParentOnClick
End If
_form = Me.FindForm()
If _form IsNot Nothing Then
AddHandler _form.Click, AddressOf ParentOnClick
End If
End Sub
Private Sub ParentOnClick(ByVal sender As Object, ByVal e As EventArgs)
'...
End Sub
This gives it a little more resillience - if it is not a direct child of a Form, if its parent changes etc.
I figured out how to do this myself - for anyone interested I am doing the following:
Private _parentForm As Form
Private Sub UserControl_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
_parentForm = CType(Parent, Form)
AddHandler _parentForm.Click, AddressOf ParentForm_Click
End Sub
Private Sub ParentForm_Click(sender As Object, e As System.EventArgs)
debug.writeline("Parent form clicked")
End Sub