Switch focus to a vb.net application on key press - vb.net

I have a vb.net application which will be minimized to task bar or notification area. Is there any way for me to maximize/focus on that application when user presses a key (even if the user is using any other application).
Tried windows hot key but doesn't focus the app when it is already open.Please help

You require global hotkeys. First, add these functions to your application.
Private Declare Function GetKeyPress Lib "user32" Alias "GetAsyncKeyState" (ByVal key As Integer) As Integer
<DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True)> _
Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll")> _
Private Shared Function ShowWindow(hWnd As IntPtr, nCmdShow As Integer) As Boolean
End Function
<DllImport("user32.dll")> _
Private Shared Function SetForegroundWindow(hWnd As IntPtr) As Integer
End Function
Next, add a Timer and in its Timer.Tick Event, use this function like this:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If GetKeyPress(Keys.LControlKey) And GetKeyPress(Keys.A) Then
Dim Handle As IntPtr = Process.GetProcessById(2916).MainWindowHandle
ShowWindow(Handle, 9)
SetForegroundWindow(Handle)
End If
End Sub
Set the Timer Interval to 150 to avoid repeated keypresses and make sure to enable the timer in the Form Load event.

Related

IsIconic() behavior varies depending on the environment

I'd like to use IsIconic function to check whether the specified window is minimized (iconic).
IsIconic function
https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms633527(v=vs.85).aspx
My code works properly in certain environments, but it does not work in other environments.
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function IsIconic(ByVal hWnd As IntPtr) As Long
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim hWnd As IntPtr = FindWindow(Nothing, "Google - Google Chrome")
If CBool(IsIconic(hWnd)) Then
Debug.WriteLine("Chrome is iconic.")
Else
Debug.WriteLine("Chrome is not iconic.")
End If
End Sub
End Class
When I run it with 64 bit Windows 7 OS, I can determine correctly whether Chrome is iconified.
However, when running on 32 bit Windows 7 OS, "Chrome is iconic." is always displayed in the immediate window regardless of whether or not Chrome is actually iconified.
Could you tell me why this difference occurs?
Is this phenomenon caused by the difference in OS bit number? Or something else?
Your return type of the IsIconic() function is wrong.
This:
Public Shared Function IsIconic(ByVal hWnd As IntPtr) As Long
...should be this:
Public Shared Function IsIconic(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
This also means that you can (and should) change:
If CBool(IsIconic(hWnd)) Then
Debug.WriteLine("Chrome is iconic.")
Else
...
to:
If IsIconic(hWnd) Then
Debug.WriteLine("Chrome is iconic.")
Else
...

Visual Studio Console-Like Blinking Cursor?

Is there any way to make a cursor look something like the blinking, square cursor used in console applications, say, inside of a text box instead of the regular vertical line? Example:
https://gyazo.com/db9f5661d493c32e48434eed2fa45252
You can control the caret (cursor) using the Win API Caret Functions.
A simple custom WinForm TextBox can be given a blinking caret like this:
Public Class MyTB : Inherits TextBox
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function CreateCaret(ByVal hWnd As IntPtr, ByVal hBitmap As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As Boolean
End Function
<DllImport("user32.dll")>
Private Shared Function DestroyCaret() As Boolean
End Function
<DllImport("user32.dll")>
Private Shared Function SetCaretBlinkTime(ByVal uMSeconds As UInt32) As Boolean
End Function
<DllImport("user32.dll")> _
Private Shared Function ShowCaret(ByVal hWnd As IntPtr) As Boolean
End Function
Protected Overrides Sub OnGotFocus(e As EventArgs)
MyBase.OnGotFocus(e)
MyTB.CreateCaret(Me.Handle, Nothing, 5, Me.Font.Height)
MyTB.SetCaretBlinkTime(500UI)
MyTB.ShowCaret(Me.Handle)
End Sub
Protected Overrides Sub OnLostFocus(e As EventArgs)
MyBase.OnLostFocus(e)
MyTB.DestroyCaret()
End Sub
End Class

VB: ShowWindow focus issue

I'm attempting to send automated keystrokes to an application that does not support copy+paste via a small VB form. The form loads data from a text file and uses SendKeys to fire it over once I click a button.
Everything appears to work except for the ShowWindow portion. I'm currently testing using Notepad and, with one exception, I can't seem to get ShowWindow to kick focus to Notepad. Obviously I'm worried it will do the same to the application I'll eventually be running this against (I don't currently have access to it). The only ShowWindow parameter that makes Notepad active is SW_SHOWMAXIMIZED. SW_SHOW and SW_SHOWNORMAL don't appear to do anything while SW_RESTORE will restore Notepad if minimized but my VB form remains the active window.
I'm not a programmer but I had made the mistake of telling my boss I dabbled in Pascal Turbo in high school (over a decade ago) so I'm the one stuck with trying to make this work. My current code cobbled together from S.O. and other sources:
(I'm running Windows 7 and using MVSE2013)
Imports System.Runtime.InteropServices
Public Class Form1
Private Declare Function FindWindow _
Lib "user32" _
Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As ShowWindowCommands) As Boolean
End Function
Enum ShowWindowCommands As Integer
SW_SHOWNORMAL = 1
SW_SHOWMAXIMIZED = 3
SW_RESTORE = 9
End Enum
Private Sub Form1_Load
[form]
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim lHwnd As IntPtr = FindWindow("Notepad", vbNullString)
If lHwnd <> IntPtr.Zero Then
ShowWindow(lHwnd, ShowWindowCommands.SW_SHOWNORMAL)
SendKeys.Send(TextBox1.Text)
Else
[blah blah error handling]
End If
End Sub
I'd try another technique like SetForegroundWindow but I read it doesn't play nice with Windows 7.
Found what I hope will be a passable workaround from PInvoke. I ended up swapping this block:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow _
As ShowWindowCommands) As Boolean
End Function
For this:
Public Declare Function BringWindowToTop Lib "user32" (ByVal hwnd As IntPtr) As Boolean
And then this line:
ShowWindow(lHwnd, ShowWindowCommands.SW_SHOWNORMAL)
For this:
BringWindowToTop(lHwnd)
I realize there are functional differences between the two but the change works in my specific instance so I'm happy.

Need help getting child windows

I am working in vb with visual studio 2010.
The app AnyOrder is no longer supported and I am trying to make an app where our users can type in info and then have the info populate into AnyOrder (and also other sites - they have to populate a lot of redundant info) but I am having no luck at all getting the child windows of any order to populate once the data is in the VB window app.
I can get the parent window handle just fine but can't seem to get a child window handle to save my life. I can't even get the first level down and the blanks that I will need to populate are great grand-children of the parent window.
It won't let me post a screencap of the spy++ since I just signed up and don't have the 10 rep but here is a link to the capture.
Thank you in advance for any assistance that you can provide.
Figured out the answer somehow.
#Region "functions"
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Int32
Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function EnumChildWindows(ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, ByVal lParam As IntPtr) As Boolean
End Function
Private Shared Function EnumWindow(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
Dim ChildrenList As List(Of IntPtr) = CType(GCHandle.FromIntPtr(Parameter).Target, Global.System.Collections.Generic.List(Of Global.System.IntPtr))
ChildrenList = CType(GCHandle.FromIntPtr(Parameter).Target, Global.System.Collections.Generic.List(Of Global.System.IntPtr))
If ChildrenList Is Nothing Then Throw New Exception("GCHandle Target could not be cast as List(Of IntPtr)")
ChildrenList.Add(Handle)
Return True
End Function
Private Shared Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
Try
EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
Finally
If ListHandle.IsAllocated Then ListHandle.Free()
End Try
Return ChildrenList.ToArray
End Function
#End Region
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
iParentHandle = FindWindow(vbNullString, AOParentName)
GetChildWindows(FindWindow(vbNullString, AOParentName))
Dim Childlist As String = String.Join(". ", ChildrenList)
MsgBox("list of child windows: " & Childlist)
End Sub

Reading keydown regardless of active application in vb.net

I asked a question earlier about keyhooks in vb.net.
My current issue is such:
I have created a program which should perform a certain action whenever a certain group of keys is pressed at the same time. The program must be able to run in the background, or in the system tray or something. Essentially, this should work like the KeyDown event on a form, except the form in this case is everything.
I'm not certain if there is a way to do this directly from within the .net API, but if there is I certainly have not found it.
That doesn't require a keyboard hook, you'll want to register a hot key. Much easier to implement and much less demanding of system resources. Here's an example, it restores the form to the foreground if it was minimized. Note that you can register more than one key:
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Public Class Form1
Private Const cHotKeyId As Integer = 0
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
'--- Register Ctrl + Shift + U as a hot key
If Not RegisterHotKey(Me.Handle, cHotKeyId, MOD_CONTROL + MOD_SHIFT, Keys.U) Then
Throw New Win32Exception()
End If
MyBase.OnLoad(e)
End Sub
Protected Overrides Sub OnFormClosing(ByVal e As System.Windows.Forms.FormClosingEventArgs)
UnregisterHotKey(Me.Handle, cHotKeyId)
MyBase.OnFormClosing(e)
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
Console.WriteLine(m.ToString())
If (m.Msg = WM_HOTKEY AndAlso m.WParam = CType(cHotKeyId, IntPtr)) Then
Me.Visible = True
If Me.WindowState = FormWindowState.Minimized Then Me.WindowState = FormWindowState.Normal
SetForegroundWindow(Me.Handle)
End If
MyBase.WndProc(m)
End Sub
'--- P/Invoke declarations
Private Const WM_HOTKEY As Integer = &H312
Private Const MOD_ALT As Integer = &H1
Private Const MOD_CONTROL As Integer = &H2
Private Const MOD_SHIFT As Integer = &H4
Private Declare Function RegisterHotKey Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifier As Integer, ByVal vk As Integer) As Boolean
Private Declare Function UnregisterHotKey Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal id As Integer) As Boolean
Private Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hWnd As IntPtr) As Boolean
End Class