Jump to content
Sign in to follow this  

Basic Slideshow Wallpaper (Multiple Monitor)

Recommended Posts

While looking for a way to change my desktop background of only my secondary monitor, I found a few simple solutions that are built into Windows. But when you look up how to do such with a slideshow... You only find programs that cost money. So, I set out to make it myself.
This is a pretty basic program. It simply displays an image in the center of the screen (scaled to fit screen) and uses a black background.
The program does allow mouse passthrough, though you can't drag and drop over it, so it wouldn't really work well if you have icons on your second monitor.
#include <File.au3>
#include <GUIConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <EditConstants.au3>
#include <Misc.au3>
#include <Array.au3>
#include <GDIPlus.au3>

;User Changeable Variables
$pictureFolder = "D:\Wallpapers"
$changeTime = 5 ;Seconds
Global $smWidth = 1600
Global $smHeight = 900
Global $monitorPosition = "Right"
;Global $monitorPosition = "Left"
Global $imageList = _FileListToArray($pictureFolder)
Global $imageCount = $imageList[0]
Global $imageHeight, $imageWidth, $pHeight, $pWidth, $pic, $gdiPic


$GUIStyle = BitOR($WS_POPUP, $WS_VISIBLE, $HWND_BOTTOM) ;Popup, Visible, Window on Bottom
$GUIStyleEx = BitOR($WS_EX_TRANSPARENT, $WS_EX_TOOLWINDOW) ;Allow Passthrough, Hide from Alt+Tab
$Parent = WinGetHandle('Program Manager', '') ;Sets parent to the program manager, allowing you to right click the desktop
If $monitorPosition = "Right" Then
    $GUI = GUICreate("Secondary Wallpaper", $smWidth, $smHeight, @DesktopWidth, 0, $GUIStyle, $GUIStyleEx, $Parent)
    $GUI = GUICreate("Secondary Wallpaper", $smWidth, $smHeight, (-1 * @DesktopWidth), 0, $GUIStyle, $GUIStyleEx, $Parent)
GUISetBkColor(0, $GUI)
_WinAPI_SetWindowPos($GUI, $HWND_BOTTOM, 0, 0, 0, 0, BitOR($SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_SHOWWINDOW)) ;Forces window to bottom of screen
WinSetTrans($GUI, '', 255) ;Sets Window Visible Transparency: Required for mouse passthrough
GUISetState(@SW_SHOW) ;Show GUI

While 1
    Sleep($changeTime * 1000)

Func ChangeImage()
    $picName = Random(1, $imageCount, 1)
    ;Get Dimensions of image
    $imageHeight = $pHeight
    $imageWidth = $pWidth

    ;Turn them all into integers. (Fixes glitch that caused some images to skip resizing)
    $imageHeight = Int($imageHeight)
    $imageWidth = Int($imageWidth)
    $smHeight = Int($smHeight)
    $smWidth = Int($smWidth)

        ;Adjust the image size
    ;If the image is bigger than the screen, adjust it
    If $imageWidth > $smWidth = 1 Or $imageHeight > $smHeight = 1 Then
        ;Calculate Aspect Ratio of image
        $aspectRatioX = $smWidth / $imageWidth
        $aspectRatioY = $smHeight / $imageHeight
        If $aspectRatioX < $aspectRatioY Then
            $scaleFactor = $aspectRatioX
            $scaleFactor = $aspectRatioY
        $imageHeight = $imageHeight * $scaleFactor
        $imageWidth = $imageWidth * $scaleFactor
        ;Image is smaller/same size as monitor

    ;Calculate Center of monitor
    ;(Monitor size - image size) / 2
    $smCenterX = ($smWidth - $imageWidth) / 2
    $smCenterY = ($smHeight - $imageHeight) / 2

    ;Resize the image
    $hHBmp = $pictureFolder & "\" & $imageList[$picName]
    $gdiPic = _GDIPlus_BitmapCreateFromFile($hHBmp) ;convert GDI bitmap to GDI+ bitmap
    $pic = _GDIPlus_ImageResize($gdiPic, $imageWidth, $imageHeight) ;resize image

    GUISetBkColor(0, $GUI)
    Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($GUI) ;create a graphics object from a window handle
    $gdiPic = _GDIPlus_BitmapCreateFromFile($pictureFolder & "\" & $imageList[$picName])

    _GDIPlus_GraphicsDrawImage($hGraphics, $pic, $smCenterX, $smCenterY) ;display scaled image
    _GDIPlus_GraphicsDispose($hGraphics) ;Garbage Cleanup
EndFunc   ;==>ChangeImage

Func GetDimensions($picName)
    Local $prop, $dArray, $fileSize, $imageDimensionsGDI

    $path = $pictureFolder & "\" & $picName
    $fileSize = FileGetSize($path)
    ;Save information to registry for faster access. Compare size of picture to verify changes to picture
    If $fileSize <> RegRead("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Size") Then
        ;File sizes do not match
        RegWrite("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Size", "REG_SZ", $fileSize)
        $imageDimensionsGDI = _GDIPlus_ImageLoadFromFile($path)
        $pWidth = _GDIPlus_ImageGetWidth($imageDimensionsGDI)
        $pHeight = _GDIPlus_ImageGetHeight($imageDimensionsGDI)
        RegWrite("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Width", "REG_SZ", $pWidth)
        RegWrite("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Height", "REG_SZ", $pHeight)
        ;File sizes match
        $pWidth = RegRead("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Width")
        $pHeight = RegRead("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Height")
        If $pWidth = "-1" Or $pHeight = "-1" Then
            RegWrite("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Size", "REG_SZ", $fileSize)
            $imageDimensionsGDI = _GDIPlus_ImageLoadFromFile($path)
            $pWidth = _GDIPlus_ImageGetWidth($imageDimensionsGDI)
            $pHeight = _GDIPlus_ImageGetHeight($imageDimensionsGDI)
            RegWrite("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Width", "REG_SZ", $pWidth)
            RegWrite("HKEY_CURRENT_USER\Software\Secondary Wallpaper\Pictures", $picName & " Height", "REG_SZ", $pHeight)

EndFunc   ;==>GetDimensions

Func CloseProgram()
    ;Garbage Cleanup
EndFunc   ;==>CloseProgram




Secondary Wallpaper.au3

Edited by Sori
Now includes scaled images and centering.
  • Like 1

If you need help with your stuff, feel free to get me on my Skype.

I often get bored and enjoy helping with projects.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • Sven-Seyfert
      By Sven-Seyfert
      Hi Community,

      I'm looking for a way to do a Video Overlay GUI or something like that. The idea is to create a GUI which plays a video loop (with transparency/alpha channel) in front of an other GUI. Before you asking why - because I don't believe that GDIPlus can do it out of the box. My skillset for that kind of graphical things isn't good enough to do that, but here are some specialist like @UEZ maybe who can help.

      Example alpha channel video (visualized as animated *.gif):

      I tried to do the light rays effect directly with GDIPlus, but honestly that's a bit too difficult for me. I would be very glad and grateful if there are some suggestions, ideas or recommendations.

      Code for the Video play:
      Example video "End.mpeg":
      The next challenge is that the overlay GUI should be not clickable. If I hover over the overlay area, I want to have the possibility to control the GUI or what ever, in the background. But if there is any chance to make it with GDIPlus as a Video Overlay for light rays, I would prefer that approach instead of my crazy work-around idea.

      Thanks for any suggestion - I'm grateful!
    • c.haslam
      By c.haslam
      I had thought that _GDIPlus_ImageClone($hImage) removes all property items, but I now know that it copies property items.
      What is the easiest way of copying an image that has property items to another image that does not have property items?
    • c.haslam
      By c.haslam
      I think that _GDIPlus_ImageGetPropertyItem should return a Property Item that can readily be set as a property of another image. Why would one want to do this? A script might (as one of mine does) edit an image of a .jpg file then write the result to a .jpg file. In editing it, in my case, the number of horizontal and vertical pixels change, and the date/time edited should be set as a property. All other property items remain the same. Other GDI+ users may change other properties.
      So an approach is to copy all the property items from image1 to image2, then update a few properties.
      M$ provides a Property Item class (id, length, pointer to an array of values) but _GDIPlus_ImageGetPropertyItem returns something different.
      I think that, wherever reasonable, UDFs that are wrappers for M$ methods should work like M$'s methods. _GDIPlus_ImageGetPropertyItem does not do this:
      While M$ returns 2 values for a value that is a ratio of 2 numbers,  _GDIPlus_ImageGetPropertyItem returns numerator/denominator as a single value (often a Double). _GDIPlus_ImageSetPropertyItem (when included in GDIPlus.au3) will be unable to set ratio property items properly because it cannot know what the numerator and denominator are. So copying such property items will not work properly. M$ has a Void* buffer where the buffer is an array of values but _GDIPlus_ImageGetPropertyItem() returns the values in the same 1-d array as id, length and type. M$'s approach produces a 1-d array with the same number of elements for all property items while _GDIPlus_ImageGetPropertyItem produces a 1-d array with various numbers of elements. To me, this is not good programming practice. For a photo from a Sony camera, the worst case has 1-d array with 67 elements. When combined into a 2-d array with the property items of all properties, there are 66 rows and 67 columns, with many elements not used. So I suggest that _GDIPlus_ImageGetPropertyItem look like this:
      ; #FUNCTION# ==================================================================================================================== ; Name ..........: cGDIPlus_ImageGetPropertyItem ; Description ...: Gets a specified property item (piece of meta data) from an Image object ; Syntax ........: cGDIPlus_ImageGetPropertyItem($hImage, $iPropID) ; Parameters ....: $hImage - Pointer to an image object ; $iPropID - Identifier of the property item to be retrieved ; Return values .: Success: Array containing the values of the property item ; [0] - identifier ; [1] - size, in bytes, of the value array ; [2] - type of value(s) in the value array ; [3] - value array ; Failure: Sets the @error flag to non-zero, @extended may contain GPSTATUS error code ($GPID_ERR*). ; Author ........: Eukalyptus ; Modified ......: c.haslam ; Remarks .......: types: unsigned byte = 1, ASCII string = 2, unsigned short = 3, unsigned long = 4, ; unsinged rational = 5, undefined = 7, signed long = 9, signed rational = 10 ; Related .......: _GDIPlus_ImageGetPropertyIdList ; Link ..........: https://msdn.microsoft.com/en-us/library/windows/desktop/ms535390(v=vs.85).aspx, ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms534493(v=vs.85).aspx, ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms534414(v=vs.85).aspx ; Example .......: Yes ; =============================================================================================================================== Func cGDIPlus_ImageGetPropertyItem($hImage, $iPropID) Local $iSize = __GDIPlus_ImageGetPropertyItemSize($hImage, $iPropID) If @error Then Return SetError(@error, @extended, -1) Local $tBuffer = DllStructCreate("byte[" & $iSize & "];") Local $pBuffer = DllStructGetPtr($tBuffer) Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetPropertyItem", "handle", $hImage, "uint", _ $iPropID, "uint", $iSize, "struct*", $tBuffer) If @error Then Return SetError(@error, @extended, -1) If $aResult[0] Then Return SetError(10, $aResult[0], False) Local $tPropertyItem = DllStructCreate("int id; int length; short type; ptr pvalue;", $pBuffer) Local $iBytes = DllStructGetData($tPropertyItem, "length") Local $pValue = DllStructGetData($tPropertyItem, "pvalue") Local $aRet[4] Local $type = DllStructGetData($tPropertyItem,'type') Local $tValues, $iValues Switch $type Case 2 ;ASCII String $iValues = 1 $tValues = DllStructCreate("char[" & $iBytes & "];", $pValue) Case 3 ;Array of UShort $iValues = Int($iBytes / 2) $tValues = DllStructCreate("ushort[" & $iValues & "];", $pValue) Case 4, 5 ;Array of UInt / Fraction $iValues = Int($iBytes / 4) $tValues = DllStructCreate("uint[" & $iValues & "];", $pValue) Case 9, 10 ;Array of Int / Fraction $iValues = Int($iBytes / 4) $tValues = DllStructCreate("int[" & $iValues & "];", $pValue) Case Else ;Array of Bytes $iValues = 1 $tValues = DllStructCreate("byte[" & $iBytes & "];", $pValue) EndSwitch $aRet[0] = DllStructGetData($tPropertyItem,'id') $aRet[1] = $iBytes $aRet[2] = $type Local $aVals[$iValues] If $type=2 Or $type=7 Then ; ASCII string or undefined $aVals[0] = DllStructGetData($tValues,1) Else For $i = 0 To $iValues-1 $aVals[$i] = DllStructGetData($tValues,1,$i+1) Next EndIf $aRet[3] = $aVals Return $aRet EndFunc And here is an example:
      #include <GDIPlus.au3> #include <Array.au3> Example() Func Example() _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile(RegRead((@AutoItX64 = True ? "HKLM\SOFTWARE\Wow6432Node\AutoIt v3\AutoIt" : "HKLM\SOFTWARE\AutoIt v3\AutoIt"), "InstallDir") & "\Examples\GUI\Torus.png") If @error Then _GDIPlus_Shutdown() MsgBox(16, "", "An error has occured - unable to load image!", 30) Return False EndIf Local $ar = _GDIPlus_ImageGetPropertyIdList($hImage) Local $vPropNbrs[UBound($ar,1)-1] ; Extract ID numbers For $i = 1 To UBound($ar,1)-1 $vPropNbrs[$i-1] = $ar[$i][0] Next ; Get all property items Local $aPropItems[UBound($vPropNbrs)][4],$vPropItem For $i = 0 To UBound($vPropNbrs)-1 $vPropItem = cGDIPlus_ImageGetPropertyItem($hImage,$vPropNbrs[$i]) For $j = 0 To 3 $aPropItems[$i][$j] = $vPropItem[$j] Next Next ; Collapse values arrays so _ArrayDisplay can display them Local $ar = $aPropItems For $i = 0 To UBound($aPropItems,1)-1 $ar[$i][0] = '0x'&Hex($ar[$i][0],4) $ar[$i][3] = '' For $j = 0 To UBound($aPropItems[$i][3])-1 $ar[$i][3] &= ($aPropItems[$i][3])[$j]&'|' Next $ar[$i][3] = StringTrimRight($ar[$i][3],1) Next _ArrayDisplay($ar) _GDIPlus_Shutdown() EndFunc Unfortunately this example (based on one now in the Help) does not exercise most of the item types, but I do not know of a file with EXIF metadata that is on most PCs. I have tested this code by updating and adding property items to torus.jpg and to a photo taken by a Sony camera. The code for implementing and calling _GDIPlus_ImageSetPropertyItem will be fairly simple [see below].
      Your thoughts?
    • c.haslam
      By c.haslam
      I have a strange symptom of a problem somewhere in my code, or in a UDF: when I add code to get all properties of a GDI+ image to a 6000-line script,  the variable type of a parameter is reported as a pointer when the caller clearly has this argument as a string. If I comment out my code that gets the properties, the function properly sees the parameter as a string.
      [Edit: The reporting as a pointer and getting image properties are miles apart, both in where they are in the script code and in where they are run.]
      At this point, I am looking for clues as to why this is happening, so the hunt is on!
      I have noticed one odd thing, in _GDIPlus_ImageGetPropertyIdList() I see a line that begins Local $sPropertyTagInfo = . This "line" is split into 2 lines. SCiTE shows that the first line is 2454 characters and the second 2400. Adding these numbers I get 4854 characters.
      But the Help for AutoIt3 Limits/defaults says that MAXLINESIZE, Maximum size for a line of script, is 4096 characters.
      The line would exceed the limit if AutoIt considers the subject line to be 1 line and not 2 lines.
      My question: is this line legal? Is buffer overun possible?
    • c.haslam
      By c.haslam
      I find _GDIPlus_ImageClone in the Help, but neither in SciTe auto-complete nor in GDIPlus.au3
      Shoud this be reported in Trac?
      By searching the forum (and changing the name of the first arguement ot DLLCall, the code appears to be:
      Func _GDIPlus_ImageClone($hImage) Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipCloneImage", "handle", $hImage, "int*", 0) If @error Then Return SetError(@error, @extended, 0) Return $aResult[2] EndFunc ;==>_GDIPlus_ImageClone