使用Java更改Windows 7壁纸

时间:2016-08-04 20:28:42

标签: java windows windows-7 jna

我在这里找到了这段代码

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));
 }

1 个答案:

答案 0 :(得分:0)

JNA代码存在一些问题,试图回答有关应该使用哪些设置的问题。

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

注意三个参数是- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector { NSEvent *currentEvent = [[NSApplication sharedApplication]currentEvent]; if ((currentEvent.modifierFlags & NSCommandKeyMask) && (currentEvent.keyCode == kVK_Return)) { //command + enter to confirm //do what you want return YES; } return NO; } (32位整数)。您应该使用JNA的UINT(32位由UINT支持),而不是long,它可以是32位或64位(无论Pointer.SIZE评估为什么)。虽然在这种特殊情况下你可以只传递普通的Java UINT_PTR值并获得你想要的结果,因为它们都不足以关注符号位。

(除此之外,为什么你使用十进制20而不是十六进制0x0014?不会破坏事情,但在进行逐位数学运算时,读者可以更清楚地将代码保留为十六进制。)

请注意,字符串的参数实际上是一个指针,虽然我链接到的文档并没有明确说明,但是在它周围挖掘似乎是C期望指向一个宽字符串类型的指针,{{ 1}}。你应该使用类似的东西:

int

所有这一切......

从其他地方看到,Windows 7在壁纸和图像压缩方面存在一些缺点,这些缺点是Windows 7的错误/功能/设计,可能不会对您的代码造成任何问题。其中包括:

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

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

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