- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试将应用程序切换器添加到我正在处理的更大项目中。它需要在 Windows XP/Vista/7/8 上运行。我正在使用 Java 1.7。下面是我创建的示例应用程序,用于演示我遇到的一些问题。我是 JNA 的新手。
非常感谢'Hovercraft Full of Eels' 的 this answer (以及许多其他!)构成测试应用程序的基础。
这是我的问题:
图像绘制 - 我从窗口图标中获取的图像是黑白绘制的。我从 this answer 修改了 getImageForWindow 中的代码麦克道尔(谢谢!)。有没有更好的方法将 HICON 对象转换为 java.awt.Image?我注意到 com.sun.jna.platform.win32.W32API.HICON 中有一个名为“fromNative”的方法,但我不知道如何使用它。
获取图标 - 我用来获取图标句柄的调用 GetClassLongW(hWnd, GCL_HICON) 不会从 64 位窗口返回图标。我想为此我需要 GetClassLongPtr,但我似乎无法通过 JNA 访问它。
根据 Alt-tab 弹出窗口获取正确的窗口列表 - 我试图复制在 this C++ answer 中完成的操作但我无法设法获得用 Java 实现的第二次(GetAncestor 等)和第三次(STATE_SYSTEM_INVISIBLE)检查。我使用了一个糟糕的替代品,它排除了标题为空白的窗口(忽略了一些合法的窗口)。
注意:运行此示例需要 JNA 和 Platform jar:
package test;
import static test.WindowSwitcher.User32DLL.*;
import static test.WindowSwitcher.Gdi32DLL.*;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class WindowSwitcher
{
public static void main(String args[])
{
JFrame JF = new JFrame();
JPanel JP = new JPanel(new GridLayout(0, 1));
JF.getContentPane().add(JP);
Vector<WindowInfo> V = getActiveWindows();
for (int i = 0; i < V.size(); i++)
{
final WindowInfo WI = V.elementAt(i);
JButton JB = new JButton(WI.title);
if(WI.image != null)
{
JB.setIcon(new ImageIcon(WI.image));
}
JB.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
SetForegroundWindow(WI.hWnd);
}
});
JP.add(JB);
}
JF.setSize(600,50+V.size()*64);
JF.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JF.setAlwaysOnTop(true);
JF.setFocusableWindowState(false);
JF.setVisible(true);
}
public static Vector<WindowInfo> getActiveWindows()
{
final Vector<WindowInfo> V = new Vector();
EnumWindows(new WNDENUMPROC()
{
public boolean callback(Pointer hWndPointer, Pointer userData)
{
HWND hWnd = new HWND(hWndPointer);
// Make sure the window is visible
if(IsWindowVisible(hWndPointer))
{
int GWL_EXSTYLE = -20;
long WS_EX_TOOLWINDOW = 0x00000080L;
// Make sure this is not a tool window
if((GetWindowLongW(hWndPointer, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) == 0)
{
// Get the title bar text for the window
char[] windowText = new char[512];
GetWindowTextW(hWnd, windowText, windowText.length);
String wText = Native.toString(windowText);
// Make sure the text is not null or blank
if(!(wText == null || wText.trim().equals("")))
{
// Get the icon image for the window (if available)
Image image = getImageForWindow(hWnd, wText);
// This window is a valid taskbar button, add a WindowInfo object to the return vector
V.add(new WindowInfo(wText, hWnd, image));
}
}
}
return true;
}
}, null);
return V;
}
public static Image getImageForWindow(HWND hWnd, String wText)
{
// Get an image from the icon for this window
int hicon = GetClassLongW(hWnd, GCL_HICON);
if(hicon == 0)
return null;
Pointer hIcon = new Pointer(hicon);
int width = 64;
int height = 64;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
draw(image, hIcon, DI_NORMAL);
BufferedImage mask = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
draw(mask, hIcon, DI_MASK);
applyMask(image, mask);
return image;
}
public static void draw(BufferedImage image, Pointer hIcon, int diFlags)
{
int width = image.getWidth();
int height = image.getHeight();
Pointer hdc = CreateCompatibleDC(Pointer.NULL);
Pointer bitmap = CreateCompatibleBitmap(hdc, width, height);
SelectObject(hdc, bitmap);
DrawIconEx(hdc, 0, 0, hIcon, width, height, 0, Pointer.NULL, diFlags);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < width; y++)
{
int rgb = GetPixel(hdc, x, y);
image.setRGB(x, y, rgb);
}
}
DeleteObject(bitmap);
DeleteDC(hdc);
}
private static void applyMask(BufferedImage image,
BufferedImage mask)
{
int width = image.getWidth();
int height = image.getHeight();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int masked = mask.getRGB(x, y);
if ((masked & 0x00FFFFFF) == 0)
{
int rgb = image.getRGB(x, y);
rgb = 0xFF000000 | rgb;
image.setRGB(x, y, rgb);
}
}
}
}
static class User32DLL
{
static
{
Native.register("user32");
}
public static native int GetWindowTextW(HWND hWnd, char[] lpString, int nMaxCount);
public static native boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer arg);
public static interface WNDENUMPROC extends com.sun.jna.win32.StdCallLibrary.StdCallCallback
{
boolean callback(Pointer hWnd, Pointer arg);
}
public static native boolean IsWindowVisible(Pointer hWnd);
public static native boolean SetForegroundWindow(HWND hWnd);
public static native int GetWindowLongW(Pointer hWnd, int nIndex);
public static int GCL_HICON = -14;
public static int GCL_HICONSM = -34;
public static native int GetClassLongW(HWND hWnd, int nIndex);
/** @see #DrawIconEx(Pointer, int, int, Pointer, int, int, int, Pointer, int) */
public static final int DI_COMPAT = 4;
public static final int DI_DEFAULTSIZE = 8;
public static final int DI_IMAGE = 2;
public static final int DI_MASK = 1;
public static final int DI_NORMAL = 3;
public static final int DI_APPBANDING = 1;
/** http://msdn.microsoft.com/en-us/library/ms648065(VS.85).aspx */
public static native boolean DrawIconEx(Pointer hdc, int xLeft,
int yTop, Pointer hIcon, int cxWidth, int cyWidth,
int istepIfAniCur, Pointer hbrFlickerFreeDraw,
int diFlags);
}
static class Gdi32DLL
{
static
{
Native.register("gdi32");
}
/** http://msdn.microsoft.com/en-us/library/dd183489(VS.85).aspx */
public static native Pointer CreateCompatibleDC(Pointer hdc);
/** http://msdn.microsoft.com/en-us/library/dd183488(VS.85).aspx */
public static native Pointer CreateCompatibleBitmap(Pointer hdc, int nWidth, int nHeight);
/** http://msdn.microsoft.com/en-us/library/dd162957(VS.85).aspx */
public static native Pointer SelectObject(Pointer hdc, Pointer hgdiobj);
/** http://msdn.microsoft.com/en-us/library/dd145078(VS.85).aspx */
public static native int SetPixel(Pointer hdc, int X, int Y, int crColor);
/** http://msdn.microsoft.com/en-us/library/dd144909(VS.85).aspx */
public static native int GetPixel(Pointer hdc, int nXPos, int nYPos);
/** http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx */
public static native boolean DeleteObject(Pointer hObject);
/** http://msdn.microsoft.com/en-us/library/dd183533(VS.85).aspx */
public static native boolean DeleteDC(Pointer hdc);
}
}
class WindowInfo
{
String title;
HWND hWnd;
Image image;
public WindowInfo(String title, HWND hWnd, Image image)
{
this.title = title;
this.hWnd = hWnd;
this.image = image;
}
}
最佳答案
我找到了适合我的目的的解决方法。这比我第一次尝试要简单得多!我现在使用 sun.awt.shell.ShellFolder 获取图标,不幸的是,这是一个未记录/不受支持的类,可能会在未来的 Java 版本中删除。还有另一种使用 FileSystemView 获取图标的方法,但返回的图标对于我的目的来说太小了(在我下面的示例中被注释掉了 - getImageForWindowIcon 方法)。
此解决方法基于 this SO answer by aleroot .我获取进程文件路径(用于打开窗口的 exe 文件,我将其与其他窗口详细信息存储在 WindowInfo 对象中),然后使用 ShellFolder 获取与该文件关联的图标。 注意:这并不总是提供正确的图标(例如,用于运行 Netbeans 进程的文件是 java.exe,因此您得到的是 Java 图标,而不是 Netbeans 图标!)。但在大多数情况下,它运行良好!
解决方法解决了上面的问题 1 和 2,但如果有人有更好的解决方案,请告诉我。我对问题 3 一无所获,但我现在必须做的是窗口列表。
这是我更新的代码...注意:运行此示例需要 JNA 和 Platform jar:
package test;
import static test.WindowSwitcher.User32DLL.*;
import static test.WindowSwitcher.Kernel32.*;
import static test.WindowSwitcher.Psapi.*;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.ptr.PointerByReference;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import sun.awt.shell.ShellFolder;
public class WindowSwitcher
{
public static void main(String args[])
{
new WindowSwitcher();
}
public WindowSwitcher()
{
JFrame JF = new JFrame("Window Switcher");
JPanel JP = new JPanel(new GridLayout(0, 1));
JF.getContentPane().add(JP);
Vector<WindowInfo> V = getActiveWindows();
for (int i = 0; i < V.size(); i++)
{
final WindowInfo WI = V.elementAt(i);
JButton JB = new JButton(WI.title);
if(WI.image != null)
{
JB.setIcon(new ImageIcon(WI.image));
}
JB.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
SetForegroundWindow(WI.hWnd);
}
});
JP.add(JB);
}
JF.setSize(600,50+V.size()*64);
JF.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JF.setAlwaysOnTop(true);
JF.setFocusableWindowState(false);
JF.setVisible(true);
}
private Vector<WindowInfo> getActiveWindows()
{
final Vector<WindowInfo> V = new Vector();
EnumWindows(new WNDENUMPROC()
{
public boolean callback(Pointer hWndPointer, Pointer userData)
{
HWND hWnd = new HWND(hWndPointer);
// Make sure the window is visible
if(IsWindowVisible(hWndPointer))
{
int GWL_EXSTYLE = -20;
long WS_EX_TOOLWINDOW = 0x00000080L;
// Make sure this is not a tool window
if((GetWindowLongW(hWndPointer, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) == 0)
{
// Get the title bar text for the window (and other info)
WindowInfo info = getWindowTitleAndProcessDetails(hWnd);
// Make sure the text is not null or blank
if(!(info.title == null || info.title.trim().equals("")))
{
// Get the icon image for the window (if available)
info.image = getImageForWindow(info);
// This window is a valid taskbar button, add a WindowInfo object to the return vector
V.add(info);
}
}
}
return true;
}
}, null);
return V;
}
private static final int MAX_TITLE_LENGTH = 1024;
private WindowInfo getWindowTitleAndProcessDetails(HWND hWnd)
{
if(hWnd == null)
return null;
char[] buffer = new char[MAX_TITLE_LENGTH * 2];
GetWindowTextW(hWnd, buffer, MAX_TITLE_LENGTH);
String title = Native.toString(buffer);
PointerByReference pointer = new PointerByReference();
GetWindowThreadProcessId(hWnd, pointer); //GetForegroundWindow()
Pointer process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pointer.getValue());
GetModuleBaseNameW(process, null, buffer, MAX_TITLE_LENGTH);
String Sprocess = Native.toString(buffer);
GetModuleFileNameExW(process, null, buffer, MAX_TITLE_LENGTH);
String SprocessFilePath = Native.toString(buffer);
return new WindowInfo(title, Sprocess, SprocessFilePath, hWnd, null);
}
private Image getImageForWindow(WindowInfo info)
{
if(info.processFilePath == null || info.processFilePath.trim().equals(""))
return null;
try
{
File f = new File(info.processFilePath);
if(f.exists())
{
// https://stackoverflow.com/questions/10693171/how-to-get-the-icon-of-another-application
// http://www.rgagnon.com/javadetails/java-0439.html
ShellFolder sf = ShellFolder.getShellFolder(f);
if(sf != null)
return sf.getIcon(true);
// Image returned using this method is too small!
//Icon icon = FileSystemView.getFileSystemView().getSystemIcon(f);
}
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
static class Psapi
{
static
{
Native.register("psapi");
}
public static native int GetModuleBaseNameW(Pointer hProcess, Pointer hmodule, char[] lpBaseName, int size);
public static native int GetModuleFileNameExW(Pointer hProcess, Pointer hmodule, char[] lpBaseName, int size);
}
static class Kernel32
{
static
{
Native.register("kernel32");
}
public static int PROCESS_QUERY_INFORMATION = 0x0400;
public static int PROCESS_VM_READ = 0x0010;
public static native Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, Pointer pointer);
}
static class User32DLL
{
static
{
Native.register("user32");
}
public static native int GetWindowThreadProcessId(HWND hWnd, PointerByReference pref);
public static native int GetWindowTextW(HWND hWnd, char[] lpString, int nMaxCount);
public static native boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer arg);
public static interface WNDENUMPROC extends com.sun.jna.win32.StdCallLibrary.StdCallCallback
{
boolean callback(Pointer hWnd, Pointer arg);
}
public static native boolean IsWindowVisible(Pointer hWnd);
public static native boolean SetForegroundWindow(HWND hWnd);
public static native int GetWindowLongW(Pointer hWnd, int nIndex);
}
}
class WindowInfo
{
String title, process, processFilePath;
HWND hWnd;
Image image;
public WindowInfo(String title, String process, String processFilePath, HWND hWnd, Image image)
{
this.title = title;
this.process = process;
this.processFilePath = processFilePath;
this.hWnd = hWnd;
this.image = image;
}
}
关于Java - 使用 JNA 的 Windows 任务栏 - 如何将窗口图标 (HICON) 转换为 Java 图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19279134/
https://github.com/mattdiamond/Recorderjs/blob/master/recorder.js中的代码 我不明白 JavaScript 语法,比如 (functio
在 iOS 7 及更早版本中,如果我们想在应用程序中找到 topMostWindow,我们通常使用以下代码行 [[[UIApplication sharedApplication] windows]
我已经尝试解决这个问题很长一段时间了:我无法访问窗口的 url,因为它位于另一个域上..有一些解决方案吗? function login() { var cb = window.ope
是否可以将 FFMPEG 视频流传递到 C# 窗口?现在它在新窗口中作为新进程打开,我只是想将它传递给我自己的 SessionWindow。 此时我像这样执行ffplay: public void E
我有一个名为 x 的矩阵看起来像这样: pTime Close 1 1275087600 1.2268 2 1275264000 1.2264 3 1275264300 1.2
在编译时,发生搜索,grep搜索等,Emacs会在单独的窗口中创建一个新的缓冲区来显示结果,有没有自动跳转到那个窗口的方法?这很有用,因为我可以使用 n 和 p 而不是 M-g n 和 M-g p 移
我有一个启动 PowerShell 脚本的批处理文件。 批处理文件: START Powershell -executionpolicy RemoteSigned -noexit -file "MyS
我有一个基于菜单栏的应用程序,单击图标时会显示一个窗口。在 Mac OS X Lion 上一切正常,但由于某种原因,在 Snow Leopard 和早期版本的 Mac OS X 上会出现错误。任何时候
在 macOS 中,如何在 Xcode 和/或 Interface Builder 中创建带有“集成标题栏和工具栏”的窗口? 这是“宽标题栏”类型的窗口,已添加到 OS X 10.10 Yosemit
在浏览器 (Chrome) 中 JavaScript: var DataModler = { Data: { Something: 'value' }, Process: functi
我有 3 个 html 页面。第 1 页链接到第 2 页,第 2 页链接到第 3 页(为了简单起见)。 我希望页面 2 中的链接打开页面 3 并关闭页面 1(选项卡 1)。 据我了解,您无法使用 Ja
当点击“创建节点”按钮时,如何打开一个新的框架或窗口?我希望新框架包含一个文本字段和下拉菜单,以便用户可以选择一个选项。 Create node Search node
我有一个用户控件,用于编辑应用程序中的某些对象。 我最近遇到一个实例,我想弹出一个新的对话框(窗口)来托管此用户控件。 如何实例化新窗口并将需要设置的任何属性从窗口传递到用户控件? 感谢您的宝贵时间。
我有一个Observable,它发出许多对象,我想使用window或buffer操作对这些对象进行分组。但是,我不想指定count参数来确定窗口中应包含多少个对象,而是希望能够使用自定义条件。 例如,
我有以下代码,它打开一个新的 JavaFX 阶段(我们称之为窗口)。 openAlertBox.setOnAction(e -> { AlertBox alert = AlertBox
我要添加一个“在新窗口中打开”上下文菜单项,该菜单项将以新的UIScene打开我的应用程序文档之一。当然,我只想在实际上支持多个场景的设备上显示该菜单项。 目前,我只是在检查设备是否是使用旧设备的iP
我正在尝试创建一个 AIR 应用程序来记录应用程序的使用情况,使用 AIR 从系统获取信息的唯一简单方法是使用命令行工具和抓取 标准输出 . 我知道像 这样的工具顶部 和 ps 对于 OS X,但它们
所以我有这个简单的 turtle 螺旋制作器,我想知道是否有一种方法可以打印出由该程序创建的我的设计副本。 代码: import turtle x= float(input("Angle: ")) y
我正在编写一个 C# WPF 程序,它将文本消息发送到另一个程序的窗口。我有一个宏程序作为我的键盘驱动程序 (Logitech g15) 的一部分,它已经这样做了,尽管它不会将击键直接发送到进程,而是
我尝试使用以下代码通过 UDP 发送,但得到了奇怪的结果。 if((sendto(newSocket, sendBuf, totalLength, 0, (SOCKADDR *)&sendAd
我是一名优秀的程序员,十分优秀!