- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在编写一种网络小程序模拟器。我看了一个网页,找到小程序参数,下载小程序运行。 小程序在其自己的进程中运行(即不是模拟器进程)非常重要。但是,它应该在模拟器进程窗口中呈现。
Java 插件是如何做到的? 当 separate_jvm
设置标志后,插件会在单独的 JVM 进程中加载小程序,但小程序仍会出现在同一浏览器面板中。
我通过创建一个加载器类取得了一些进展,该加载器类在另一个 JVM 上将目标 Applet 添加到一个未修饰的、不可见的框架中,并将该框架的窗口句柄发送给模拟器 JVM。后者将其绑定(bind)到 Canvas
带有 user32.SetParent
的实例通过 JNA,显示效果很好。
但是,只发送鼠标事件:不转发键盘输入。小程序报告Component#isFocusOwner
为假,requestFocusInWindow
不会使其成为焦点所有者,返回 false。 如何将键盘焦点传递给 Applet 窗口句柄?我目前的方法涉及服务器(模拟器),它从客户端(applet)接收窗口句柄。只有鼠标事件似乎有效,因为 Applet 无法获得焦点。
服务器类处理小程序的显示。
import com.sun.jna.*;
import com.sun.jna.platform.win32.User32;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import static com.sun.jna.platform.win32.User32.*;
public class Loader {
private static final String APPLET_DIRECTORY = ""; // TODO: Set this to the directory containing the compiled applet
private static ServerSocket serverSocket;
private static JFrame frame;
private static Canvas nativeDisplayCanvas;
public static void main(String[] argv) throws Exception {
nativeDisplayCanvas = new Canvas();
frame = new JFrame("Frame redirect");
frame.setLayout(new BorderLayout());
frame.add(nativeDisplayCanvas, BorderLayout.CENTER);
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
(new Thread() {
public void run() {
try {
serve();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
spawnAltJVM(APPLET_DIRECTORY, "AppletDemo");
}
public static void serve() throws Exception {
serverSocket = new ServerSocket(6067);
serverSocket.setSoTimeout(10000);
while (true) {
try {
System.out.println("Waiting for applet on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Connected to " + server.getRemoteSocketAddress());
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
DataOutputStream out = new DataOutputStream(server.getOutputStream());
while (true) {
String msg = in.readLine();
if (msg != null && msg.startsWith("child_hwnd")) {
windowCreatedHandler(msg);
out.writeUTF("hwnd_recv\n");
out.flush();
}
}
} catch (IOException ex) {
System.out.println("Something happened to the socket...");
break;
}
}
}
public static void windowCreatedHandler(String message) {
String[] tokens = message.split(":");
final User32 user32 = User32.INSTANCE;
HWND child_applet = new HWND(Pointer.createConstant(Long.parseLong(tokens[1])));
final HWND child_frame = new HWND(Pointer.createConstant(Long.parseLong(tokens[2])));
frame.addComponentListener(
new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
user32.SetWindowPos(child_frame, new HWND(Pointer.NULL), 0, 0, frame.getWidth(), frame.getHeight(), 0);
}
}
);
HWND parent = new HWND(Native.getComponentPointer(nativeDisplayCanvas));
user32.SetParent(child_applet, parent);
int style = user32.GetWindowLong(child_frame, GWL_STYLE) & ~WS_POPUP | (WS_CHILD | WS_VISIBLE);
user32.SetWindowLong(child_applet, GWL_STYLE, style);
user32.SetWindowPos(child_applet, new HWND(Pointer.NULL), 0, 0, nativeDisplayCanvas.getWidth(), nativeDisplayCanvas.getHeight(), 0);
}
public static void spawnAltJVM(String cp, String clazz) throws IOException, InterruptedException, ClassNotFoundException {
ProcessBuilder processBuilder = new ProcessBuilder(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java", "-cp", cp, clazz);
Process applet = processBuilder.start();
final BufferedReader in = new BufferedReader(new InputStreamReader(applet.getInputStream()));
final BufferedReader err = new BufferedReader(new InputStreamReader(applet.getErrorStream()));
(new Thread() {
public void run() {
while (true) {
try {
System.out.println("[client] " + in.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
与此同时,客户端类只是实例化句柄并向其发送消息。
import sun.awt.windows.WComponentPeer;
import javax.swing.*;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingDeque;
public class AppletDemo extends Applet {
private Canvas canvas;
private static Color backgroundColor = Color.RED;
public AppletDemo() {
setLayout(new BorderLayout());
canvas = new Canvas();
add(canvas, BorderLayout.CENTER);
setBackground(Color.CYAN);
canvas.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
refreshColors();
}
});
canvas.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
refreshColors();
}
});
}
private void refreshColors() {
SwingUtilities.invokeLater(
new Runnable() {
@Override
public void run() {
backgroundColor = (backgroundColor == Color.RED ? Color.GREEN : Color.RED);
canvas.setBackground(backgroundColor);
}
}
);
}
public static void main(String[] argv) throws Exception {
System.setErr(System.out);
final AppletDemo app = new AppletDemo();
Frame frame = new Frame("AppletViewer");
frame.setLayout(new BorderLayout());
frame.add(app, BorderLayout.CENTER);
frame.setUndecorated(true);
frame.pack(); // Create the native peers
frame.setSize(300, 200);
final Socket client = new Socket("localhost", 6067);
final LinkedBlockingDeque<String> messageQueue = new LinkedBlockingDeque<>();
final DataOutputStream out = new DataOutputStream(client.getOutputStream());
final BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
(new Thread() {
public void run() {
while (true) {
try {
out.writeBytes(messageQueue.take() + "\n");
out.flush();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
}
}
}).start();
(new Thread() {
public void run() {
while (true) {
try {
if ("hwnd_recv".equals(in.readLine())) {
// Attempt to grab focus in the other process' frame
System.out.println("Trying to request focus...");
System.out.println(app.requestFocusInWindow());
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}).start();
messageQueue.add("child_hwnd:" + ((WComponentPeer) app.getPeer()).getHWnd() + ":" + ((WComponentPeer) frame.getPeer()).getHWnd());
}
}
它们都有点冗长,因为它们需要一些套接字工作,但它们是可编译的,应该可以证明问题。它们需要 JNA 来编译。我以一些良好做法为代价尽可能地缩短了它们。
当 Loader
运行时,应该会出现一个重定向 AppletDemo
Canvas 的窗口。发送鼠标事件: Canvas 在按下鼠标时在红色和绿色之间切换。理想情况下,击键也应该发生相同的行为。
我使用 WinSpy 获取 notepad.exe 窗口和文本 Pane 的句柄,并将句柄硬编码到 Loader
中。键盘焦点与多行编辑控件完美配合,但与顶层窗口本身配合不佳。为什么?这与我遇到的问题有关吗?
我在 WinSpy 中打开一个运行小程序的 Chrome 窗口,发现该插件没有创建虚拟 Frame
— 小程序 Canvas 直接设置为 Chrome 的子项。但是,我无法为 Applet
创建本地对等点,因为它似乎要求它是可显示的。
我读过 dangers of cross-process parent/child or owner/owned window relationship , 但我想不出更好的方法将子小程序移植到模拟器中。
最佳答案
由于您真正想要的是将 applet 创建为子窗口,因此简单的解决方案是说服 applet 成为您的子窗口,而不是强行采用它,并同时针对 Windows 和 JVM 工作。
幸运的是,Sun/Oracle Java VM 带有一个名为 WComponentFrame
的类(正如名称所暗示的那样,仅限 Windows)。它可以从 hwnd
构建,您可以从父进程发送它。然后可以将小程序添加为窗口的子项。
import sun.awt.windows.WComponentPeer;
frame = new WEmbeddedFrame(hwnd);
frame.setLayout(new BorderLayout());
frame.add(applet, BorderLayout.CENTER);
关于java - 采用另一个进程的子窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27810513/
考虑以下代码: template struct list { template list(Args...) { static_assert(sizeof..
考虑以下代码: template struct list { template list(Args...) { static_assert(sizeof..
最近才开始学习"new"OpenGL(可编程而不是固定功能,我从 Nehe 教程中学到的),我想知道自从 OpenGL 4 发布以来学习 OpenGL 3 是否真的有用。 我问的原因是因为我想知道能够
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我想了解如何操作特征向量/矩阵。我想实现最小二乘高斯牛顿算法(因此我学习使用 Eigen 库)。我有一个 1x6 的参数 vector ,每次迭代都需要更新它们。现在,我只想弄清楚函数如何将 vect
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 5 年前。 Improv
我发现编写适用于Enums的静态方法非常困难。这是一个非常人为的示例,但假设您想要编写一个方法,该方法采用 Enum 常量并返回下一个声明的常量。我发现(大约一个小时后)你可以按如下方式进行。它可以工
我正在尝试编写一个函数,在某些条件下,将指向结构的指针更改为指向不同的结构。 我的限制是我想保留初始函数签名,该签名将指向指针(而不是特定结构类型)的通用指针作为参数。 这行不通: [nav] In
我正在尝试将 Keras 示例改编为 VAE https://blog.keras.io/building-autoencoders-in-keras.html 我修改了代码,使用有噪声的 mnist
自 JPA 2.0 以来,关系上有 orphanRemoval 属性,它极大地简化了父子关系的更新,并且与级联删除一起允许删除树的整个分支并轻松删除它。 但是,也有一些情况可能被标记为“收养”,即您将
我正在尝试编写一个类,它能够在以后及时调用不带参数的 lambda。我期待 C++17 类模板参数推导以避免需要工厂函数。但是,尝试在不指定类型的情况下实例化对象会失败。我可以很好地使用工厂功能,但我
我怎样才能避免并非所有控制路径都在此处返回容器的事实: enum Type {Int, String}; Container containerFactory(Type
我开始学习 C++ 和 STL。 我有一个问题: 写一个函数模板palindrome,接受一个 vector 参数并返回true或false来检查 vector 是否是回文(12321是回文,1234
我一直在尝试获取一个条目值(代码中的 S1)以将其自身设置为一个值(_attributes 字典中的 STR),但我就是无法让它工作。我想让它成为一个最终的顶层循环,但我在这方面一步一步来,因为我是一
我想做同样的事情 How do I get the number of days between two dates in JavaScript? 但我想对此日期格式执行相同操作:2000-12-31
我想编写一个带有构造函数的 C++ 类,该构造函数将 auto_ptr 作为其参数,以便我可以将类实例从 auto_ptr 初始化为另一个实例: #include class A { public:
我需要一种方法,我可以在其中获取二维数组中的输入并以最快的方式之一对其进行逐行排序。我尝试使用 Insertion Sort 同时获取 Input 和 Sort it。我使用的第二件事是我单独为一行取
好的,我已经阅读了一些关于 IDisposable 最佳实践的文章,我想我基本上明白了(终于)。 我的问题与从 IDisposable 基类继承有关。我看到的所有示例都在子类中一遍又一遍地编写相同的代
定义类时,以下是否有效? T(const T&&) = default; 我正在阅读移动构造函数 here并且它解释了如何仍然可以隐式声明默认值: A class can have multiple
我想使用 LoadLibrary 开发一个插件系统。 我的问题是:我希望我的函数采用 const char* 而 LoadLibrary 采用 LPCTSTR。 我有一个聪明的想法来做(LPCSTR)
我是一名优秀的程序员,十分优秀!