IsIconic() behavior varies depending on the environment - vb.net

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
...

Related

FindWindowEx in VB.NET

I have a query, how can I kill a process with just the class name using FindWindowEx
If you have been able to reliably get a window handle back from calling FindWindowEx you can then use GetWindowThreadProcessId to find the ID of the process from the window handle.
Once you have the process ID you can find the Process by that ID and call Kill() on it. For example:
Imports System.Runtime.InteropServices
Imports System.Diagnostics
Module Module1
<DllImport("user32.dll", SetLastError:=True)>
Private Function GetWindowThreadProcessId(ByVal hwnd As IntPtr,
ByRef lpdwProcessId As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Function FindWindowEx(ByVal parentHandle As IntPtr,
ByVal childAfter As IntPtr,
ByVal lclassName As String,
ByVal windowTitle As String) As IntPtr
End Function
Sub Main()
Dim hWnd As IntPtr = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Chrome_WidgetWin_0", "Spotify Premium")
Dim ProcessId As Integer
GetWindowThreadProcessId(hWnd, ProcessId)
If ProcessId <> 0 Then
Dim Process As Process = Process.GetProcessById(ProcessId)
Process.Kill()
End If
End Sub
End Module
The tricky part will be making sure that you can always get a window handle. Think about cases when there are multiple instances of the handle. You mention class name but it will likely also be necessary to supply the window title to FindWindowEx.
You may also need to consider what happens if calling Process.Kill() should throw an exception, for example, if the user that your program is running under doesn't have the rights to kill that particular process.

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

Switch focus to a vb.net application on key press

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.

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