B4J Question How to request focus for a program that is running

tdocs2

Well-Known Member
Licensed User
Longtime User
Greetings.

Thank you in advance for replying to my question.

The code below (courtesy of Erel) checks if Notepad is running, and if is not running, it runs it via the shell command.

QUESTION

How do I give Notepad focus and "bring to front" if it is running?

Best regards.

Sandy

B4X:
Sub BShell_MouseClicked (EventData As MouseEvent)
  Dim shellexe As String
  shellexe="notepad.exe"
  Dim exerunning As Boolean =ProcessExists(shellexe)
  Log ("exerunning "&exerunning)
  If exerunning = False Then
      shell1.initialize("shell1","c:\Windows\System32\notepad.exe",list1)
      shell1.Run(-1)
  End If
End Sub

Sub ProcessExists(ExeName As String) As Boolean
  Dim Result As ShellSyncResult
  Dim Sh As Shell
  Sh.InitializeDoNotHandleQuotes("", "tasklist", Null)
  Result = Sh.RunSynchronous(5000)
     Return Result.StdOut.ToLowerCase.Contains(ExeName.ToLowerCase)
End Sub
 

jmon

Well-Known Member
Licensed User
Longtime User
It's quite easy to use:
B4X:
Dim AutoIt as jAutoItX
AutoIt.Initialize
If AutoIt.WinExists("Untitled - Notepad", "") then
    AutoIt.WinActivate("Untitled - Notepad", "")
End If

EDIT: Note that WinSetOnTop will set the "OnTop" attribute to the window, pushing it always in foreground of other windows. You should use winActivate.
 
Upvote 0

tdocs2

Well-Known Member
Licensed User
Longtime User
Thank you, jmon.

You are right winActivate would be the correct.

The issue is not the usage - it is the installation - I do not even know what JACOB is....

Sandy
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
You could use JNA - just need to copy 2 jars to extra libs folder (jna-4.2.1.jar & jna-platform-4.2.1.jar)
B4X:
....
    #AdditionalJar: jna-4.2.1
    #AdditionalJar: jna-platform-4.2.1
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim inline As JavaObject
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    inline = Me
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
    ' test if Notepad is running, if not attempt to start it using shell
    inline.RunMethod("isRunning",Array("Notepad"))
End Sub
Sub startProcess(name As String)
    Dim sh As Shell
    sh.Initialize("",name,Null)
    sh.Run(-1)
End Sub
#if java
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;

public static void isRunning(String progName) throws Exception {
    HWND hwnd = User32.INSTANCE.FindWindow(progName,null); // program name
    if (hwnd == null) {
        System.out.println(progName + " is not currently running. Will attempt to start it.");
        _startprocess(progName); // can use this shortcut to b4j sub as it's in same class
        }
    else
        {
        System.out.println(progName + " is currently running, giving it focus");
        User32.INSTANCE.ShowWindow(hwnd, 9 );        // SW_RESTORE
        User32.INSTANCE.SetForegroundWindow(hwnd);   // bring to front
        }
}
#end if
 
Upvote 0

jmon

Well-Known Member
Licensed User
Longtime User
You could use JNA
Awesome, thank you.

I do not even know what JACOB is
I will update the installation instruction in the autoit thread, I agree it's not very clear. The jacob-1.17-x86.dll is located in the jAutoitX_source.zip file attached, under the folder libs.
 
Last edited:
Upvote 0

tdocs2

Well-Known Member
Licensed User
Longtime User
@Daestrum
Indeed always thinking. Thank you.
Where do I download jna-4.2.1.jar & jna-platform-4.2.1.jar?

@jmon
Thank you, indeed.

Best regards to both.

Sandy
 
Last edited:
Upvote 0

jmon

Well-Known Member
Licensed User
Longtime User
Upvote 0

tdocs2

Well-Known Member
Licensed User
Longtime User
@Daestrum

I received an error in B4J V4 Compile... I also inserted code used.

upload_2015-12-25_20-49-3.png



B4X:
#Region  Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 400
   
    #AdditionalJar: jna-4.2.1
    #AdditionalJar: jna-platform-4.2.1

#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim inline As JavaObject
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    inline = Me
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
    ' test if Notepad is running, if not attempt to start it using shell
    inline.RunMethod("isRunning",Array("Notepad"))
End Sub
Sub startProcess(name As String)
    Dim sh As Shell
    sh.Initialize("",name,Null)
    sh.Run(-1)
End Sub
#if java
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;

public static void isRunning(String progName) throws Exception {
    HWND hwnd = User32.INSTANCE.FindWindow(progName,null); // program name
    if (hwnd == null) {
        System.out.println(progName + " is not currently running. Will attempt to start it.");
        _startprocess(progName); // can use this shortcut to b4j sub as it's in same class
        }
    else
        {
        System.out.println(progName + " is currently running, giving it focus");
        User32.INSTANCE.ShowWindow(hwnd, 9 );        // SW_RESTORE
        User32.INSTANCE.SetForegroundWindow(hwnd);   // bring to front
        }
}
#end if

Thank you.

Sandy
 
Upvote 0

rwblinn

Well-Known Member
Licensed User
Longtime User
Hi,

tested your code and receiving the same error when compiling in Release (obfuscated) Mode.
When compiling & running in Release Mode, then no error.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
You need to change the call from the inline java to a ba.raiseevent as the code names get mangled by the obsf.

You could just get the code to return true/false if app is running then call the shell to start it if not running.
B4X:
public static boolean isRunning(String progName) throws Exception {
HWND hwnd = User32.INSTANCE.FindWindow(progName,null); // program name
if (hwnd == null) {
    return false;
}
else
{
User32.INSTANCE.ShowWindow(hwnd, 9 ); // SW_RESTORE
User32.INSTANCE.SetForegroundWindow(hwnd); // bring to front
return true;
}
}
then use something like
B4X:
  if inline.runmethod("isRunning",array("notepad"))= false then startProcess("notepad")
 
Last edited:
Upvote 0

tdocs2

Well-Known Member
Licensed User
Longtime User
Licenses to JNA and JACOB.

For the benefit of others reading this thread:

The JNA is under this license:
This library is licensed under the LGPL, version 2.1 or later, and (from version 4.0 onward) the Apache Software License, version 2.0. Commercial license arrangements are negotiable.
http://www.apache.org/foundation/license-faq.html#WhatDoesItMEAN

The AutoIX has a lot of goodies based on JACOB. Great job by @jmon
JACOB is under this license:
GNU Library General Public License, version 2.0
http://www.gnu.org/licenses/old-licenses/lgpl-2.0.en.html
 
Upvote 0

jmon

Well-Known Member
Licensed User
Longtime User
I received an error in B4J V4 Compile
You need to change the call from the inline java
I read somewhere that if you put an Underscore in the sub name, it won't be obfuscated, so change the function name like this
B4X:
sub start_Process(Name as String)
    '....
end sub
 
Upvote 0

tdocs2

Well-Known Member
Licensed User
Longtime User
I read somewhere that if you put an Underscore in the sub name, it won't be obfuscated, so change the function name like this

That was true in B4A. And it probably works in B4J.

Thank you, jmon.

Your generosity as well as Daestrum's and Rob's is to be commended.
 
Upvote 0

tdocs2

Well-Known Member
Licensed User
Longtime User
I read somewhere that if you put an Underscore in the sub name, it won't be obfuscated, so change the function name like this

@jmon

It works. Very clever. Simplicity at its best.

B4X:
#Region  Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 400
  
    #AdditionalJar: jna-4.2.1
    #AdditionalJar: jna-platform-4.2.1

#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim inline As JavaObject
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    inline = Me
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
    ' test if Notepad is running, if not attempt to start it using shell
    inline.RunMethod("isRunning",Array("Notepad"))
End Sub
Sub start_Process(name As String)
    Dim sh As Shell
    sh.Initialize("",name,Null)
    sh.Run(-1)
End Sub
#if java
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;

public static void isRunning(String progName) throws Exception {
    HWND hwnd = User32.INSTANCE.FindWindow(progName,null); // program name
    if (hwnd == null) {
        System.out.println(progName + " is not currently running. Will attempt to start it.");
        _start_process(progName); // can use this shortcut to b4j sub as it's in same class
        }
    else
        {
        System.out.println(progName + " is currently running, giving it focus");
        User32.INSTANCE.ShowWindow(hwnd, 9 );        // SW_RESTORE
        User32.INSTANCE.SetForegroundWindow(hwnd);   // bring to front
        }
}
#end if
 
Upvote 0
Top