有没有办法在Windows XP中使用Java(或Groovy)更改桌面墙纸?我有一个每天(或随时)创建新图像的程序,我希望有一种自动更新桌面的方法。我在这个站点上看到了一些关于C++或.NET问题,但我没有看到任何特定于Java的问题。
agyaoht71#
对不起,我有点落后于@ataylor的答案,因为我正在准备一个片段来做这件事。是的,JNA是一个正确的方法。在这里,你去:
import java.util.HashMap; import com.sun.jna.Native; import com.sun.jna.platform.win32.WinDef.UINT_PTR; import com.sun.jna.win32.*; public class WallpaperChanger { public static void main(String[] args) { //supply your own path instead of using this one String path = "C:\\Users\\Public\\Pictures\\Sample Pictures\\Chrysanthemum.jpg"; SPI.INSTANCE.SystemParametersInfo( new UINT_PTR(SPI.SPI_SETDESKWALLPAPER), new UINT_PTR(0), path, new UINT_PTR(SPI.SPIF_UPDATEINIFILE | SPI.SPIF_SENDWININICHANGE)); } public interface SPI extends StdCallLibrary { //from MSDN article long SPI_SETDESKWALLPAPER = 20; long SPIF_UPDATEINIFILE = 0x01; long SPIF_SENDWININICHANGE = 0x02; SPI INSTANCE = (SPI) Native.loadLibrary("user32", SPI.class, new HashMap<Object, Object>() { { put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); } }); boolean SystemParametersInfo( UINT_PTR uiAction, UINT_PTR uiParam, String pvParam, UINT_PTR fWinIni ); } }
你需要在类路径上有JNA库才能工作。这是在Windows7中测试的,在XP中可能会有一些细微差别,但我认为它应该工作。那个API应该是稳定的。
编辑(2010年1月20日):我以前省略了选项SPIF_UPDATEINIFILE和SPIF_SENDWININICHANGE。现在按照Coding 4Fun MSDN文章中的建议使用这些选项。
SPIF_UPDATEINIFILE
SPIF_SENDWININICHANGE
rm5edbpk2#
你可以做得更容易:
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.platform.win32.WinDef.PVOID; import com.sun.jna.win32.W32APIOptions; public class Wallpaper { public static interface User32 extends Library { User32 INSTANCE = (User32) Native.loadLibrary("user32",User32.class,W32APIOptions.DEFAULT_OPTIONS); boolean SystemParametersInfo (int one, int two, String s ,int three); } public static void main(String[] args) { User32.INSTANCE.SystemParametersInfo(0x0014, 0, "C:\\Users\\Public\\Pictures\\Sample Pictures\\Chrysanthemum.jpg" , 1); } }
r55awzrz3#
您可以编写一个batch file to change the wall-paper,并使用以下命令执行该批处理文件:Runtime.getRuntime.exec()
Runtime.getRuntime.exec()
ocebsuys4#
JNA java库允许您轻松调用Win32 API调用,特别是要更改桌面背景,需要调用SystemParametersInfo函数。请参阅这篇文章,了解JNA的简介:http://today.java.net/article/2009/11/11/simplify-native-code-access-jna
bsxbgnwa5#
这是一个纯Java实现,它使用Project Panama将本机回调到Windows USER32.DLL中。请注意,API正在孵化,因此在JDK 16、17和更高版本之间发生了变化。这些示例使用当前JDK 16/17版本中的Panama版本,如果您切换到最新的Panama Early Access版本,则可能需要进行一些更改。
import java.lang.invoke.*; import java.nio.file.Path; import jdk.incubator.foreign.*; /** %JDK16%\bin\java -Dforeign.restricted=permit --add-modules jdk.incubator.foreign SetWallpaper.java A.JPG */ public class SetWallpaper { static final int SPI_SETDESKWALLPAPER = 0x0014; static final int SPIF_UPDATEINIFILE = 0x01; static final int SPIF_SENDCHANGE = 0x02; public static void main(String[] args) throws Throwable { LibraryLookup user32 = LibraryLookup.ofLibrary("user32"); MethodHandle spi = CLinker.getInstance().downcallHandle(user32.lookup("SystemParametersInfoA").get() // BOOL SystemParametersInfoA (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); , MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class, int.class) , FunctionDescriptor.of(CLinker.C_LONG,CLinker.C_LONG, CLinker.C_LONG, CLinker.C_POINTER, CLinker.C_LONG)); Path path = Path.of(args[0]).toRealPath(); try (NativeScope scope = NativeScope.unboundedScope()) { MemorySegment img = CLinker.toCString(path.toString(), scope); int status = (int)spi.invokeExact(SPI_SETDESKWALLPAPER, 0, img.address(), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE); System.out.println("Changed wallpaper to "+path+" rc="+status+(status == 0 ? "***ERROR***": " OK")); } } }
JDK 17所需的小改动:
/** %JAVA_HOME%\bin\java --enable-native-access=ALL-UNNAMED --add-modules jdk.incubator.foreign SetWallpaper.java A.JPG * / public static void main(String[] args) throws Throwable { System.loadLibrary("user32"); // BOOL SystemParametersInfoA(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); MemoryAddress symbol = SymbolLookup.loaderLookup().lookup("SystemParametersInfoW").get(); MethodHandle SystemParametersInfoW = CLinker.getInstance().downcallHandle(symbol , MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class, int.class) , FunctionDescriptor.of(CLinker.C_LONG,CLinker.C_LONG, CLinker.C_LONG, CLinker.C_POINTER, CLinker.C_LONG)); Path path = Path.of(args[0]).toRealPath(); try(ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope); // toCString as WIDE string Addressable wide = allocator.allocateArray(CLinker.C_CHAR, (path+"\0").getBytes(StandardCharsets.UTF_16LE)); int status = (int)SystemParametersInfoW.invokeExact(SPI_SETDESKWALLPAPER, 0, wide.address(), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE); System.out.println("Changed wallpaper to "+path+" rc="+status+(status == 0 ? "***ERROR***": " OK")); } }
x8diyxa76#
扩展@DuncG的答案,这里有一个更新的解决方案,它使用JDK 18中的Project Panama。
import jdk.incubator.foreign.*; import java.lang.invoke.MethodHandle; import java.nio.file.Path; import static jdk.incubator.foreign.ValueLayout.*; public class WindowsOperatingSystem { private static final int SPI_SETDESKWALLPAPER = 0x0014; private static final int SPIF_UPDATEINIFILE = 0x01; private static final int SPIF_SENDCHANGE = 0x02; private static final MethodHandle systemParametersInfoAFunction; static { System.loadLibrary("user32"); // BOOL SystemParametersInfoA(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); systemParametersInfoAFunction = CLinker.systemCLinker().downcallHandle( SymbolLookup.loaderLookup().lookup("SystemParametersInfoA").get(), FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_INT, JAVA_INT, ADDRESS, JAVA_INT) ); } public static void setWallpaper(Path file) { try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); Addressable nativeFilePath = allocator.allocateUtf8String(file.toString()); var result = (boolean)systemParametersInfoAFunction.invokeExact( SPI_SETDESKWALLPAPER, 0, nativeFilePath, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ); if (!result) { throw new IllegalStateException(); } } catch (Error | RuntimeException t) { throw t; } catch (Throwable t) { throw new RuntimeException(t); } } }
6条答案
按热度按时间agyaoht71#
对不起,我有点落后于@ataylor的答案,因为我正在准备一个片段来做这件事。是的,JNA是一个正确的方法。在这里,你去:
你需要在类路径上有JNA库才能工作。这是在Windows7中测试的,在XP中可能会有一些细微差别,但我认为它应该工作。那个API应该是稳定的。
参考
编辑(2010年1月20日):
我以前省略了选项
SPIF_UPDATEINIFILE
和SPIF_SENDWININICHANGE
。现在按照Coding 4Fun MSDN文章中的建议使用这些选项。rm5edbpk2#
你可以做得更容易:
r55awzrz3#
您可以编写一个batch file to change the wall-paper,并使用以下命令执行该批处理文件:
Runtime.getRuntime.exec()
ocebsuys4#
JNA java库允许您轻松调用Win32 API调用,特别是要更改桌面背景,需要调用SystemParametersInfo函数。
请参阅这篇文章,了解JNA的简介:http://today.java.net/article/2009/11/11/simplify-native-code-access-jna
bsxbgnwa5#
这是一个纯Java实现,它使用Project Panama将本机回调到Windows USER32.DLL中。请注意,API正在孵化,因此在JDK 16、17和更高版本之间发生了变化。这些示例使用当前JDK 16/17版本中的Panama版本,如果您切换到最新的Panama Early Access版本,则可能需要进行一些更改。
JDK 17所需的小改动:
x8diyxa76#
扩展@DuncG的答案,这里有一个更新的解决方案,它使用JDK 18中的Project Panama。