【问题标题】:Java JNA focus a specific WindowJava JNA 关注特定的窗口
【发布时间】:2016-05-25 10:38:36
【问题描述】:

我正在尝试让我的应用程序能够聚焦另一个窗口(在本例中为记事本)

我的班级是这样的

 public static class Win32WindowUtils {

  public interface User32 extends StdCallLibrary {
        User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
        HWND GetParent(HWND hWnd);
        HWND FindWindow(String lpClassName, String lpWindowName);
        HWND SetFocus(HWND hWnd);
        HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter, String lpszClass, String lpszWindow);
        int GetWindowText(HWND hWnd, char[] lpString, int nMaxCount);
    }

    private static final int WIN_TITLE_MAX_SIZE = 512;

    public static HWND GetWindowHandle(String strSearch, String strClass) {
        char[] lpString = new char[WIN_TITLE_MAX_SIZE];
        String strTitle;
        int iFind = -1;
        HWND hWnd = User32.INSTANCE.FindWindow(strClass, null);
        while(hWnd != null) {
            User32.INSTANCE.GetWindowText(hWnd, lpString, WIN_TITLE_MAX_SIZE);
            strTitle = new String(lpString);
            strTitle = strTitle.toUpperCase();
            iFind = strTitle.indexOf(strSearch);
            if(iFind != -1) {
                return hWnd;
            }
            hWnd = (User32.INSTANCE).FindWindowEx(null, hWnd, strClass, null);
        }
        return hWnd;
    }
}

我通过以下方式调用它:

User32.INSTANCE.SetFocus(Win32WindowUtils.GetWindowHandle(windowTitle, null));

注意:

public String windowTitle = "Unbennant - Editor";

遗憾的是什么都没发生,我不知道为什么

【问题讨论】:

  • 根据MSDN,“窗口必须附加到调用线程的消息队列”。该注释似乎暗示您不能通过 SetFocus() 函数强制关注不同的应用程序。
  • 您可能想改用BringWindowToTop()
  • 您要激活应用程序(将其放在前面)还是只是确保将键盘事件定向到所选窗口?

标签: java window focus jna


【解决方案1】:

下面的代码 sn-p 遍历机器中打开的所有窗口,当找到具有特定标题的 Notepad++ 窗口时停止,然后将其聚焦。在聚焦时按回车键三下。

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;
import com.sun.jna.win32.StdCallLibrary;

public class TryWithHWND {
public interface User32 extends StdCallLibrary {
    User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);

    boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc, Pointer arg);

    WinDef.HWND SetFocus(WinDef.HWND hWnd);

    int GetWindowTextA(HWND hWnd, byte[] lpString, int nMaxCount);

    boolean SetForegroundWindow(WinDef.HWND hWnd);
}

public static void main(String[] args) {
    final User32 user32 = User32.INSTANCE;
    user32.EnumWindows(new WNDENUMPROC() {
        int count = 0;

        public boolean callback(HWND hWnd, Pointer arg1) {
            byte[] windowText = new byte[512];
            user32.GetWindowTextA(hWnd, windowText, 512);
            String wText = Native.toString(windowText);

            // get rid of this if block if you want all windows regardless
            // of whether
            // or not they have text
            if (wText.isEmpty()) {
                return true;
            }

            System.out.println("Found window with text " + hWnd
                    + ", total " + ++count + " Text: " + wText);
            if (wText
                    .equals("C:\\Users\\Avi.J\\Desktop\\Datasource and Mq setup commands.txt - Notepad++")) {
                user32.SetForegroundWindow(hWnd);
                return false;
            }
            return true;
        }
    }, null);
    // user32.SetFocus(hWnd);
    try {
        Robot r = new Robot();
        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
    } catch (AWTException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

希望这有帮助,我相信发送击键的部分也可以由 User32 库完成。

【讨论】:

    【解决方案2】:

    我知道我迟到了 3 年,但是由于 Windows api 在尝试在与您不同来源的其他程序上进行修改时的限制,目前的答案至少不适用于 JNA。我做了几个小时的研究,尝试了很多不同的功能,但没有成功。最后,我找到了真正干净的方法。在这里使用 Avinash Jha 代码库是一种方法:

    public class JnaInstances {
    
        public interface User32 extends StdCallLibrary {
            User32 INSTANCE = Native.loadLibrary("user32", User32.class);
    
            boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc,
                                Pointer data);
    
            int GetWindowTextW(WinDef.HWND hWnd, char[] lpString, int nMaxCount);
    
            boolean ShowWindow(WinDef.HWND hWnd, int nCmdShow);
    
        }
    
    }
    
    public static void main(String[] args) {
        JnaInstances.User32 user32 = JnaInstances.User32.INSTANCE;
    
        user32.EnumWindows(new WinUser.WNDENUMPROC() {
    
            @Override
            public boolean callback(WinDef.HWND hwnd, Pointer pointer) {
                char[] windowText = new char[512];
                user32.GetWindowTextW(hwnd, windowText, 512);
    
                String windowName = Native.toString(windowText);
    
                System.out.println("The window is called: "+ windowName);
    
                if(windowName.contains("Window name")) { //Here you can use the .equals if you want more accurancy
    
                    user32.ShowWindow(hwnd, User32.SW_RESTORE);
                    return false;
                }
    
                return true;
            }
    
        }, null);
    }
    

    【讨论】:

    【解决方案3】:

    应该是这样的

    public String windowTitle = "Unbenannt - Editor";
    

    【讨论】:

    • 不,我不想让它阅读,public String windowTitle = "Unbenannt - Editor";为其指定要关注的窗口的名称,在这种情况下,在我的语言中是未命名的记事本
    • @durchstarter 看看你的问题:你在字符串windowTitle 中有错字:Unbennant 而不是 Unbenannt
    【解决方案4】:

    Avinash Jha 的回答很好。只需在 user32.SetForegroundWindow(hWnd); 后添加以下两行,您无需添加机器人按键 VK_ENTER 即可激活窗口,因为单击 Enter 会导致单击窗口的默认键(例如按钮 OK、Run)

    ...
    user32.SetForegroundWindow(hWnd);
    
    user32.SetFocus( winOne.winHandle);
    Thread.sleep(500);
    user32.ShowWindow(winOne.winHandle, WinUser.SW_SHOWNOACTIVATE);
    
    return false;
    ...
    

    【讨论】:

      猜你喜欢
      • 2015-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-12
      • 1970-01-01
      • 2021-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多