【问题标题】:Change Windows 7 Wallpaper Using Java使用 Java 更改 Windows 7 壁纸
【发布时间】:2016-12-11 03:22:01
【问题描述】:

我在这里找到了这段代码

import java.util.HashMap;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef.UINT_PTR;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIFunctionMapper;
import com.sun.jna.win32.W32APITypeMapper;

public class test {

 public static void main(String[] args) {
      //supply your own path instead of using this one
     String png = "C:\\Overwatch\\690653.png";
     String jpg = "C:\\Witcher\\616521.jpg";
     String path = png;

     System.out.println(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
        );
    }
}

但它似乎不适用于 png。我只能用它来将壁纸设置为 jpg。我一直无法弄清楚 UINT_PTR 在做什么,我想知道是否需要根据图像类型更改其中一个。

我尝试更改为 UINT 并使用 LPWSTR,但它仍然只更改为 jpg。这是我目前拥有的...

 public static void main(String[] args){
     String[] paths = {
             "C:\\Overwatch\\690653.png",
             "C:\\Witcher\\616521.jpg",
             "C:\\wallpapers\\mario.gif",
             "C:\\wallpapers\\Mystic_Tree.wmv"
     };

     for(String path : paths)
         System.out.println(change(path) ? "Worked!\n" + path : "Didn't work :(\n" + path);
 }

 public static interface User32 extends StdCallLibrary {
     User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, W32APIOptions.UNICODE_OPTIONS);        
     boolean SystemParametersInfo (UINT uiAction, UINT uint, Pointer imagePath, UINT fWinIni);         
 }

 public static boolean change(String path){
     Pointer imagePath = new LPWSTR(path).getPointer();

     UINT uiAction = new UINT(0x0014l);
     UINT userPolicy = new UINT(0l);
     long updateIni = 0x01l;
     long sendChange = 0x02l;
     return User32.INSTANCE.SystemParametersInfo(uiAction, userPolicy, imagePath , new UINT(updateIni | sendChange));
 }

【问题讨论】:

    标签: java windows windows-7 jna


    【解决方案1】:

    JNA 代码存在一些问题,尝试回答您关于应使用哪些设置的问题。

    首先,请参阅method signature for SystemParametersInfo。这应该有助于回答您的许多问题。

    注意其中三个参数是UINT(32 位整数)。您应该使用 JNA 的 UINT(由 long 支持的 32 位),而不是可以是 32 位或 64 位的 UINT_PTR(无论 Pointer.SIZE 计算结果如何)。尽管在这种特殊情况下,您可以只传递纯 Java int 值并获得您想要的结果,因为它们都没有大到足以关心符号位。

    (顺便说一句,你为什么使用十进制 20 而不是十六进制 0x0014?不会破坏事物,但是在进行按位数学时,读者更清楚地将代码保留为十六进制。)

    请注意,字符串的参数实际上是一个指针,虽然我链接到的文档没有说清楚,但挖掘它似乎 C 在这里期待一个指向宽字符串类型的指针,LPWSTR。你应该使用类似的东西:

    WTypes.LPWSTR png = new WTypes.LPWSTR("C:\\Overwatch\\690653.png");
    

    说了这么多……

    从其他地方的阅读中可以看出,Windows 7 在壁纸和图像压缩方面存在一些缺点,这是 Windows 7 的错误/功能/设计,可能不是您的代码的问题。其中:

    • this question(可能是您的原始来源?)的答案之一指出“Windows 7 不喜欢将 jpeg 图像设置为墙纸。您需要先将图像文件转换为位图,然后然后将bmp图像设置为背景。”

    • 微软网站上的
    • This thread 讨论压缩问题并建议“将图像保存为位图,即 .bmp,然后重命名为 .jpg,因此文件本身实际上是位图,但它被传递给操作系统一个 jpeg,所以它认为它不必压缩它”

    我建议从 .bmp 开始并将其保存为所有不同的扩展名,以排除任何特定于扩展名的行为。

    【讨论】:

    • 我在上面的代码上尝试了你的改进,然后我缩短了代码并让它循环通过多种文件类型,我可以将我的墙纸设置为,但它仍然只适用于 jpg。对于为什么它仍然没有设置为其他文件类型,您还有什么想法吗?当我第一次实现你的建议时,它是第一个代码,我所有的字符串都是 LPWSTR。
    • 我相信 Windows 对 PNG 和 JPG 使用不同的压缩设置(后者未压缩。)您是否尝试过使用不同的 PNG 文件来排除该特定文件的任何独特之处?它可以使用普通的 Windows 例程工作吗?你能改变它的大小吗?
    • 我没有尝试过其他 png 文件,但我可以通过右键单击并选择“设置为桌面背景”或其他方式手动将所有这些文件设置在策略中。我在石油钻井平台上工作,所以几天后我回家时会抓起一堆不同大小的 png 文件并尝试一下。
    猜你喜欢
    • 2014-05-28
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多