]> code.delx.au - bg-scripts/commitdiff
Import initial windows version
authorGreg Darke <greg@tsukasa.net.au>
Sun, 24 Feb 2008 12:23:27 +0000 (23:23 +1100)
committerGreg Darke <greg@tsukasa.net.au>
Sun, 24 Feb 2008 12:23:27 +0000 (23:23 +1100)
bin/ChangeWallpaper.pyw [new file with mode: 0644]

diff --git a/bin/ChangeWallpaper.pyw b/bin/ChangeWallpaper.pyw
new file mode 100644 (file)
index 0000000..7d1fbc4
--- /dev/null
@@ -0,0 +1,196 @@
+# Python program to change the background under windows (tested on windows XP)\r
+\r
+from __future__ import division\r
+\r
+import sys, os\r
+from PIL import Image\r
+\r
+import ctypes\r
+# Kinda like 'from ctypes.windll import user32'\r
+user32 = ctypes.windll.user32\r
+\r
+###sys.stdout = file(os.path.join(os.environ['USERPROFILE'], 'Desktop', 'Output.txt'), 'w')\r
+###sys.stderr = sys.stdout\r
+\r
+def getUnicodeArgs():\r
+       LocalFree = ctypes.windll.kernel32.LocalFree\r
+\r
+       # Defining the GetCommandLineW function\r
+       GetCommandLineW = ctypes.windll.kernel32.GetCommandLineW\r
+       GetCommandLineW.restype = ctypes.c_wchar_p\r
+\r
+       # Defining the CommandLineToArgvW function\r
+       CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW\r
+       CommandLineToArgvW.argtypes = (ctypes.c_wchar_p, ctypes.c_void_p)\r
+       CommandLineToArgvW.restype = ctypes.c_void_p\r
+\r
+       args = GetCommandLineW()\r
+       # if args != NULL\r
+       if args:\r
+               try:\r
+                       numArgs = ctypes.c_int()\r
+                       argv_address = CommandLineToArgvW(args, ctypes.byref(numArgs))\r
+\r
+                       # if argv_address != NULL\r
+                       if argv_address:\r
+                               try:\r
+                                       argvArrayType = ctypes.c_wchar_p * numArgs.value\r
+                                       argvArray = argvArrayType.from_address(argv_address)\r
+                                       argv = tuple(unicode(arg) for arg in argvArray)\r
+                               finally:\r
+                                       # Free the memory in argv_address\r
+                                       LocalFree(argv_address)\r
+               finally:\r
+                       # Free this memory since it isn't needed\r
+                       LocalFree(args)\r
+\r
+\r
+       # Drop the first argument (since this the call to the python interperator\r
+       return argv[1:]\r
+\r
+sys.unicode_argv = getUnicodeArgs()\r
+\r
+\r
+# Taken from the Platform SDK\r
+SPI_SETDESKWALLPAPER = 20\r
+SPIF_SENDWININICHANGE = 2\r
+\r
+# Resize an image (returns a new image)\r
+def resize(image, (outputWidth, outputHeight), \r
+               fillBoundingBox = False, \r
+               cropImage = True,\r
+               method = Image.BICUBIC):\r
+\r
+       imgWidth, imgHeight = image.size\r
+\r
+       if (imgHeight == outputHeight) and (imgWidth == outputWidth):\r
+               return image\r
+\r
+       aspectRatio = imgHeight / imgWidth\r
+       outputAspectRatio = outputHeight / outputWidth\r
+\r
+       if fillBoundingBox:\r
+               if aspectRatio < outputAspectRatio:\r
+                       newHeight = outputHeight\r
+                       newWidth = int(outputHeight / aspectRatio)\r
+                       # (left, upper, right, lower)\r
+                       offset = (newWidth - outputWidth) // 2\r
+                       outputBox = (offset, 0, offset + outputWidth, outputHeight)\r
+               else:\r
+                       newWidth = outputWidth\r
+                       newHeight = int(outputWidth * aspectRatio)\r
+                       # (left, upper, right, lower)\r
+                       offset = (newHeight - outputHeight) // 2\r
+                       outputBox = (0, offset, newWidth, offset + outputHeight)\r
+\r
+               print >>sys.stderr, "Aspects: ", aspectRatio, outputAspectRatio\r
+               print >>sys.stderr, "Output: ", outputWidth, outputHeight\r
+               print >>sys.stderr, "Img: ", imgWidth, imgHeight\r
+               print >>sys.stderr, "new:", newWidth, newHeight\r
+               print >>sys.stderr, "CropBox: ", outputBox\r
+\r
+               image = image.resize( (newWidth, newHeight), method)\r
+               if cropImage and not\\r
+                               ((newHeight == outputHeight) and (newWidth == outputWidth)):\r
+                       image = image.crop( outputBox )\r
+       else:\r
+               raise NotImplementedError\r
+\r
+       return image\r
+\r
+# Converts the input image to a bitmap (with optional resizing)\r
+def convertImage(pathToImage, boundingBox = None):\r
+       TEMP_FILE = 'pywallpaper.bmp'\r
+       newPath = os.path.join(os.getcwd(), TEMP_FILE)\r
+\r
+       bmpImg = Image.open(pathToImage)\r
+\r
+       if boundingBox is not None:\r
+               bmpImg = resize(bmpImg, boundingBox, fillBoundingBox = True)\r
+\r
+       # Check the colour space it is in (we only want RGB)\r
+       if bmpImg.mode == 'RGBA':\r
+               bmpImg = bmpImg.convert('RGB')\r
+\r
+       # Save it as a bitmap\r
+       bmpImg.save(newPath, "BMP")\r
+\r
+       return newPath\r
+\r
+# Actually sets the wallpaper\r
+def updateWall(pathToBMP):\r
+       # Parameters for SystemParametersInfoA are:\r
+       # (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)\r
+       user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER,\r
+                       0,\r
+                       pathToBMP,\r
+                       SPIF_SENDWININICHANGE)\r
+\r
+###\r
+# Code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/460509\r
+# Gets the size of all monitors attached to this computer)\r
+###\r
+class RECT(ctypes.Structure):\r
+  _fields_ = [\r
+    ('left', ctypes.c_long),\r
+    ('top', ctypes.c_long),\r
+    ('right', ctypes.c_long),\r
+    ('bottom', ctypes.c_long)\r
+    ]\r
+  def dump(self):\r
+    return map(int, (self.left, self.top, self.right, self.bottom))\r
+\r
+class MONITORINFO(ctypes.Structure):\r
+  _fields_ = [\r
+    ('cbSize', ctypes.c_ulong),\r
+    ('rcMonitor', RECT),\r
+    ('rcWork', RECT),\r
+    ('dwFlags', ctypes.c_ulong)\r
+    ]\r
+\r
+def get_monitors():\r
+  retval = []\r
+  CBFUNC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(RECT), ctypes.c_double)\r
+  def cb(hMonitor, hdcMonitor, lprcMonitor, dwData):\r
+    r = lprcMonitor.contents\r
+    #print "cb: %s %s %s %s %s %s %s %s" % (hMonitor, type(hMonitor), hdcMonitor, type(hdcMonitor), lprcMonitor, type(lprcMonitor), dwData, type(dwData))\r
+    data = [hMonitor]\r
+    data.append(r.dump())\r
+    retval.append(data)\r
+    return 1\r
+  cbfunc = CBFUNC(cb)\r
+  temp = user32.EnumDisplayMonitors(0, 0, cbfunc, 0)\r
+  #print temp\r
+  return retval\r
+\r
+def monitor_areas():\r
+  retval = []\r
+  monitors = get_monitors()\r
+  for hMonitor, extents in monitors:\r
+    data = [hMonitor]\r
+    mi = MONITORINFO()\r
+    mi.cbSize = ctypes.sizeof(MONITORINFO)\r
+    mi.rcMonitor = RECT()\r
+    mi.rcWork = RECT()\r
+    res = user32.GetMonitorInfoA(hMonitor, ctypes.byref(mi))\r
+    data.append(mi.rcMonitor.dump())\r
+    data.append(mi.rcWork.dump())\r
+    retval.append(data)\r
+  return retval\r
+\r
+###\r
+# End code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/460509\r
+###\r
+\r
+def main():\r
+       def getPrimarySize():\r
+               monitors = monitor_areas()\r
+               monitorID, size, workingSize = monitors[0]\r
+               sizeLeft, sizeTop, sizeRight, sizeBottom = size\r
+               return (sizeRight - sizeLeft, sizeBottom - sizeTop)\r
+       \r
+       pathToBMP = convertImage(sys.unicode_argv[1], getPrimarySize())\r
+       updateWall(pathToBMP)\r
+\r
+if __name__ == '__main__':\r
+       main()\r