You are viewing limited content. For full access, please sign in.

Question

Question

CAT: Calling GetForegroundWindow() from a Separate Thread

SDK
asked on February 29, 2016

Hey guys! I have a (super specific) question about CAT's `ClientManager.GetForegroundWindow()` function, specifically about calling it on a separate thread than a program's UI thread.

In order to speed up my program's load time, I'd like to put very little initial processing in the `load` event. Instead, I'd like to just pass all initial processing (which should happen on load) to a background worker thread, as seen below:

Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

     BackgroundWorker1.RunWorkerAsync()

End Sub

However, what I'm finding is that I can't call `ClientManager.GetForegroundWindow()` from the separate thread. If I do, it seems to silently fail (no exceptions, just nothing happens). Other CAT calls work fine from the seperate thread.

Any ideas on how I can get the foreground window, from a separate thread? Thanks!

0 0

Replies

replied on February 29, 2016 Show version history

I don't see how calling GetForegroundWindow from a background thread would make any difference. Internally CAT calls the windows API function GetForegroundWindow() (from user32.dll) and compares that to all of the windows returned by ClientManager.GetAllClientWindows to find the top window. Try calling the windows API function yourself, does it return NULL?

0 0
replied on February 29, 2016 Show version history

Hey Robbie! I tried calling the Windows API function directly (from a separate thread) and it appears to work fine. I made a short video of what I'm seeing on my end: http://screencast.com/t/mYatLuVvs

Note that I misspoke earlier. As you can see in the video, when I call CAT from a separate thread, it does not silently fail, it does indeed throw an exception.

Also, in case its helpful, below is the code I'm using (this is the same code as appears in the video).

Imports System.ComponentModel
Imports Laserfiche.ClientAutomation
Imports Laserfiche.RepositoryAccess
Imports System.Threading
Imports System.Runtime.InteropServices

Public Class Form1

    Public Declare Function GetForegroundWindow Lib "user32" () As Long

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        BackgroundWorker1.RunWorkerAsync()

    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

        Using lfClient As New ClientManager()

            'Dim foregroundWindow As ClientWindow = lfClient.GetForegroundWindow
            'MsgBox(foregroundWindow.IsLoggedIn)

            MsgBox(GetForegroundWindow.ToString)

        End Using

    End Sub

End Class

Note: I assume that I am importing `user32.dll` correctly. Let me know if that's not the case.

0 0
replied on February 29, 2016

The windows API function is returning the handle for your application because that is the currently active window. If CAT's GetForegroundWindow returns null, try GetTopWindow to find the topmost window for a particular ClientInstance. Here is a post with more ideas for determining which window is at the "top".

0 0
replied on February 29, 2016

Ah OK. That makes sense.

It sounds like I need to leverage `GetTopWindow()` in order to determine the z-order of all open windows on the machine. Then, by iterating over all ClientInstance objects, and their ClientWindow objects, I can then compare hWnd values to see if I'm currently iterating over the top-most window for a particular ClientInstance. If so, then I act on that window.

This makes sense in theory, but I'm a bit confused as to what hWnd to pass to `GetTopWindow()`. Where do I get that value from? The only CAT object that returns a hWnd property is ClientWindow, but that doesn't sound like the correct hWnd for me to pass, correct? Am I thinking about this correctly?

0 0
replied on February 29, 2016

Yes, pass in the hwnd from one of the ClientWindow objects, I think you can pass any one and GetTopWindow will return the topmost.

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.