Search code examples
javajava.util.scannerjna

JNA user32.ShowWindow with java.util.Scanner doesnt work


Hello~ im using JNA and i want to make another program appear on the screen with focus but it doesnt work.

So here is my code.

import java.util.Scanner;

import com.sun.jna.platform.win32.User32;

import com.sun.jna.platform.win32.WinDef; public class Main {

public static void main(String args[]) {

    System.out.println("test");
    Scanner sc = new Scanner(System.in);
    int number = sc.nextInt();
    sc.close();
    System.out.println(number);

    setFocusToWindowsApp("점포관리", number);

    System.exit(0);
}

public static void setFocusToWindowsApp(String applicationTitle, int windowState) {
    //int state = User32.SW_SHOWNORMAL; // default window state (Normal)
    int state = windowState;
        switch (state) {
        default:
        case 0:
            state = User32.SW_SHOWNORMAL;
            break;
        case 1:
            state = User32.SW_SHOWMAXIMIZED;
            break;
        case 2:
            state = User32.SW_SHOWMINIMIZED;
            break;
    }

    User32 user32 = User32.INSTANCE;
    WinDef.HWND hWnd = user32.FindWindow(null, applicationTitle);
    if (user32.IsWindowVisible(hWnd)) {
        user32.ShowWindow(hWnd, state); // .SW_SHOW);
        user32.SetForegroundWindow(hWnd);
        user32.SetFocus(hWnd);
    }
}

}

this code is just for test... without Scanner, it works just fine. but With scanner, only SW_SHOWMAXIMIZED works. Otherwise, the program just doesnt appear on the screen. it just blinks on the icon bar. i think Scanner is related to System call or whatever so it's messing with user32. i think. ive tried every flag on the doc.(SW_SHOWNORMAL,SW_SHOWMAXIMIZED etc...) but only SW_SHOWMAXIMIZED works.. i dont want the window to be maximized.

any help would be appreciated.. Thanks!!


Solution

  • As you correctly assumed, the cause of your problem is with the Scanner.
    But the problem is not with the showWindow() function, but rather with the SetForegroundWindow() function.

    The documentation states the following:

    An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user.

    source: Microsoft doc

    So you cannot bring this screen to the foreground from your application if you require input.

    The solution is a bit of a hack, but by simply causing the screen to be first Minimized and then restored to it's Normal view you can force it to the foreground.

    The modified method would look like this

    public static void setFocusToWindowsApp(String applicationTitle, int windowState) {
        int state = windowState;
            switch (state) {
            default:
            case 0:
                state = User32.SW_SHOWNORMAL;
                break;
            case 1:
                state = User32.SW_SHOWMAXIMIZED;
                break;
            case 2:
                state = User32.SW_SHOWMINIMIZED;
                break;
        }
    
        User32 user32 = User32.instance;
        HWND hWnd = user32.FindWindowA(null, applicationTitle);
        if (user32.IsWindowVisible(hWnd)) {
            if (state != User32.SW_SHOWMINIMIZED) {
                user32.ShowWindow(hWnd, User32.SW_SHOWMINIMIZED);
            }
            user32.ShowWindow(hWnd, state);
            user32.SetFocus(hWnd);
        }
    }