Click to See Complete Forum and Search --> : Switching Focus
softweng
June 18th, 2001, 10:33 AM
Does anyone know how to switch focus to a text box on another application with out using SendKeys?
The other app is outlook 2000. I need to switch focus to a certain text box on a form so my app
can fill it in. SendKeys doesn't work because the focus does not always start in the same place
when the form opens. I'm sure there are API's that can do this (I hope). If anyone can provide
any help it will be greatly appreciated.
Thanks!!!
Kris
Software Engineer
Phoenix,AZ
Kdev
June 18th, 2001, 11:41 AM
Quote from the MSDN:
By using the AttachThreadInput function, a thread can attach its input processing to another thread. This allows a thread to call SetFocus to set the keyboard focus to a window associated with another thread's message queue.
This is how it can be done:
private Declare Function SetFocus Lib "user32" _
(byval hwnd as Long) as Long
private Declare Function AttachThreadInput Lib "user32" _
(byval idAttach as Long, byval idAttachTo as Long, _
byval fAttach as Long) as Long
private Declare Function GetCurrentThreadId Lib "kernel32" () as Long
private Declare Function GetWindowThreadProcessId Lib "user32" _
(byval hwnd as Long, lpdwProcessId as Long) as Long
public Function SetFocusEx(lHwnd as Long) as Long
Dim rc as Long, idAttach as Long, idAttachTo as Long, fAttach as Boolean
idAttach = GetCurrentThreadId
idAttachTo = GetWindowThreadProcessId(lHwnd, vbNull)
fAttach = true
'I'm not sure of the implications of leaving this thread attached
'so you may want to detach it after setting the focus
rc = AttachThreadInput(idAttach, idAttachTo, fAttach)
rc = SetFocus(lHwnd)
SetFocusEx = rc
End Function
This is assuming that you know the handle to the text box you would like to set the focus to.
I'm not sure if there is a better way to find this out but I wrote a small program a while back to let me test window functions on any window on my system. This program uses createToolHelpSnapshot to enumerate all the windows on the system (using a tree view somewhat like spy++). Then I can check any window I want and perform various functions (minimize, maximize, kill process, hide, restore, SetFocus :p)
I used this program to find the textbox of say the To: field in Outlook 2000. However the only way I knew that it was the To: Field is that it showed up in the list directly under the To: Field label (since the label has text it is shown on my program otherwise you see just the class name).
I hope this helps.
-K
Kdev
June 18th, 2001, 11:47 AM
I did some testing and noticed that in the manner described in my previous post you cannot set the focus if the window is minimized. However, if you have the window in a normal or maximized state and then you Hide the window (api call can do this for you) you will be able to set the focus and it will change (though you won't see it unless you make the window visible again).
-K
Jason Bennison
June 18th, 2001, 11:47 AM
I have found the AppActivate Function works fine.
try this for calling the Windows Calculator from within a VB program.
Dim ReturnValue
DoEvents
ReturnValue = Shell("C:\WINDOWS\CALC.EXE", 1)
DoEvents
AppActivate ReturnValue, 0
DoEvents
Or if using Excel or Word, and your program generates documents or excel speadsheets to be used with their applications, Call the document itself once ur program has made it, and its associated app will start.
Dim ReturnValue
DoEvents
AppActivate "MyDoc.doc"
HTH Jas.
softweng
June 18th, 2001, 12:04 PM
Thanks, I will give it a shot. Any ideas on getting the Hwnd of the text box?
It is the "TO" field in the "New Meeting Request" form in OutLook 2000.
Kris
Software Engineer
Phoenix,AZ
Kdev
June 18th, 2001, 02:03 PM
This of course is the real problem here. Since Window Handles are assigned when they are created they can vary every time you create the window. I was manually finding mine but it does follow a pattern. That is, I am using GetDesktop followed by a recursive function to GetWindow to enumerate all the windows on the desktop. Here is my function to accomplish this:
private lWindows as Long
private sWinNames() as string
private lhWndWindows() as Long
private Function GetToHwnd() as Long
Dim sTitle as string
Dim lhWndDesktop as Long, i, rc
Dim lhWndTo as Long
me.MousePointer = vbHourglass
lhWndDesktop = GetDesktopWindow()
lWindows = -1
Call GetText(lhWndDesktop, sTitle)
'Load all window handles into array
'and put the Window Text or Class Name in
'another array
Call EnumerateChildren(lhWndDesktop)
for i = 0 to ubound(sWinNames)
if trim(sWinNames(i)) = "Untitled - Meeting" then 'This is the window text of a new Meeting Request in Outlook 2000
while trim(sWinNames(i)) <> "to" And i <= ubound(sWinNames)
i = i + 1
wend
if i <= ubound(sWinNames) then
i = i + 1
lhWndTo = lhWndWindows(i) 'This is the actual textbox handle
end if
end if
next i
GetToHwnd = lhWndTo
me.MousePointer = vbArrow
End Sub
private Sub EnumerateChildren(hWndParent as Long)
Dim hWndChild as Long, sTitle as string
Dim rc as Integer
'get the first child of hWndParent
hWndChild = GetWindow(hWndParent, GW_CHILD Or GW_HWNDFIRST)
Do While hWndChild <> 0
lWindows = lWindows + 1
ReDim Preserve lhWndWindows(lWindows)
ReDim Preserve sWinNames(lWindows)
lhWndWindows(lWindows) = hWndChild
Call GetText(hWndChild, sTitle)
sWinNames(lWindows) = sTitle
Call EnumerateChildren(hWndChild)
'move on to the next window
hWndChild = GetWindow(hWndChild, GW_HWNDNEXT)
Loop
End Sub
'get the caption of the window, if none exists get the class name instead
private Sub GetText(hwnd as Long, sText as string)
Const MAXCHARS = 21
Dim sName as string * MAXCHARS, rc
rc = GetWindowText(hwnd, sName, MAXCHARS)
If rc = 0 then
rc = GetClassName(hwnd, sName, MAXCHARS)
sText = "[" & Left(sName, InStr(sName, Chr(0)) - 1) & "]"
Exit Sub
End If
sText = Left(sName, InStr(sName, Chr(0)) - 1)
End Sub
This is a very crude method but it appears to work. Use at your own risk.
-K
softweng
June 26th, 2001, 11:07 AM
Your Code Worked Great. Thanks A Lot!!!
Kris
Software Engineer
Phoenix,AZ
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.