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

如何在Java中获取原生窗口句柄通过JNI传递给C++ DLL实现JavaFX窗口置底

解决方案

1. 调整JNI方法签名

不要在C侧遍历查找窗口,效率低且容易匹配错误,直接修改JNI方法新增窗口句柄入参,由Java侧获取后传入即可。
修改后的C
代码:

#define FLAGS (SWP_NOMOVE | SWP_NOSIZE) // 保留窗口原有位置和尺寸,不需要可删除
#define ALWAYS_ON_BOTTOM HWND_BOTTOM

JNIEXPORT void JNICALL Java_libreria_WindowsHandlerWrapper_SetAlwaysOnBottom
(JNIEnv* env, jobject obj, jlong hWndValue) {
    HWND hWnd = (HWND)hWndValue;
    SetWindowPos(
        hWnd,
        ALWAYS_ON_BOTTOM,
        0, 0, 0, 0, // 配合SWP_NOMOVE、SWP_NOSIZE参数,这四个值会被自动忽略
        FLAGS
    );
}

同步修改Java侧的native方法声明:

package libreria;
public class WindowsHandlerWrapper {
    public native void SetAlwaysOnBottom(long hWnd);
    // 原有DLL加载逻辑保留
    static {
        System.loadLibrary("你的DLL文件名");
    }
}

2. JavaFX侧获取原生窗口句柄

根据你使用的JDK版本选择对应实现,必须在Stage调用show()方法之后再执行获取逻辑,未显示的窗口无法拿到有效句柄:

适用于Java 8

import com.sun.javafx.stage.StageHelper;
import javafx.stage.Stage;

long hWnd = StageHelper.getStagePeer(stage).getNativeHandle();

适用于Java 9及以上版本

Java 9之后模块化隐藏了内部API,通过反射获取即可:

import javafx.stage.Stage;
import java.lang.reflect.Method;

public long getHWnd(Stage stage) throws Exception {
    Method getPeerMethod = Stage.class.getMethod("getPeer");
    Object windowPeer = getPeerMethod.invoke(stage);
    Method getNativeHandleMethod = windowPeer.getClass().getMethod("getNativeHandle");
    return (long) getNativeHandleMethod.invoke(windowPeer);
}

3. 最终调用

拿到句柄后直接调用JNI方法即可完成窗口置底:

long hWnd = getHWnd(yourStage);
new WindowsHandlerWrapper().SetAlwaysOnBottom(hWnd);

注意事项

  • 如果需要窗口在大小、位置变化后始终保持置底,可以监听Stage的xProperty()、yProperty()、widthProperty()、heightProperty()变化,每次变更后重新调用一次置底方法
  • 该实现仅适用于Windows平台,跨平台场景需要单独适配其他系统的原生API

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 07:45:04