B4J Question Is there an event that triggers when a B4J [UI] application loses focus?

m4.s

Member
Licensed User
Longtime User
Or at least when the B4J application's z-order is no longer the highest (in Windows and macOS)?

Note: I don't want to set my application to be 'always on top'.
 

amykonio

Active Member
Licensed User
Longtime User
Hi.
I guess you can check this using EventName_FocusChanged.
B4X:
Private Sub MainForm_FocusChanged (HasFocus As Boolean)
    TextAreaLog.Text = TextAreaLog.Text & HasFocus & CRLF 'This is a TextArea on the MainForm...
End Sub
Of course this event should be implemented in any form you want to handle when it gets or loose focus.
Andreas.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
Or at least when the B4J application's z-order is no longer the highest (in Windows and macOS)?

Note: I don't want to set my application to be 'always on top'.

Hi there... a different look... for what you want... may be more difficult... but you can have on mind...

I don't know for macos - may be this i am using not work... but for windows i am sure...

This in reality will give you info what Window is in Front (any window not only yours app) - so with this i think you can check with and "If" or "select" ---> having in title something you trust...

You can do more things...

B4X:
'need a special library... the jna... easy to get it from the internet !!!
    #AdditionalJar: jna-5.2.0
    #AdditionalJar: jna-platform-5.2.0


Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Private Button1 As B4XView
'you will need the timer:
    Private tm As Timer
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
   
'you can have this in b4xpages to check every 0.5 sec:
    tm.Initialize("Timer1",500)
    tm.Enabled=True
   
End Sub

'and this sub to check what is in front:
Sub Timer1_tick
tm.Enabled=False
    Dim user32 As JavaObject
    user32 = user32.InitializeStatic("com.sun.jna.platform.win32.User32").GetField("INSTANCE")
   
    Dim hwnd1 As JavaObject = user32.RunMethod("GetForegroundWindow",Null)

    Dim Rect As JavaObject
    Rect.InitializeNewInstance("com.sun.jna.platform.win32.WinDef.RECT",Null)
    user32.runmethod("GetWindowRect",Array(hwnd1,Rect))
   
    Dim title(512) As Char
    user32.RunMethod("GetWindowText", Array(hwnd1,title,512))
    Dim native As JavaObject
    Dim activewindowtitle As String = native.InitializeStatic("com.sun.jna.Native").RunMethod("toString", Array(title))
    activewindowtitle = activewindowtitle.Trim
'check for it:
    Log(activewindowtitle)
'you can even get the height or width of form... or the position... you can play with magic..
    Log(Rect.GetField("left") & " " & (Rect.GetField("right")-Rect.GetField("left")))
tm.Enabled=True
End Sub
 
Upvote 0

m4.s

Member
Licensed User
Longtime User
Thank you @amykonio, as your recommended
B4X:
Sub MainForm_FocusChanged (HasFocus As Boolean)
solution works perfectly in/for my application!

@Magma - I really appreciate the time you took replying in such good detail. Your solution approach is more complex than is required, because in my case I only need the application focus (change) event to trigger from the main form (i.e. not when other/additional application forms are opened/closed); plus I don't need to know what any of the other running applications are. But your sample code may be of benefit to me in the future, or other developers here sooner.

Note to all: I've subsequently found these 2 related discussion threads which further educated and assisted me some as well:

https://www.b4x.com/android/forum/threads/b4j-form-related-subs.101724/#post-638720

https://www.b4x.com/android/forum/threads/all-windows-titles.98720/#content
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
Ofcourse solution of amykonio is "exactly" what you want... (no need to have complex subs)

but I ve mention this extra solution because you can use it for example at "main" code of your b4xpages.... and you can have only one "check"... also you can check for other apps also.. as you said you can have it in mind for future use...
 
Upvote 0
Top