5

WindowsでJavaFXアプリケーションを構築しており、Windows7/8タスクバーでのアプリケーションの表示方法を操作するためにいくつかのことを実行できるようにしたいと考えています。これには、「アプリケーションユーザーモデルID 」と呼ばれるWindows変数を変更する必要があります。

JNAを使用して、Swingでやりたいことを正確に実行することができました。このソリューションを、JavaFXで繰り返したいと思います。hWnd残念ながら、これを行うには、アプリケーションの各ウィンドウの(ウィンドウハンドル)を取得できる必要があります。これは、Swing /AWTでJNANative.getWindowPointer()メソッドを介して実行できます。これはで動作しjava.awt.Windowますが、でこれを実行するための適切な方法を見つけることができませんjavafx.stage.Window

誰かが取得する方法を知っていますhWndStage

4

6 に答える 6

3

これがJavaFX2バージョンです(WindowではなくStageを使用します):

private static Pointer getWindowPointer(Stage stage) {
    try {
        TKStage tkStage = stage.impl_getPeer();
        Method getPlatformWindow = tkStage.getClass().getDeclaredMethod("getPlatformWindow" );
        getPlatformWindow.setAccessible(true);
        Object platformWindow = getPlatformWindow.invoke(tkStage);
        Method getNativeHandle = platformWindow.getClass().getMethod( "getNativeHandle" );
        getNativeHandle.setAccessible(true);
        Object nativeHandle = getNativeHandle.invoke(platformWindow);
        return new Pointer((Long) nativeHandle);
    } catch (Throwable e) {
        System.err.println("Error getting Window Pointer");
        return null;
    }
}
于 2014-05-28T01:40:23.803 に答える
2

JNAへの依存関係を追加します。

<dependency>
  <groupId>net.java.dev.jna</groupId>
  <artifactId>jna-platform</artifactId>
  <version>5.3.1</version>
</dependency>

次にStage、明確なタイトル(この例では「MyStage」)を付けてから、次のようなウィンドウIDを取得します。

WinDef.HWND hwnd = User32.INSTANCE.FindWindow(null, "MyStage");

long wid = Pointer.nativeValue(hwnd.getPointer());

これは、JavaFXのバージョンに関係なくWindowsで機能します。

于 2019-06-15T22:05:31.423 に答える
1

次のメソッドは、JavaFXステージ(またはWindow )のネイティブウィンドウハンドル(hWnd)を取得し、それをJNAポインタオブジェクトに格納する方法を示しています。

private static Pointer getWindowPointer(javafx.stage.Window window) {
    Pointer retval = null;
    try {
        Method getPeer = window.getClass().getMethod("impl_getPeer");
        final Object tkStage = getPeer.invoke(window);
        Method getPlatformWindow = tkStage.getClass().getDeclaredMethod("getPlatformWindow");
        getPlatformWindow.setAccessible(true);
        final Object platformWindow = getPlatformWindow.invoke(tkStage);
        Method getNativeHandle = platformWindow.getClass().getMethod("getNativeHandle");
        retval = new Pointer((Long) getNativeHandle.invoke(platformWindow));
    } catch (Throwable t) {
        System.err.println("Error getting Window Pointer");
        t.printStackTrace();
    }
    return retval;
}

このソリューションは、リフレクションを使用して多数のプライベートメソッドにアクセスするため、壊れやすく、一般的に望ましくありません。しかし、それは仕事を成し遂げます。うまくいけば、Oracleは最終的にネイティブウィンドウハンドルへの直接アクセスを提供するので、これを行う必要はありません。

もちろん、このコードはMSWindowsで実行している場合にのみ機能します。また、JavaFX 8の初期リリースビルドでのみ試してみました(ただし、JavaFX 2でも正常に機能すると思われます。編集:JavaFX 2では機能しないようです)。

于 2013-11-01T21:48:50.630 に答える
1
com.sun.glass.ui.Window.getWindows.get(0).getNativeWindow

//

com.sun.glass.ui.Window.getFocusedWindow.getNativeWindow
于 2014-07-12T05:01:02.763 に答える
1

次のコードは、Windows上のJavaFX 11で機能します(必要なのはそこでのみです)。他のバージョンではテストしていません。

非常に脆弱ですが、私の場合は、Javaランタイムをアプリケーションにバンドルしているので、その下にあるものを常に把握しているため、管理しやすくなっています。

Java 9モジュールを使用する場合は、呼び出し元のモジュールに対してパッケージを開く必要もあります。

--add-opens javafx.graphics/javafx.stage=com.example--add-opens javafx.graphics/com.sun.javafx.tk.quantum=com.example

package com.example;

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import javafx.stage.Stage;
import javafx.stage.Window;
import java.lang.reflect.Method;

public class FXWinUtil {

    public static WinDef.HWND getNativeHandleForStage(Stage stage) {
        try {
            final Method getPeer = Window.class.getDeclaredMethod("getPeer", null);
            getPeer.setAccessible(true);
            final Object tkStage = getPeer.invoke(stage);
            final Method getRawHandle = tkStage.getClass().getMethod("getRawHandle");
            getRawHandle.setAccessible(true);
            final Pointer pointer = new Pointer((Long) getRawHandle.invoke(tkStage));
            return new WinDef.HWND(pointer);
        } catch (Exception ex) {
            System.err.println("Unable to determine native handle for window");
            return null;
        }
    }
}

JNAを使用している場合(これは、このようなハックなことをしている場合に発生する可能性があります)、から利益を得ることができますWinDef.HWND

于 2021-08-18T19:06:28.440 に答える
0

Kotlinで記述されたJavaFX16のソリューション(Reflectionのみ)

fun getPointer(scene: Scene): Long {
    val tkStage = SceneHelper.getPeer(scene)

    val windowStage = tkStage.javaClass.getDeclaredMethod("getWindowStage")
        .apply { isAccessible = true }
        .invoke(tkStage)

    val platformWindow = windowStage.javaClass.getDeclaredMethod("getPlatformWindow")
        .apply { isAccessible = true }
        .invoke(windowStage)
    
    // Use fields 'ptr' and 'delegatePtr' instead of getNativeHandle() to avoid Platform.runLater
    val ptr = Window::class.java.getDeclaredField("ptr")
        .apply { isAccessible = true }[platformWindow] as Long

    val delegatePtr = Window::class.java.getDeclaredField("delegatePtr")
        .apply { isAccessible = true }[platformWindow] as Long

    return if (delegatePtr != 0L) delegatePtr else ptr
}

于 2021-12-17T04:45:53.900 に答える