使用AWT,我想通過在窗口隱藏時停止繪製到屏幕來節省資源,如閃存。但首先,我需要一種方法來檢測Frame是否完全被一個或多個其他窗口覆蓋。 Windows可能不是來自同一個應用程序,所以我不能總結他們的形狀。是否有可能檢測窗口遮擋
所以問題是,是否有可能檢測窗口是否被其他應用程序的其他窗口覆蓋?
使用AWT,我想通過在窗口隱藏時停止繪製到屏幕來節省資源,如閃存。但首先,我需要一種方法來檢測Frame是否完全被一個或多個其他窗口覆蓋。 Windows可能不是來自同一個應用程序,所以我不能總結他們的形狀。是否有可能檢測窗口遮擋
所以問題是,是否有可能檢測窗口是否被其他應用程序的其他窗口覆蓋?
一切都是可能只是你需要一些創造力和辛勤工作:)
我希望你知道,Java可以調用本地的Windows API(這不會是很業績虎鉗,但我們只有這樣),爲此我們可以使用JNA lib,它可以讓我們訪問本地共享庫。
我已經做了一些快速概念檢查此代碼只檢查活動窗口是否完全覆蓋java應用程序窗口,但您可以遍歷可見窗口並計算面積,JNA也提供該訪問。
對於我的演示項目,我用這些JNA依賴關係:
compile("net.java.dev.jna", "jna", "4.5.0")
compile("net.java.dev.jna", "jna-platform", "4.5.0")
我的主類:
package com.sauliuxx.inc;
import com.sauliuxx.inc.workers.ActiveWindowChecker;
import com.sun.jna.platform.win32.WinDef;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* The type App.
*/
public class App extends Frame implements ActionListener {
private final String title = "Demo123";
private Label sizeLabel;
private Label positionLabel;
private Label visibleLabel;
BlockingQueue<WinDef.RECT> q =
new LinkedBlockingQueue<>();
private App() {
this.setTitle(title);
this.setLayout(new BorderLayout());
this.setSize(500, 500);
Panel infoPanel = new Panel();
sizeLabel = new Label(this.getSize().height + " X " + this.getSize().width);
infoPanel.add(sizeLabel);
positionLabel = new Label("X: " + this.getLocation().getX() + " Y: " + this.getLocation().getY());
infoPanel.add(positionLabel);
visibleLabel = new Label(this.isVisible() ? "true" : "false");
infoPanel.add(visibleLabel);
this.add(infoPanel, BorderLayout.PAGE_END);
Timer timer = new Timer(250, this);
timer.start();
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent componentEvent) {
sizeLabel.setText(componentEvent.getComponent().getSize().height + " X " + componentEvent.getComponent().getSize().width);
}
@Override
public void componentMoved(ComponentEvent componentEvent) {
positionLabel.setText("X: " + componentEvent.getComponent().getLocation().getX() + " Y: " + componentEvent.getComponent().getLocation().getY());
}
@Override
public void componentShown(ComponentEvent componentEvent) {
visibleLabel.setText("true");
}
@Override
public void componentHidden(ComponentEvent componentEvent) {
visibleLabel.setText("false");
}
});
ActiveWindowChecker awcDeamon = new ActiveWindowChecker(q);
awcDeamon.setDaemon(true);
awcDeamon.start();
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
WinDef.RECT rect = null;
try {
rect = q.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (this.isActive()) {
System.out.println("action");
} else {
//System.out.println("rect = " + (rect != null ? rect : ""));
//System.out.println("frame = [(" + (int)this.getLocation().getX() + "," + (int)this.getLocation().getY() + ") (" + this.getSize().width + "," + this.getSize().height + ")]");
// x and y windows to compare top left point
int rxTop = rect == null ? 0: rect.left;
int ryTop = rect == null ? 0:rect.top;
int fxTop = (int) this.getLocation().getX();
int fyTop = (int) this.getLocation().getY();
// bottom right points
int rxBottom = rect == null ? 0: rect.right;
int ryBottom = rect == null ? 0: rect.bottom;
int fxBottom = fxTop + this.getSize().width;
int fyBottom = fyTop + this.getSize().height;
if ((rxTop >= fxTop || ryTop >= fyTop) || (rxBottom <= fxBottom || ryBottom <= fyBottom))
{
System.out.println("Not covered by active window.");
}
else{
System.out.println("Covered by active window.");
}
}
}
/**
* The entry point of application.
*
* @param args the input arguments
*/
public static void main(String... args) {
if (!System.getProperty("os.name").contains("Windows")) {
System.err.println("ERROR: Only implemented on Windows");
System.exit(1);
}
java.awt.EventQueue.invokeLater(() -> new App().setVisible(true));
}
}
我工人階級:
package com.sauliuxx.inc.workers;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import java.util.concurrent.BlockingQueue;
/**
* The type Active window checker.
*/
public class ActiveWindowChecker extends Thread {
private static final int MAX_TITLE_LENGTH = 1024;
private final BlockingQueue<WinDef.RECT> queue;
/**
* Instantiates a new Active window checker.
*
* @param q the q
*/
public ActiveWindowChecker(BlockingQueue<WinDef.RECT> q) {
this.queue = q;
}
@Override
public void run() {
Exception ex = null;
while (ex == null) {
char[] buffer = new char[MAX_TITLE_LENGTH * 2];
WinDef.HWND hwnd = User32.INSTANCE.GetForegroundWindow();
User32.INSTANCE.GetWindowText(hwnd, buffer, MAX_TITLE_LENGTH);
System.out.println("Active window title: " + Native.toString(buffer));
WinDef.RECT rect = new WinDef.RECT();
User32.INSTANCE.GetWindowRect(hwnd, rect);
try {
queue.put(rect);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
ex = e;
}
}
}
}
具有創造性,但對我而言並不理想,因爲我需要至少支持Windows,Linux和OS X.我相信在這些平臺上可以完成相同的任務,但是我發現很難激勵爲多個平臺維護此功能。 – Dolda2000
我相信你有兩個挑戰:構建可以在所有系統上工作的應用程序,並且Java是不錯的選擇,你也可以使用在JVM上運行的其他語言,第二個應用程序應該與所有這些操作系統平臺交互,而這真是太糟糕了。 –
Java的2D應該做的自動。 –
我的測試表明,如果窗口被覆蓋或不覆蓋,渲染速度/成本不受影響。 – warren
你到底有多渲染? [MCVE](http://stackoverflow.com/help/mcve)可能對此有所幫助。 –