CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7

Thread: Switching Focus

  1. #1
    Join Date
    Mar 2000
    Location
    Arizona, USA
    Posts
    493

    Switching Focus

    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
    Kris
    Software Engineer
    Phoenix, AZ USA

  2. #2
    Join Date
    Jan 2001
    Posts
    165

    Re: Switching Focus

    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 )

    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


  3. #3
    Join Date
    Jan 2001
    Posts
    165

    Re: Switching Focus

    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


  4. #4
    Join Date
    Sep 2000
    Location
    London England
    Posts
    144

    Re: Switching Focus

    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.







  5. #5
    Join Date
    Mar 2000
    Location
    Arizona, USA
    Posts
    493

    Re: Switching Focus

    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
    Kris
    Software Engineer
    Phoenix, AZ USA

  6. #6
    Join Date
    Jan 2001
    Posts
    165

    Re: Switching Focus

    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



  7. #7
    Join Date
    Mar 2000
    Location
    Arizona, USA
    Posts
    493

    Re: Switching Focus

    Your Code Worked Great. Thanks A Lot!!!

    Kris
    Software Engineer
    Phoenix,AZ
    Kris
    Software Engineer
    Phoenix, AZ USA

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured