如何将焦点移动到下一个展开的窗口?

问题描述 投票:0回答:1

我正在创建一个脚本,当按下组合键时,它将最小化当前活动窗口并移至下一个窗口。然后,当按下组合键时,展开最后一个最小化的窗口。

最小化活动窗口后,将焦点传递到下一个窗口(如果有)时存在问题。

ShowWindow 文档中写为“SW_MINIMIZE 6 最小化指定窗口并激活 Z 顺序中的下一个顶级窗口。”,但由于某种原因这对我不起作用。

User32.java

import jnr.ffi.LibraryLoader;
import jnr.ffi.Pointer;
import jnr.ffi.annotations.Delegate;
import jnr.ffi.types.u_int32_t;

public interface User32 {
    User32 INSTANCE = LibraryLoader.create(User32.class).load("user32");

    @u_int32_t
    long GetForegroundWindow();

    boolean SetForegroundWindow(@u_int32_t long hWnd);

    boolean ShowWindow(@u_int32_t long hWnd, @u_int32_t long nCmdShow);

    boolean IsIconic(@u_int32_t long hWnd);

    boolean IsWindowVisible(@u_int32_t long hwnd);

    void keybd_event(byte bVk, byte bScan, @u_int32_t int dwFlags,
                     int dwExtraInfo);

    interface WinEnumProc {
        @Delegate
        boolean apply(@u_int32_t long hwnd, Pointer data);
    }

    boolean EnumWindows(WinEnumProc lpEnumFunc, Pointer lParam);
}

WindowManager.java

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;

public class WindowManager {
    private static final Logger log = LogManager.getLogger(WindowManager.class.getName());
    private static final int SW_MINIMIZE = 6;
    private static final int SW_RESTORE = 9;
    private static long lastWindow = 0;


    public static void winMinimize() {
        long activeWin = User32.INSTANCE.GetForegroundWindow();
        log.info("Active window: {}", activeWin);

        if (activeWin != 0) {
            List<Long> windows = new ArrayList<>();

            User32.INSTANCE.EnumWindows((hwnd, data) -> {
                if (User32.INSTANCE.IsWindowVisible(hwnd)) {
                    windows.add(hwnd);
                }
                return true;
            }, null);


            lastWindow = activeWin;
            User32.INSTANCE.ShowWindow(activeWin, SW_MINIMIZE);

            int activeWinIndex = windows.indexOf(activeWin);

            if (activeWinIndex != -1 && activeWinIndex + 1 < windows.size()) {
                long nextWin = windows.get(activeWinIndex + 1);
                log.info("Next win: {}", windows.get(activeWinIndex + 1));
//              User32.INSTANCE.keybd_event((byte) 0xA4, (byte) 0x45, 0x2, 0);
                User32.INSTANCE.SetForegroundWindow(nextWin);
            }

            log.info("Focus: {}", User32.INSTANCE.GetForegroundWindow());
        }
    }

    public static void winRestore() {
        if (lastWindow != 0 && User32.INSTANCE.IsIconic(lastWindow)) {
            User32.INSTANCE.ShowWindow(lastWindow, SW_RESTORE);
            User32.INSTANCE.SetForegroundWindow(lastWindow);
            lastWindow = 0;
        }
    }
}

我创建了一个最大化窗口列表

windows
,从中获取下一个最大化窗口并尝试为其调用
SetForegroundWindow
。该窗口开始闪烁,但焦点仍未转移。

我还找到了一个模拟按 Alt 键的解决方案,

User32.INSTANCE.keybd_event((byte) 0xA4, (byte) 0x45, 0x2, 0)
,但我觉得这很奇怪。我希望获得与鼠标单击最小化窗口按钮时相同的行为。

我已经阅读了关于 SetForegroundWindow 的文档,也许问题出在线程中,但我不明白我需要做什么来解决它。

java winapi user32
1个回答
0
投票

在 @IInspectable 和 @Starship 的建议之后,我阅读了有关 RegisterHotKey 和 AttachThreadInput 的内容。 这确实解决了我的问题。我还找到了使用 RegisterHotKey 的 jintellitype 库。

© www.soinside.com 2019 - 2024. All rights reserved.