我正在使用:
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER,
0, "picturefile", 0)
更换壁纸。
但是我想知道是否有任何简单的方法可以在每个屏幕上放置不同的壁纸。
虽然此功能在 Windows 中不是标准功能,但有像 ultramon 这样的外部应用程序可以执行此操作。有人知道这是如何运作的吗?
我认为如果我将两个图像连接在一起然后将其作为壁纸,它可能会起作用,但我仍然需要一种方法将一个图像跨越两个屏幕。
另外,我如何获取有关显示器设置、每个屏幕的分辨率及其位置的一些信息?就像您在 Windows 中的 GUI 显示设置中看到的那样,但以数字表示。
将图像组合成大图像后,您必须将壁纸模式设置为平铺以使图像跨越桌面(否则它将在每个显示器上重新启动)。
有几种方法可以做到这一点:
a) 使用IActiveDesktop(这不需要需要使用活动桌面,不用担心)。这是最好的,因为在 Win7 上新壁纸会淡入。
您创建一个 IActiveDesktop / CLSID_ActiveDesktop COM 对象,然后调用 SetWallpaper、SetWallpaperOptions,最后调用 ApplyChanges。 (因为我不是 Python 开发人员,所以我不确定如何访问 COM 对象,抱歉。)
或:
b) 通过注册表。这不是那么好,但效果很好。
在
HKEY_CURRENT_USER\Control Panel\Desktop
下设置:
TileWallpaper
到 (REG_SZ) 1
(即字符串“1”而不是数字 1)WallpaperStyle
到 (REG_SZ) 0
(即字符串“0”而不是数字 0).
顺便说一句,我正在查看的代码使用 IActiveDesktop 并在失败时退回到注册表,将
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE
作为最后一个参数传递给 SystemParameterInfo;您当前正在传递 0,这可能是错误的。EnumDisplayMonitors 是 Win32 API,用于获取显示器的详细信息,包括它们的屏幕尺寸和相对于彼此的位置。
该 API 通过您必须提供的回调函数返回其结果。 (它为每个监视器调用一次。)我不是 Python 开发人员,所以我不确定如何从 Python 调用这样的函数。
快速 Google 一下“Python EnumWindows”(EnumWindows 是一种常用的 API,它以相同的方式返回结果),发现人们正在谈论这一点,并使用 Lambda 函数进行回调,所以看起来这是可能的,但我会留给更了解 Python 的人吧。
注意:请记住处理彼此不相邻或不对齐的显示器。您编译的图像可能需要有空白区域,以使所有显示器上的内容正确排列。如果您移动其中一台显示器并对整个桌面进行 PrtScn 屏幕截图,您就会在结果中明白我的意思。
https://stackoverflow.com/a/74203777/3620725
import random
from ctypes import HRESULT, POINTER, pointer
from ctypes.wintypes import LPCWSTR, UINT, LPWSTR
import comtypes
from comtypes import IUnknown, GUID, COMMETHOD
# noinspection PyPep8Naming
class IDesktopWallpaper(IUnknown):
# Ref: https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-idesktopwallpaper
# Search `IDesktopWallpaper` in `\HKEY_CLASSES_ROOT\Interface` to obtain the magic string
_iid_ = GUID("{B92B56A9-8B55-4E14-9A89-0199BBB6F93B}")
@classmethod
def CoCreateInstance(cls):
# Search `Desktop Wallpaper` in `\HKEY_CLASSES_ROOT\CLSID` to obtain the magic string
class_id = GUID("{C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD}")
return comtypes.CoCreateInstance(class_id, interface=cls)
_methods_ = [
COMMETHOD(
[],
HRESULT,
"SetWallpaper",
(["in"], LPCWSTR, "monitorID"),
(["in"], LPCWSTR, "wallpaper"),
),
COMMETHOD(
[],
HRESULT,
"GetWallpaper",
(["in"], LPCWSTR, "monitorID"),
(["out"], POINTER(LPWSTR), "wallpaper"),
),
COMMETHOD(
[],
HRESULT,
"GetMonitorDevicePathAt",
(["in"], UINT, "monitorIndex"),
(["out"], POINTER(LPWSTR), "monitorID"),
),
COMMETHOD(
[],
HRESULT,
"GetMonitorDevicePathCount",
(["out"], POINTER(UINT), "count"),
),
]
def SetWallpaper(self, monitorId: str, wallpaper: str):
self.__com_SetWallpaper(LPCWSTR(monitorId), LPCWSTR(wallpaper))
def GetWallpaper(self, monitorId: str) -> str:
wallpaper = LPWSTR()
self.__com_GetWallpaper(LPCWSTR(monitorId), pointer(wallpaper))
return wallpaper.value
def GetMonitorDevicePathAt(self, monitorIndex: int) -> str:
monitorId = LPWSTR()
self.__com_GetMonitorDevicePathAt(UINT(monitorIndex), pointer(monitorId))
return monitorId.value
def GetMonitorDevicePathCount(self) -> int:
count = UINT()
self.__com_GetMonitorDevicePathCount(pointer(count))
return count.value
if __name__ == "__main__":
wallpapers = [
r"C:\path\to\wallpaper1.jpg",
r"C:\path\to\wallpaper2.jpg",
r"C:\path\to\wallpaper3.jpg",
r"C:\path\to\wallpaper4.jpg",
]
desktop_wallpaper = IDesktopWallpaper.CoCreateInstance()
monitor_count = desktop_wallpaper.GetMonitorDevicePathCount()
for i in range(monitor_count):
monitor_id = desktop_wallpaper.GetMonitorDevicePathAt(i)
wallpaper = wallpapers[i]
desktop_wallpaper.SetWallpaper(monitor_id, str(wallpaper))