AutoHotkey Community

It is currently May 26th, 2012, 2:41 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Wallpaper changer
PostPosted: December 30th, 2008, 8:55 am 
Offline

Joined: July 30th, 2007, 11:32 pm
Posts: 581
I wrote a little script that automatically changes your wallpaper on startup (either at every startup, or every n day(s)). I made it in about 3 hours for my girlfriend :D and I just thought you'd like it. It's very simple. You give it a directory, and it'll cycle through the pictures in the directory (either sequencially or randomly). It would have been much smaller, but as I found out, desktop wallpapers can only be in bmp (at least on XP). Therefore, this script uses Tariq Porter's (tic) ConvertImage function which can be found here (thanks!). As a plus side however, the function allows a broad array of image formats, which might be a plus to some.

I tried to make it as clean as possible, but it's late, and I'm tired, so let me know if you find any bugs. Also, I'm running this as a compiled script. If you want to keep it in AHK, you need to change the startup registry value to point to AutoHotkey.exe and then pass the script's path as parameter one, and "startup" as parameter two. However, if you registered the AHK extension with AutoHotkey, you don't need to point to AutoHotkey.exe given that the shell can pass more than one parameter to AutoHotkey (the first parameter being taken by the script's path). To check that it can, go in Windows Explorer>Tools>Folder Options>File Types>AHK>Advanced>Run>Edit> make sure that it says "[path to autohotkey.exe]" "%1" "%2"

If you don't like it writing registry entries, you can easily modify it to use an ini file instead.

And now, I will go to sleep. Enjoy!

Code:
#NoTrayIcon
#NoEnv

;Make sure the program is registered as a startup item
;If not compiled, prepend "[path to autohotkey.exe]"%A_Space%" to "%A_ScriptFullPath%"%A_Space%"startup"
RegWrite REG_SZ, HKCU, Software\Microsoft\Windows\CurrentVersion\Run, WPChanger, "%A_ScriptFullPath%"%A_Space%"startup"

;Get settings
RegRead sDir, HKCU, SOFTWARE\AutoHotkey, Dir
RegRead bStartupChange, HKCU, SOFTWARE\AutoHotkey, StartupChange
RegRead iDayWait, HKCU, SOFTWARE\AutoHotkey, DayWait
RegRead bRand, HKCU, SOFTWARE\AutoHotkey, Random
RegRead bStretch, HKCU, SOFTWARE\AutoHotkey, Stretch
RegRead bRecurse, HKCU, SOFTWARE\AutoHotkey, Recurse

;Set defaults if there's no reg settings
bStartupChange := (bStartupChange = "") ? False : bStartupChange
iDayWait := (iDayWait = "") ? 1 : iDayWait
bRand := (bRand = "") ? True : bRand
bStretch := (bStretch = "") ? True : bStretch
bRecurse := (bRecurse = "") ? False : bRecurse
sTemp := A_AppData . "\Microsoft\Windows\wp.bmp"

;Get current wallpaper
RegRead sCurrentWP, HKCU, Control Panel\Desktop, OriginalWallpaper

;Check if launch was at startup
If (%1% := "startup") {
   
   ;Check if we have a directory
   If (sDir = "")
      ExitApp
      
   ;Check if day changing is enabled
   If bStartupChange
      bChange := True
   Else {
      
      ;Retrieve last time the wallpaper has been changed
      RegRead, iDays, HKCU, SOFTWARE\Autohotkey, LastWPChange

      ;Check if a change is needed
      If ErrorLevel
         bChange := True
      Else {   
         If ((A_YDay - iDays) >= iDayWait)
            bChange := True
         Else If (A_YDay < iDays)   ;We changed year
            bChange := True
         Else
            bChange := False
      }
   }
   
   ;Remove that section if you don't need that functionality
   ;Check if the user is forcing anything
   If (GetKeyState("LShift"))
      bChange := True
   Else If (GetKeyState("LCtrl"))
      bChange := False
   
   ;Change if needed
   if bChange {
      
      ;Check if we're going randomly
      If bRand {
         
         ;Count the number of wallpapers
         Loop %sDir%\*.*, 0, %bRecurse%
            If A_LoopFileExt in jpg,jpeg,bmp
               iCount += 1
         
         ;Get random number
         Random, iRand, 1, iCount
         
         ;Get chosen wallpaper
         Loop %sDir%\*.*, 0, %bRecurse%
         {
            If A_LoopFileExt in jpg,jpeg,bmp
               iPos += 1
            
            If (iPos = iRand) {
               sChosenWP := A_LoopFileLongPath
               Break
            }
         }
      
      ;We're going sequentially
      } Else {

         ;Check if the current wallpaper is in the given directory
         If InStr(sCurrentWP, sDir) {
            
            ;Find its position
            bFound := False
            Loop %sDir%\*.*, 0, %bRecurse%
            {
               If bFound {
                  If A_LoopFileExt in jpg,jpeg,bmp
                  {
                     sChosenWP := A_LoopFileLongPath
                     Break
                  }
               }
               
               If (A_LoopFileLongPath = sCurrentWP)
                  bFound := True
            }
                     
         ;It's not in the given directory. Choose the first pic
         } Else {
            
            Loop %sDir%\*.*, 0, %bRecurse%
            {
               If A_LoopFileExt in jpg,jpeg,bmp
               {
                  sChosenWP := A_LoopFileLongPath
                  Break
               }
            }
         }
      }
      
      ;Change wallpaper
      pToken := Gdip_Startup()
      ConvertImage(sChosenWP, sTemp)
      Gdip_Shutdown(pToken)
      RegWrite REG_SZ, HKCU, Control Panel\Desktop, OriginalWallpaper, %sChosenWP%
      RegWrite REG_SZ, HKCU, Control Panel\Desktop, Wallpaper, %sTemp%
      RegWrite REG_SZ, HKCU, Control Panel\Desktop, TileWallpaper, 0
      RegWrite REG_SZ, HKCU, Control Panel\Desktop, WallpaperStyle, % (bStretch ? 2 : 0)
      DllCall("SystemParametersInfoA", int, 20, int, 0, int, &sTemp, int, 3)   ;%
      
      ;Update value
      RegWrite, REG_DWORD, HKCU, SOFTWARE\AutoHotkey, LastWPChange, %A_YDay%
      
   }

;We have to show the GUI   
} Else {
   
   ;Build GUI
   Gui, -MinimizeBox -MaximizeBox -Resize
   Gui, Add, Text, x7 y13 w47 h15, Folder:
   Gui, Add, Edit, x56 y10 w240 h20 +ReadOnly -Multi vtxtDir, %sDir%
   Gui, Add, Button, x306 y10 w30 h20 gbtnBrowse, ...
   Gui, Add, CheckBox, x56 y30 w240 h20 vchkRecurse, Include subdirectories
   Gui, Add, Radio, x6 y60 w130 h20 voptDays goptDaysChecked, Change wallpaper every
   Gui, Add, Radio, x6 y90 w330 h20 voptStartup goptStartupChecked, Change wallpaper when the computer starts
   Gui, Add, Edit, x139 y61 w30 h18 +Number -Multi vtxtDays, %iDayWait%
   Gui, Add, Text, x177 y64 w33 h13, day(s)
   Gui, Add, CheckBox, x6 y110 w330 h20 vchkStretch, Stretch wallpaper (leave unchecked to center)
   Gui, Add, CheckBox, x6 y130 w330 h20 vchkRandom, Select in random order
   Gui, Add, Button, x236 y160 w100 h30 gbtnOK, &OK
   Gui, Add, Button, x116 y160 w100 h30 gbtnCancel, Cancel

   ;Set values
   GuiControl,, chkRecurse, %bRecurse%
   GuiControl,, % (bStartupChange ? "optStartup" : "optDays"), 1   ;%
   GuiControl,, chkStretch, %bStretch%
   GuiControl,, chkRandom, %bRand%
   GuiControl, % (bStartupChange ? "Disable" : "Enable"), txtDays   ;%
   
   ;Show GUI
   Gui, Show, x131 y91 h202 w349, Wallpaper Changer
   Return
   

}

;We're done
GuiClose:
btnCancel:
ExitApp

btnBrowse:
   FileSelectFolder, sDir, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}, 0, Select folder containing wallpapers
   If Not ErrorLevel
      GuiControl,, txtDir, %sDir%
Return

optDaysChecked:
   GuiControl, Enable, txtDays
Return

optStartupChecked:
   GuiControl, Disable, txtDays
Return

btnOK:
   
   ;Write data back to the registry
   Gui Submit
   RegWrite REG_SZ, HKCU, SOFTWARE\AutoHotkey, Dir, %txtDir%
   RegWrite REG_SZ, HKCU, SOFTWARE\AutoHotkey, StartupChange, %optStartup%
   RegWrite REG_SZ, HKCU, SOFTWARE\AutoHotkey, DayWait, %txtDays%
   RegWrite REG_SZ, HKCU, SOFTWARE\AutoHotkey, Random, %chkRandom%
   RegWrite REG_SZ, HKCU, SOFTWARE\AutoHotkey, Stretch, %chkStretch%
   RegWrite REG_SZ, HKCU, SOFTWARE\AutoHotkey, Recurse, %chkRecurse%
   
   ;Done
   ExitApp
   
Return

;###############################################################################################################
;
; ConvertImage() by Tariq Porter (tic) 04/05/08
; Version:      1.01
;
; sInput:         Location of the input file to be converted. May be of filetype jpg,bmp,png,tiff,gif
; sOutput:      Location to save the converted file. Extension determines the output filetype jpg,bmp,png,tiff,gif
; Width:        Width either in pixels or percentage (depending on Method) to save the converted file
; Height:         Height either in pixels or percentage (depending on Method) to save the converted file
;            Width or Height may also be -1 to keep the aspect ratio the same
; Method:         Can either be "Percent" or "Pixels" to determine the width and height of the converted file
;
; Return:      0=Success; -1=Could not create a bitmap from file; -2=Source file has no width or height
;            -3=Resize method must be either Precentage or Pixels; -4=Error resizing image;
;            -5=Could not get a list of filetype encoders on the system; -6=Could not find matching codec
;            -7=Wide file output could not be created; -8=File could not be written to disk

;###############################################################################################################

Gdip_Startup()
{
   If !DllCall("GetModuleHandle", "Str", "gdiplus")
   DllCall("LoadLibrary", "Str", "gdiplus")
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UInt*", pToken, "UInt", &si, "UInt", 0)
   VarSetCapacity(si, 0)
   Return, pToken
}

;###############################################################################################################

Gdip_Shutdown(pToken)
{
   DllCall("gdiplus\GdiplusShutdown", "UInt", pToken)
   If hModule := DllCall("GetModuleHandle", "Str", "gdiplus")
   DllCall("FreeLibrary", "UInt", hModule)
   Return, 0
}

;###############################################################################################################

ConvertImage(sInput, sOutput, Width="", Height="", Method="Percent")
{
   StringSplit, OutputArray, sOutput, .
    Extension := "." OutputArray%OutputArray0%
   
   VarSetCapacity(wInput, 1023)
   DllCall("kernel32\MultiByteToWideChar", "UInt", 0, "UInt", 0, "UInt", &sInput, "Int", -1, "UInt", &wInput, "Int", 512)
   DllCall("gdiplus\GdipCreateBitmapFromFile", "UInt", &wInput, "UInt*", pBitmap)
   If !pBitmap
   Return, -1
   
   If (Width && Height)
   {
      DllCall("gdiplus\GdipGetImageWidth", "UInt", pBitmap, "UInt*", sWidth)
      DllCall("gdiplus\GdipGetImageHeight", "UInt", pBitmap, "UInt*", sHeight)
      If !(sWidth && sHeight)
      {
         DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
         Return, -2
      }
         
      If (Method = "Percent")
      {
         Width := (Width = -1) ? Height : Width, Height := (Height = -1) ? Width : Height
         dWidth := Round(sWidth*(Width/100)), dHeight := Round(sHeight*(Height/100))
      }
      Else If (Method = "Pixels")
      {
         If (Width = -1)
         dWidth := Round((Height/sHeight)*sWidth), dHeight := Height
         Else If (Height = -1)
         dHeight := Round((Width/sWidth)*sHeight), dWidth := Width
         Else
         dWidth := Width, dHeight := Height
      }
      Else
      {
         DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
         Return, -3
      }
     
      DllCall("gdiplus\GdipCreateBitmapFromScan0", "Int", dWidth, "Int", dHeight, "Int", 0, "Int", 0x26200A, "UInt", 0, "UInt*", FpBitmap)
      DllCall("gdiplus\GdipGetImageGraphicsContext", "UInt", FpBitmap, "UInt*", G)
      DllCall("gdiplus\GdipSetInterpolationMode", "UInt", G, "Int", 7)
     
      E := DllCall("gdiplus\GdipDrawImageRectRectI", "UInt", G, "UInt", pBitmap
      , "Int", 0, "Int", 0, "Int", dWidth, "Int", dHeight
      , "Int", 0, "Int", 0, "Int", sWidth, "Int", sHeight
      , "Int", 2, "UInt", ImageAttr, "UInt", 0, "UInt", 0)
     
      DllCall("gdiplus\GdipDeleteGraphics", "UInt", G)
      DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
      pBitmap := FpBitmap
      
      If E
      {
         DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
         Return, -4
      }
   }
   
   DllCall("gdiplus\GdipGetImageEncodersSize", "UInt*", nCount, "UInt*", nSize)
    VarSetCapacity(ci, nSize)
    DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "UInt", &ci)
   If !(nCount && nSize)
   {
      DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
      Return, -5
   }
   
    Loop, %nCount%
    {
        nSize := DllCall("WideCharToMultiByte", "UInt", 0, "UInt", 0, "UInt", NumGet(ci, 76*(A_Index-1)+44), "Int", -1, "UInt", 0, "Int",  0, "UInt", 0, "UInt", 0)
        VarSetCapacity(sString, nSize)
        DllCall("WideCharToMultiByte", "UInt", 0, "UInt", 0, "UInt", NumGet(ci, 76*(A_Index-1)+44), "Int", -1, "Str", sString, "Int", nSize, "UInt", 0, "UInt", 0)
   
        If !InStr(sString, Extension)
        Continue
        pCodec := &ci+76*(A_Index-1)
        Break
    }
   If !pCodec
   {
      DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
      Return, -6
   }
   
   nSize := DllCall("MultiByteToWideChar", "UInt", 0, "UInt", 0, "UInt", &sOutput, "Int", -1, "UInt", 0, "Int", 0)
   VarSetCapacity(wOutput, nSize*2)
   DllCall("MultiByteToWideChar", "UInt", 0, "UInt", 0, "UInt", &sOutput, "Int", -1, "UInt", &wOutput, "Int", nSize)
   VarSetCapacity(wOutput, -1)
   If !VarSetCapacity(wOutput)
   {
      DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
      Return, -7
   }

   E := DllCall("gdiplus\GdipSaveImageToFile", "UInt", pBitmap, "UInt", &wOutput, "UInt", pCodec, "UInt", 0)
   DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
   If E
   DllCall("gdiplus\GdipDisposeImage", "UInt", pBitmap)
   Return, E ? -8 : 0
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 15th, 2009, 5:45 am 
Offline

Joined: April 18th, 2008, 7:57 am
Posts: 1390
Location: The Interwebs
This looks like quite a neat little utility. I've thought about something like this a couple of times, since I had two images I like to use as my backgrounds. But now I have two monitors so problem solved :D

Despite that, I was glad to find this script... Showed me how to change the wallpaper both for the current session and when the system starts up again! So thanks for posting.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 15th, 2009, 7:10 am 
Offline

Joined: July 30th, 2007, 11:32 pm
Posts: 581
Glad to know my script interested someone! :D


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 27th, 2009, 5:00 am 
Offline

Joined: November 14th, 2008, 1:45 am
Posts: 80
Location: USA
This is awesome! I would like to have the wallpaper change more often than once per day though. Is is possible to modify the script and enable it to change say, every 10 minutes, and if so exactly how would I do it? (Just to let you know, I'm really not very good at programming.)

Thanks in advance,
Sam.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 27th, 2009, 8:06 am 
Offline

Joined: July 30th, 2007, 11:32 pm
Posts: 581
Sam. wrote:
This is awesome! I would like to have the wallpaper change more often than once per day though. Is is possible to modify the script and enable it to change say, every 10 minutes, and if so exactly how would I do it? (Just to let you know, I'm really not very good at programming.)

Thanks in advance,
Sam.

Not without modifying it extensively. You'd be better off writing a new script. The way it works right now, the wallpaper changing only occurs when it is executed on startup. Constantly changing the wallpaper would require the script to stay on all the time.

What you could do instead is to enable the "Change wallpaper when the computer starts" option and then write a script which simply calls the wallpaper changer every 10 minutes with the "startup" parameter. It will then unconditionally change the wallpaper.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 28th, 2009, 12:40 am 
Offline

Joined: November 14th, 2008, 1:45 am
Posts: 80
Location: USA
TheGood wrote:
What you could do instead is to enable the "Change wallpaper when the computer starts" option and then write a script which simply calls the wallpaper changer every 10 minutes with the "startup" parameter. It will then unconditionally change the wallpaper.

Sorry, I'm afraid I don't understand how to do that. Could you possible be kind enough to show me? I sincerely apologize for my lack of experience and competence.

TIA,
Sam.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 28th, 2009, 1:14 am 
Offline

Joined: July 30th, 2007, 11:32 pm
Posts: 581
Sam. wrote:
Sorry, I'm afraid I don't understand how to do that. Could you possible be kind enough to show me? I sincerely apologize for my lack of experience and competence.

TIA,
Sam.

It's quite alright. :D
Make a script containing the following:
Code:
Loop {
     Sleep 600000 ;10 minutes (= 1000 ms/s X 60 s/min X 10 min)
     ;Comment out one of the following two lines (depending if you compiled the script or not)
     Run "[path of script]" "startup" ;If compiled
     Run "[path of AutoHotkey.exe]" "[path of script]" "startup" ;If script
}

And make sure that the "Change wallpaper when the computer starts" option (in my Wallpaper Changer) is selected.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 28th, 2009, 3:14 am 
Offline

Joined: November 14th, 2008, 1:45 am
Posts: 80
Location: USA
It's working great, thanks so much TheGood!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 6th, 2009, 12:04 am 
Offline

Joined: November 24th, 2005, 8:16 am
Posts: 851
Hi everybody,

Bumped into this post when I was searching for my own Wallpaper script, which I thought I posted here a while ago.

Sam. wrote:
I would like to have the wallpaper change more often than once per day though. Is is possible to modify the script and enable it to change say, every 10 minutes, and if so exactly how would I do it? (Just to let you know, I'm really not very good at programming.


So, without any intention of hijacking this post, if anyone is interested in seeing another approach which supports Sam's request to change at specific intervals, please visit the Wallpaper Randomizer thread.

_________________
Sector-Seven - Freeware tools built with AutoHotkey


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: daonlyfreez, Google [Bot], mhe and 10 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group