Hotkeys in Visual Basic 2010: one works, one does not - vb.net

I'm creating an "autoclicker" for use in video games that left clicks my mouse repeatedly at the push of a button. I want to have hotkeys set up that work globally without the autoclicker window being in focus. For some reason, only the hotkey that is meant to stop the clicking is currently functioning (F2). The F1 key is supposed to start the clicking, but currently the only way to start it is by pressing the Start button on the form manually. The code seems to throw an error when attempting to be deployed to version 4.0 of the .NET framework, but setting it to 3.5 solves this issue. I've included my entire code below because I can't figure out why the F1 hotkey is not functioning despite the F2 hotkey working flawlessly. Thanks for your time. A good portion of this code I came up with by looking at examples of other peoples' work, and I only understand it to a certain extent. I hope my code is formatted correctly because I'm new to this site and I don't exactly understand how to paste it correctly. Thanks for your help in advance, I really appreciate it.
Public Class Form1
Private Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vkey As Long) As Integer
Private Declare Sub mouse_event Lib "user32.dll" (ByVal dwflags As Long, ByVal dx As Long, ByVal cbuttons As Long, ByVal dy As Long, ByVal dwExtraInfo As Long)
Dim hotkey1 As Boolean
Dim hotkey2 As Boolean
Private Const mouseclickup = 4
Private Const mouseclickdown = 2
Dim Test As Integer
Dim Interval As Integer
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
Click.Start()
End Sub
Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
Click.Stop()
End Sub
Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTest.Click
Test = Test + 1
Counter.Text = Test
End Sub
Private Sub Click_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Click.Tick
Interval = CInt(timeTextbox.Text)
Click.Interval = Interval
mouse_event(mouseclickdown, 0, 0, 0, 0)
mouse_event(mouseclickup, 0, 0, 0, 0)
hotkey1 = GetAsyncKeyState(Keys.F1)
If hotkey1 = True Then
btnStart.PerformClick()
End If
hotkey2 = GetAsyncKeyState(Keys.F2)
If hotkey2 = True Then
btnStop.PerformClick()
End If
End Sub
Private Sub timeTextbox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timeTextbox.TextChanged
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
KeyPreview = True
End Sub
End Class

Your declarations were for VB6. The data types need to be changed for VB.Net as shown below.
Also, you need two independent timers. One for detecting the keypress, which has to run at a high rate. And another for doing the actual clicking, whose rate is determined by your TextBox value.
Public Class Form1
Private Const MOUSEEVENTF_LEFTDOWN As Integer = &H2
Private Const MOUSEEVENTF_LEFTUP As Integer = &H4
Private Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As System.Windows.Forms.Keys) As Short
Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Integer, _
ByVal dx As Integer, ByVal dy As Integer, ByVal cButtons As Integer, _
ByVal dwExtraInfo As Integer)
Private WithEvents KeyTimer As New Timer
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
KeyTimer.Interval = 50
KeyTimer.Start()
Click.Enabled = False
End Sub
Private Sub KeyTimer_Tick(sender As Object, e As System.EventArgs) Handles KeyTimer.Tick
If IsKeyDown(Keys.F1) Then
Click.Start()
ElseIf IsKeyDown(Keys.F2) Then
Click.Stop()
End If
End Sub
Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTest.Click
Static Test As Integer
Test = Test + 1
Counter.Text = Test
End Sub
Private Sub timeTextbox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timeTextbox.TextChanged
Dim Interval As Integer
If Integer.TryParse(timeTextbox.Text, Interval) Then
Click.Interval = Interval
End If
End Sub
Private Sub Click_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Click.Tick
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
End Sub
Private Function IsKeyDown(ByVal key As System.Windows.Forms.Keys) As Boolean
Return ((GetAsyncKeyState(key) And &H8000) = &H8000)
End Function
End Class

Related

How to resize a parent form and panel to fit a child window

I use the code below to start a cmd.exe windows and move it into a panel after execution. At this moment, the child window is resized to fit into Panel1 on my Form1. I would like it to be the other way around: my Form1 (and thus Panel1) should resize to fit the size of the child window, so no matter what the size of the default cmd.exe window is on the local computer.
Does anybody know how I should do that?
Thanks for any help in advance!
Kind regards,
Eric
Imports System.Runtime.InteropServices
Public Class Form1
Private WithEvents Tmr As New Timer With {.Interval = 100}
Private Const HWND_BOTTOM As Integer = &H1
Private WithEvents proc As New Process
<DllImport("user32.dll", EntryPoint:="SetParent")>
Private Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="SetWindowPos")>
Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Text = "My title"
proc.EnableRaisingEvents = True
proc.StartInfo.FileName = "cmd"
proc.Start()
Tmr.Start()
End Sub
Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Tmr.Tick
If SetParent(proc.MainWindowHandle, Panel1.Handle) <> IntPtr.Zero Then
Tmr.Stop()
SetWindowPos(proc.MainWindowHandle, New IntPtr(HWND_BOTTOM), 0, 0, Panel1.ClientSize.Width, Panel1.ClientSize.Height, 0)
End If
End Sub
Private Sub Proc_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles proc.Exited
Invoke(Sub() Close())
End Sub
End Class
As suggested by #Jimi, I used DwmGetWindowAttribute to retrieve the size of the child, before moving it into the panel. Afterwards I use ShowWindow to maximize it, to get rid of the borders.
The changed code can be found in a different post of mine.

Hotkey doesn't work while interface is minimized

I created a simple auto clicker in visual basic using a timer and a couple of buttons.
I assigned keybinds to my start and stop buttons but they only work when the interface is open, and I want to use them while the program is minimized.
How might I go about doing that? Below is some of the more important code for context. If you need more information just let me know.
Declare Sub mouse_event Lib "user32.dll" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dx As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32, v As Integer)
Private Sub frmAutoClicker_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Z) Then
btnStart.PerformClick()
End If
End Sub
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
Timer1.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
mouse_event(&H2, 0, 0, 0, 1)
mouse_event(&H4, 0, 0, 0, 1)
End Sub
You could try SetWindowsHookEx from user32.dll, it'a an aggressive method... but it will work.. (search SetWindowsHookEx in this forum...)
Or you couldtry to add a message filter to the application:
Application.AddMessageFilter
You can use RegisterHotkey to implement VB.NET Detecting Keypress While Minimized.
It is the first step to know the Virtual-Key Codes.
In order to facilitate the test, I set the automatic click limit of Timer1_Tick, which is limited to 50 times.
Sample code:
Imports System.Runtime.InteropServices
Public Class frmAutoClicker
Public Const WM_HOTKEY As Integer = &H312
Public Const VK_1 As Integer = &H5A '0x5A Z key
Dim i As Integer = 0
<DllImport("User32.dll")>
Public Shared Function RegisterHotKey(ByVal hwnd As IntPtr,
ByVal id As Integer, ByVal fsModifiers As Integer,
ByVal vk As Integer) As Integer
End Function
<DllImport("User32.dll")>
Public Shared Function UnregisterHotKey(ByVal hwnd As IntPtr,
ByVal id As Integer) As Integer
End Function
Declare Sub mouse_event Lib "user32.dll" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dx As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32, v As Integer)
Private Sub frmAutoClicker_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim retVal1 As Boolean = RegisterHotKey(Me.Handle, 10, 0, VK_1)
If retVal1 = False Then
MsgBox("The hotkeys could not be registered!", MsgBoxStyle.Critical)
Application.Exit()
End If
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_HOTKEY Then
Dim id As IntPtr = m.WParam
Select Case (id.ToString)
Case "10"
btnStart.PerformClick()
End Select
End If
MyBase.WndProc(m)
End Sub
Private Sub frmAutoClicker_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
UnregisterHotKey(Me.Handle, 10)
End Sub
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
Timer1.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If i > 50 Then
Timer1.Stop()
i = 0
Else
mouse_event(&H2, 0, 0, 0, 1)
mouse_event(&H4, 0, 0, 0, 1)
End If
i = i + 1
End Sub
End Class
Result:

Disable/lock Keyboard Permanently

I new to vb.net. I try to create system to disable/lock keyboard.
And also i try many code from google but its all work only in that form. I want It disable/lock permanently.
Public Class Form1
Private Declare Function BlockInput Lib "user32" Alias "BlockInput" (ByVal fBlock As Integer) As Integer
Private Declare Function ShowCursor Lib "user32" (ByVal lShow As Long) As Long
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
BlockInput(1)
ShowCursor(0)
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
BlockInput(0)
ShowCursor(1)
End Sub
End Class
Thanks.
Try this but this will block the mouse and the keyboard so i would put an timer to re-enable it
Public Class Form1
Private Declare Function BlockInput Lib "user32" (ByVal fBlock As Long) As Long
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Timer1.Interval = 5000 '5 seconds
Timer1.Enabled = True
BlockInput(True)
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Timer1.Enabled = False
BlockInput(False)
MsgBox("You can now use your mouse and keyboard")
End Sub
End Class

record pressed keys and amount of time they were pressed vb.net

It's a bit tricky, but how do I record the amount of time a key was pressed? My objective is to record the keys I pressed and the amount of time I pressed those keys, then be able to programatically use that recording whenever I want.
Your question is not too specific and thus there are many alternatives fitting there. If what you want is a rough introduction to the way in which this problem should be addressed, here you have some help:
Public Class Form1
Dim allStartTimes(50) As Date
Dim allElapsedTimes(50) As TimeSpan
Dim allKeys(50) As Keys
Dim curIndex As Integer = 0
Dim totKeys As Integer = 50
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Dim count As Integer = 0
Do
count = count + 1
If (e.KeyCode = allKeys(count)) Then
If (curIndex <> count) Then
If (curIndex > 0) Then
allElapsedTimes(curIndex) = Now.Subtract(allStartTimes(curIndex))
End If
allStartTimes(count) = Now
curIndex = count
Exit Do
End If
End If
Loop While (count < totKeys)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
allKeys(1) = Windows.Forms.Keys.A
allKeys(2) = Windows.Forms.Keys.B
'.....
End Sub
End Class
This code shows the basic algorithm and one alternative to get the keys: KeyDown/KeyUp events for a given object (in this case it is the main form; bear in mind that only works when the main form is selected). I haven't included the KeyUp part because of requiring some work to synchronise both events and to get it working properly (what you should be doing). This code does not store the time when the given key stops being pressed, but when a different one is pressed.
One alternative to events are hooks. They work everywhere (don't need to select a specific object) but also have their drawbacks. Here you have a working code:
Public Class Form1
Private Const WM_HOTKEY As Integer = &H312
Private Declare Function RegisterHotKey Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifier As Integer, ByVal vk As Integer) As Integer
Private Declare Function UnregisterHotKey Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal id As Integer) As Boolean
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 0, Nothing, Keys.A)
RegisterHotKey(Me.Handle, 0, Nothing, Keys.B)
'.....
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If (m.Msg = WM_HOTKEY AndAlso m.WParam = CType(0, IntPtr)) Then
If (m.LParam = CType(4259840, IntPtr)) Then
'A
ElseIf (m.LParam = CType(4325376, IntPtr)) Then
'B
End If
'.....
End If
MyBase.WndProc(m)
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
UnregisterHotKey(Me.Handle, 0)
End Sub
End Class
List of parameters for all the keys to run the hook above. The shown A & B integer values represent just a quick solution for illustrative purposes.
Even there are further alternatives like relying on WPF: an example of a C# implementation.
These are the basic ideas. If you want a proper and reliable code you would have to do some research and testing to account for all the possible eventualities.

VB.NET | How to get Windows Form WorkingArea, not Desktop WorkingArea

I wanted an effect of fading a panel control and the controls / object inside it. I found some containers with opacity property it only changes the background color's opacity.
So I came up my own solution. I created another form containing the controls I need and I got what I want but I got some problems with positioning the new form created. I don't know how to get the working area of its parent form to set the initial position. What I mean for working area is that, it won't include the control box / title bar. Different OS has different title bar sizes (as far as I know) so I need to adjust it correctly
Form2, the one holding the Opaque Controls
Public Class Form2
Private Const dif As Integer = 23
Private Const GWL_EXSTYLE As Integer = (-20)
Private Const WS_EX_TRANSPARENT As Integer = &H20
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As IntPtr, ByVal nIndex As Integer) As Integer
Public Sub resizeFrom(ByVal parent As Form)
Me.Height = parent.Height - dif
Me.Width = parent.Width
Me.Top = (parent.Top + ((parent.Height - Me.Height) / 2) + (dif / 2))
Me.Left = parent.Left + ((parent.Width - Me.Width) / 2)
End Sub
Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.TopMost = True
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Me.BackColor = Color.Red
SetWindowLong(Me.Handle, GWL_EXSTYLE, GetWindowLong(Me.Handle, GWL_EXSTYLE) Or WS_EX_TRANSPARENT)
End Sub
End Class
The Parent/Main Form
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Show()
Form2.Show()
Form2.resizeFrom(Me)
End Sub
Private Sub Form1_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Move
Form2.resizeFrom(Me)
End Sub
Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
Form1_Move(Me, New EventArgs)
End Sub
Private Sub HScrollBar1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles HScrollBar1.Scroll
Form2.Opacity = HScrollBar1.Value / 100
Me.Text = "Opacity: " & HScrollBar1.Value & "%"
End Sub
End Class
It should look like this
http://i48.tinypic.com/25qubk0.jpg
Opaque Form is for display purposes, it was set to "Ghost Like Form" or "Click-through Form"
Is there any solution so I can get the proper WorkingArea of the Form?
Please help.
Thanks
What you need is the absolute location of the ClientRectangle. The Location of this is (0, 0) but you can magically convert it to screen values:
Form2.Location = PointToScreen(Me.ClientRectangle.Location)
Form2.Size = Me.ClientRectangle.Size