1 # Python program to change the background under windows (tested on windows XP)
3 from __future__ import division
9 # Kinda like 'from ctypes.windll import user32'
10 user32 = ctypes.windll.user32
12 ###sys.stdout = file(os.path.join(os.environ['USERPROFILE'], 'Desktop', 'Output.txt'), 'w')
13 ###sys.stderr = sys.stdout
16 LocalFree = ctypes.windll.kernel32.LocalFree
18 # Defining the GetCommandLineW function
19 GetCommandLineW = ctypes.windll.kernel32.GetCommandLineW
20 GetCommandLineW.restype = ctypes.c_wchar_p
22 # Defining the CommandLineToArgvW function
23 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
24 CommandLineToArgvW.argtypes = (ctypes.c_wchar_p, ctypes.c_void_p)
25 CommandLineToArgvW.restype = ctypes.c_void_p
27 args = GetCommandLineW()
31 numArgs = ctypes.c_int()
32 argv_address = CommandLineToArgvW(args, ctypes.byref(numArgs))
34 # if argv_address != NULL
37 argvArrayType = ctypes.c_wchar_p * numArgs.value
38 argvArray = argvArrayType.from_address(argv_address)
39 argv = tuple(unicode(arg) for arg in argvArray)
41 # Free the memory in argv_address
42 LocalFree(argv_address)
44 # Free this memory since it isn't needed
48 # Drop the first argument (since this the call to the python interperator
51 sys.unicode_argv = getUnicodeArgs()
54 # Taken from the Platform SDK
55 SPI_SETDESKWALLPAPER = 20
56 SPIF_SENDWININICHANGE = 2
58 # Resize an image (returns a new image)
59 def resize(image, (outputWidth, outputHeight),
60 fillBoundingBox = False,
62 method = Image.BICUBIC):
64 imgWidth, imgHeight = image.size
66 if (imgHeight == outputHeight) and (imgWidth == outputWidth):
69 aspectRatio = imgHeight / imgWidth
70 outputAspectRatio = outputHeight / outputWidth
73 if aspectRatio < outputAspectRatio:
74 newHeight = outputHeight
75 newWidth = int(outputHeight / aspectRatio)
76 # (left, upper, right, lower)
77 offset = (newWidth - outputWidth) // 2
78 outputBox = (offset, 0, offset + outputWidth, outputHeight)
80 newWidth = outputWidth
81 newHeight = int(outputWidth * aspectRatio)
82 # (left, upper, right, lower)
83 offset = (newHeight - outputHeight) // 2
84 outputBox = (0, offset, newWidth, offset + outputHeight)
86 print >>sys.stderr, "Aspects: ", aspectRatio, outputAspectRatio
87 print >>sys.stderr, "Output: ", outputWidth, outputHeight
88 print >>sys.stderr, "Img: ", imgWidth, imgHeight
89 print >>sys.stderr, "new:", newWidth, newHeight
90 print >>sys.stderr, "CropBox: ", outputBox
92 image = image.resize( (newWidth, newHeight), method)
94 ((newHeight == outputHeight) and (newWidth == outputWidth)):
95 image = image.crop( outputBox )
97 raise NotImplementedError
101 # Converts the input image to a bitmap (with optional resizing)
102 def convertImage(pathToImage, boundingBox = None):
103 TEMP_FILE = 'pywallpaper.bmp'
104 newPath = os.path.join(os.getcwd(), TEMP_FILE)
106 bmpImg = Image.open(pathToImage)
108 if boundingBox is not None:
109 bmpImg = resize(bmpImg, boundingBox, fillBoundingBox = True)
111 # Check the colour space it is in (we only want RGB)
112 if bmpImg.mode == 'RGBA':
113 bmpImg = bmpImg.convert('RGB')
115 # Save it as a bitmap
116 bmpImg.save(newPath, "BMP")
120 # Actually sets the wallpaper
121 def updateWall(pathToBMP):
122 # Parameters for SystemParametersInfoA are:
123 # (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
124 user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER,
127 SPIF_SENDWININICHANGE)
130 # Code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/460509
131 # Gets the size of all monitors attached to this computer)
133 class RECT(ctypes.Structure):
135 ('left', ctypes.c_long),
136 ('top', ctypes.c_long),
137 ('right', ctypes.c_long),
138 ('bottom', ctypes.c_long)
141 return map(int, (self.left, self.top, self.right, self.bottom))
143 class MONITORINFO(ctypes.Structure):
145 ('cbSize', ctypes.c_ulong),
148 ('dwFlags', ctypes.c_ulong)
153 CBFUNC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(RECT), ctypes.c_double)
154 def cb(hMonitor, hdcMonitor, lprcMonitor, dwData):
155 r = lprcMonitor.contents
156 #print "cb: %s %s %s %s %s %s %s %s" % (hMonitor, type(hMonitor), hdcMonitor, type(hdcMonitor), lprcMonitor, type(lprcMonitor), dwData, type(dwData))
158 data.append(r.dump())
162 temp = user32.EnumDisplayMonitors(0, 0, cbfunc, 0)
168 monitors = get_monitors()
169 for hMonitor, extents in monitors:
172 mi.cbSize = ctypes.sizeof(MONITORINFO)
173 mi.rcMonitor = RECT()
175 res = user32.GetMonitorInfoA(hMonitor, ctypes.byref(mi))
176 data.append(mi.rcMonitor.dump())
177 data.append(mi.rcWork.dump())
182 # End code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/460509
186 def getPrimarySize():
187 monitors = monitor_areas()
188 monitorID, size, workingSize = monitors[0]
189 sizeLeft, sizeTop, sizeRight, sizeBottom = size
190 return (sizeRight - sizeLeft, sizeBottom - sizeTop)
192 pathToBMP = convertImage(sys.unicode_argv[1], getPrimarySize())
193 updateWall(pathToBMP)
195 if __name__ == '__main__':