Create New Project.
On top left of the form add a button -> change text to: Capture coordinates
Resize button to make it a bit bigger.
On the right of this button add another button -> change text to: Cancel, change visible to: False
On the right of the "cancel" button add a label
Below the first button add a checkbox -> change text to: Whole Screen
Below this button (middle left of the form) add a small textbox -> Mulitline: yes, size around: 140, 90
Below the textbox add a button -> text: Clear
On the right of the first textbox add two more with the same properties, so that the middle of the field form has three small textboxes. Below each one there should be one "Clear" button.
On top of the second textbox add another checkbox -> text: Form + Borders
On top of the third textbox add a checkbox -> text: Form - No Borders
Go to toolbox -> All Windows Forms -> Double click a Timer to add to the program.
The program will be able to follow three types of mouse coordinates: the whole screen of your computer, the main form of the program including borders (like the blue header) and the coordinates of the space inside the borders of the program.
We will display the coordinates inside the textboxes. The capturing of coordinates will be done with the keyboard "Space" key (any pressed key really). This allows us to get mouse coordinates outside the main program form and over various objects inside the form, which would be hard to achieve with a mouse click.
First we will focus on making one textbox operational and then, at the end, we will easily add the code for the other two.
Double click on the "Capture coordinates" button and add this inside:
-> if any of the checkboxes is checked (checked is true), then a person can start the operations form the "capture" button - otherwise this is not possible.
Button2, in this case, is the "cancel" button on the right of the "capture" button.
We will use the timer to calculate the coordinates in every moment. When the program is started, the timer is turned off. We have to turn it on right after turning a checkbox on. First we will only do checkbox1.
Double click Checkbox1 on the design page. Add this inside:
If Checkbox1.checked Then
Timer1.Enabled = True
Else
Timer1.Enabled = False
End If
When we turn on the timer it should start sending in data to our textbox1 every 100 miliseconds (which is the default interval). We will always write this data in the last used line of the textbox and save captured coordinates in previous text lines. For doing this we will need two variables.
Right after "Public Class Form1" declare this:
Double click on Timer1 on the design page. Inside the sub add this:
-> only if checkbox1 is checked, re-dimension "gg". The string array variable "gg" didn't have a size defined before this point. That's why we couldn't write at a specific positions into it, like: gg(12) = "hello"
The "Preserve" modifier keeps all the content inside the array's positions. So, if we create gg(0 To 2), then write words inside gg(0), gg(1) and gg(2) - we can use preserve this words in a later re-dimensioning and give the same array a new size like gg(0 To 20).
Cursor.Position.ToString - takes the current x and y positions of the cursor on the whole screen (0,0 should be at the most top-left corner of your computer screen).
We have to be using the "gg" variable to store values inside the textbox. This is required since we can't write directly in a specific line of the textbox, for example:
TextBox1.Lines(x1) = Cursor.Position.ToString - doesn't work. We can't choose a specific textbox line.
That's why we store all the content from the "gg" inside the textbox all the time and only change "gg".
You can check the operation of timer so far by checking the checkbox1 on.
Code:
Private x1 As Integer
Private gg As String()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If CheckBox1.Checked Or CheckBox2.Checked Or CheckBox3.Checked Then
Label1.Text = "! Scroll with your mouse and then press Space !"
Button2.Visible = True
End If
End Sub
Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.Checked Then
Timer1.Enabled = True
Else
Timer1.Enabled = False
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If CheckBox1.Checked Then
ReDim Preserve gg(0 To x1)
gg(x1) = Cursor.Position.ToString
TextBox1.Lines = gg
End If
End Sub
End Class
The first click on the "capture" button will start the process of waiting for a keyboard keypress. We will end this process by pressing the "space" button while the object selected inside the program is our "capture" button. First click starts the process, second one ends it.
At the beginning of our button1 we will add the operation for the second (awaited) press of the button. Add:
End If
-> first button1 press makes button2 visible, therefore, this option becomes available for the second press.
x1 = x1+1 - this line is the main reason why we get a capture. Right after this line happens, the timer will write it's last cursor data in the old gg(x1) and directly start writing the new data inside the next "gg" line from now on.
After we make a capture, the label is emptied, the "cancel" button is made invisible.
At this point, we should have found a good location for our label on the form. If that's the case go to the design page, click on the label -> go to properties -> leave the "text" property empty.
Label1.Focus() - removing the focus from the "capture" is done only for esthetical reasons. Not important.
Let's add an operation to the "cancel" button. Go to the design page and double click on button2. Add:
-> pressing the "cancel" button makes it invisible and reset's it's text. This will also disable the process of capturing the cursor coordinates, since the second button press on the "capture" button is expecting a visible "cancel" button.
Currently we have a problem that must solve: after a person clicks on the "capture" button, the same button awaits for a keypress BUT the user doesn't have to do that, he can click with the left mouse button on some other object on the form (i.e. inside a textbox) and lose the focus from the "capture" button. After the focus was lost, pressing the "space" button won't press the button1 anymore. This will leave the waiting for "space" process hanging until the mouse is used on either button1 or button2.
We'll have to keep the focus on the "capture" button after it was pressed.
At the bottom of the Timer1 sub, below the "End If" line, add this:
-> this will keep the focus on the "capture" button every 100 miliseconds. The problem of this is that this will ALSO keep the focus away from the "cancel" button (unless we click really fast). This is inconvenient. We have to be able to retain the focus on the "cancel" button when we want to click on it.
We'll add the code to fix this in the following post.
What happens when we uncheck checkbox1? Inside the checkbox1 sub , below "End If", insert:
-> this will empty the last line of the textbox - the 'active coordinates' line. If you removed: gg(x1) = "" , and then checked / unchecked the checkbox, you would get like a capture inside of it you didn't want.
Private x1 As Integer
Private gg As String()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If Button2.Visible = True Then
x1 = x1 + 1
Label1.Text = ""
Button2.Visible = False
Label1.Focus()
Exit Sub
End If
If CheckBox1.Checked Or CheckBox2.Checked Or CheckBox3.Checked Then
Label1.Text = "! Scroll with your mouse and then press Space !"
Button2.Visible = True
End If
End Sub
Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.Checked Then
Timer1.Enabled = True
Else
Timer1.Enabled = False
End If
If CheckBox1.Checked = False Then
gg(x1) = ""
TextBox1.Lines = gg
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If CheckBox1.Checked Then
ReDim Preserve gg(0 To x1)
gg(x1) = Cursor.Position.ToString
TextBox1.Lines = gg
End If
If Button2.Visible = True Then
Button1.Focus()
End If
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Button2.Visible = False
Label1.Text = ""
End Sub
End Class
Continuing in the next post.
Go to next post.