Java:点击窗口(包括文本/图像) [英] Java: Making a window click-through (including text/images)

查看:187
本文介绍了Java:点击窗口(包括文本/图像)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Java中创建一个透明始终位于顶部的叠加层,并且我可以点击。我发现了一些类似 提到关于这个问题,但即使在听完他们的答案之后,我也遇到了一个问题。

I want to create an overlay in Java that is transparent, always on top, and that I can click-through. I've found some similar posts about this issue, but even after following their answers, I'm having one issue.

我的问题是点击整个窗口。我在使用JFrame时没有任何问题,但是当我向其添加任何组件(JLabel或ImagePanel)时,点击后属性不会继续对他们来说。

My problem is making the whole window click-through. I'm not having any problem making it work with a JFrame, but once I add any components to it (JLabel or an ImagePanel), the click-through attribute doesn't carry over to them.

因为我想为我的应用程序提供一个背景图像,这基本上使我无法看到无论何时单击区域文本/图像覆盖。

As I want to have a background image for my application this basically makes the code I have useless seeing how the window gets focused whenever I click the area the text/image covers.

在我显示我正在使用的代码之前,我首先要参考这些 threads 基本上描述了我想要的东西,除了在C#中。

Before I show the code I'm using I'd first like to refer to these threads which essentially describes precisely what I want, except in C#.

我的目标是创建一个带有透明.png图像和一些顶部文本的叠加层,这些叠加层会在关键事件上发生变化。如果它使用JFrame或任何其他库无关紧要。我只需要它与Windows兼容。

My goal is to create an overlay with a transparent .png-image and some text on-top that will change on key events. If it uses JFrame or any other library doesn't matter. I only need it compatible with Windows.

我还想提一下我有一些Java经验,但我是使用JFrame的新手。

I'd also like to mention that I've got some experience with Java, but am a novice in using JFrame.

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

import com.sun.jna.platform.WindowUtils;


public class Overlay {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Overlay Window");
        frame.setUndecorated(true);
        frame.setAlwaysOnTop(true);
        frame.getRootPane().putClientProperty("apple.awt.draggableWindowBackground", false);
        frame.setLocation(400, 400);
        frame.getContentPane().setLayout(new java.awt.BorderLayout());

        JLabel textLabel = new JLabel("I'm a label in the window", SwingConstants.CENTER);
        frame.getContentPane().add(textLabel, BorderLayout.CENTER); 
        frame.pack();

        System.setProperty("sun.java2d.noddraw", "true");
        WindowUtils.setWindowTransparent(frame, true);
        WindowUtils.setWindowAlpha(frame, 1.0f);

        //Using AWTUtilities gives the same result as WindowUtils
        //AWTUtilities.setWindowOpaque(frame, false);
        //AWTUtilities.setWindowOpacity(frame, 1.0f);

        frame.setVisible(true);
    }
}

请注意,问题是不是关于窗口被聚焦(虽然这是问题的结果),但关于 JLabel和ImagePanel不是点击

Note that the problem is not about the window being focused (though that is a result of the issue), but about the JLabel and ImagePanel not being click-through.

推荐答案

让窗口点击的问题在于它是在系统级别上处理的,超出了标准API的范围。这意味着为使窗口点击而编写的任何代码都将取决于系统。话虽如此,在Windows上完成此操作的过程非常简单。

The problem with having a window be "click through" is that it's handled on a system level, outside the scope of the standard APIs. This means that any code written to make a window "click through" will be system dependant. That being said, the process for accomplishing this on windows is rather straight forward.

在Windows 2000及更高版本中,通过设置标志 WS_EX_LAYERED和WS_EX_TRANSPARENT 一个窗口上,窗口将随后是通过点击。示例代码使用 JNA 来完成此任务:

On Windows 2000 and later, by setting the flags WS_EX_LAYERED and WS_EX_TRANSPARENT on a window, the window will then be click through. Example code uses JNA to accomplish this:

public static void main(String[] args) {
    Window w = new Window(null);

    w.add(new JComponent() {
        /**
         * This will draw a black cross on screen.
         */
        protected void paintComponent(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(0, getHeight() / 2 - 10, getWidth(), 20);
            g.fillRect(getWidth() / 2 - 10, 0, 20, getHeight());
        }

        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }
    });
    w.pack();
    w.setLocationRelativeTo(null);
    w.setVisible(true);
    w.setAlwaysOnTop(true);
    /**
     * This sets the background of the window to be transparent.
     */
    AWTUtilities.setWindowOpaque(w, false);
    setTransparent(w);
}

private static void setTransparent(Component w) {
    WinDef.HWND hwnd = getHWnd(w);
    int wl = User32.INSTANCE.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE);
    wl = wl | WinUser.WS_EX_LAYERED | WinUser.WS_EX_TRANSPARENT;
    User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, wl);
}

/**
 * Get the window handle from the OS
 */
private static HWND getHWnd(Component w) {
    HWND hwnd = new HWND();
    hwnd.setPointer(Native.getComponentPointer(w));
    return hwnd;
}

这篇关于Java:点击窗口(包括文本/图像)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆