You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Windows系统中用Java实现类似系统快捷键的分屏效果?

实现JFrame窗口的Windows半屏分屏效果(无侧边距)

问题描述

Windows系统中按下⊞ Win + ←/→快捷键,可让应用窗口无缝占据半屏。但通过Java代码设置JFrame尺寸为屏幕宽度一半、可用高度,位置设为(0,0)时,窗口底部和左侧会出现小边距,需实现和系统快捷键一致的无间隙半屏效果,询问是否可通过Java或JNI实现。

用户尝试的代码:

JFrame testFrame = new JFrame();

Rectangle windowBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
testFrame.setSize(windowBounds.width / 2, windowBounds.height);
testFrame.setLocation((int) windowBounds.getMinX(), (int) windowBounds.getMinY());

testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testFrame.setVisible(true);

解决方案

一、Java原生实现(无需JNI)

问题根源是JFrame的标题栏、边框会占用额外空间,单独使用setSize和setLocation无法适配这些装饰区域,以下是两种可行方法:

  1. 适配窗口装饰计算准确边界
    通过获取屏幕Insets(任务栏等系统区域),结合窗口装饰的尺寸,直接用setBounds设置完整窗口边界:
import javax.swing.*;
import java.awt.*;

public class HalfScreenFrame {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame testFrame = new JFrame();
            testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // 获取屏幕设备与边界信息
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice gd = ge.getDefaultScreenDevice();
            Rectangle screenBounds = gd.getDefaultConfiguration().getBounds();
            Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration());

            // 计算左侧半屏的准确尺寸(含窗口装饰)
            int halfWidth = (screenBounds.width - screenInsets.left - screenInsets.right) / 2;
            int fullHeight = screenBounds.height - screenInsets.top - screenInsets.bottom;
            testFrame.setBounds(
                screenInsets.left, 
                screenInsets.top, 
                halfWidth + screenInsets.left, 
                fullHeight + screenInsets.top + screenInsets.bottom
            );

            testFrame.setVisible(true);
        });
    }
}
  1. 使用无装饰窗口(无标题栏边框)
    如果不需要窗口的标题栏和边框,可设置为无装饰模式,此时尺寸和位置设置会更精准:
import javax.swing.*;
import java.awt.*;

public class HalfScreenFrame {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame testFrame = new JFrame();
            testFrame.setUndecorated(true); // 关闭窗口装饰
            testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            Rectangle screenBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
            testFrame.setBounds(0, 0, screenBounds.width / 2, screenBounds.height);

            testFrame.setVisible(true);
        });
    }
}

二、JNI调用Windows API实现(完全匹配系统快捷键效果)

如果需要和Win+←/→完全一致的系统级分屏效果,可通过JNI调用Windows API模拟系统分屏指令:

  1. C++本地代码(编译为DLL)
#include <windows.h>
#include <jni.h>

JNIEXPORT void JNICALL Java_HalfScreenFrame_moveToLeftHalf(JNIEnv *env, jobject obj) {
    // 获取Java端传递的窗口句柄
    jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), "hwnd", "J");
    HWND hwnd = (HWND)env->GetLongField(obj, fid);
    
    // 方法1:发送系统分屏消息,模拟Win+←快捷键效果
    SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | MF_LEFT, 0);
    
    // 方法2:直接用SetWindowPos设置窗口到左侧半屏
    // RECT screenRect;
    // GetWindowRect(GetDesktopWindow(), &screenRect);
    // int halfWidth = (screenRect.right - screenRect.left) / 2;
    // SetWindowPos(hwnd, HWND_TOP, screenRect.left, screenRect.top, halfWidth, screenRect.bottom - screenRect.top, SWP_SHOWWINDOW);
}
  1. Java端调用代码
import javax.swing.*;
import java.lang.reflect.Field;

public class HalfScreenFrame {
    private long hwnd;

    static {
        System.loadLibrary("HalfScreen"); // 加载编译好的DLL文件
    }

    private native void moveToLeftHalf();

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame testFrame = new JFrame();
            testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            testFrame.setVisible(true);

            // 通过反射获取JFrame的Windows句柄
            try {
                Field field = testFrame.getClass().getDeclaredField("hwnd");
                field.setAccessible(true);
                HalfScreenFrame frame = new HalfScreenFrame();
                frame.hwnd = field.getLong(testFrame);
                frame.moveToLeftHalf();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}

内容的提问来源于stack exchange,提问作者Cardinal System

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 10:22:45