多显示器窗口分布规律探索(包括WorkerW的区域)

新知引入

在许多壁纸应用程序中,它们大多都支持多显示器的分布,而对于Windows的多显示器而言,它的窗口不可能是多边形

整个大窗口的布局其实是这2块显示屏的外边缘组成的大矩形,即

而在.net里面,有一个专门的类去管理显示器的虚拟区域

vbnet 复制代码
Dim s As Screen() = Screen.AllScreens

这一个方法可以给s附上所有显示器的数据,包括系统分配的设备名称、各个显示器的虚拟位置,其中,非常值得注意的一点是,虚拟桌面的坐标原点为主显示器(显示器1)的坐标原点(左上角)

因此,上图的红色大矩形数据为

转换为Rectangle为:-2048 -442 3968 1536

然后,事情就变得非常好办了,由于在显示器内,窗口的坐标是按照显示器的坐标原点来计算的,但是,WorkerW作为桌面背景层,它的区域就是上图的红色大矩形,并且中的并且,如果你想要设置一个窗口嵌入WorkerW,那么你就需要将不同显示器的坐标转换到WorkerW作为Parent的坐标。

说的有点绕了,简言之就是那个大矩形就是WorkerW的主窗体,然后你要嵌入窗口并且想要让壁纸准确出现在不同显示器上就要换算对应显示器区域在WorkerW上的哪一个位置

我们来使用代码来解释

vbnet 复制代码
 BackPalyer.Show()
 Threading.Thread.Sleep(100)
 Dim s As Screen() = Screen.AllScreens

 Dim Wrect As RECT
 GetWindowRect(&H60950, Wrect)
 Dim ToWorkerWRect As New List(Of Rectangle)

 For Each i In s
     Dim p As New Point(i.Bounds.X - Wrect.Left, i.Bounds.Y - Wrect.Top)
     ToWorkerWRect.Add(New Rectangle(p.X, p.Y, i.Bounds.Width, i.Bounds.Height))
 Next
 SetParent(BackPalyer.Handle, &H60950)
 BackPalyer.DesktopBounds = ToWorkerWRect(0)

解读一下:

延时100ms可以不写,s()是当前所有显示器的集合,Wrect是WorkerW的窗口rect,&H60950是WorkerW的句柄(注意,此处为了方便理解,实则每一次重启explorer都会变!先不要着急复制代码,下面会给出方法!)

在循环过程中,p的作用是换算的显示器在WorkerW上的位置,循环添加到列表

最后使用SetParent设置桌面背景,然后按照显示器bound设置壁纸窗口的DesktopBounds

如何获取壁纸层的句柄?

参考文章:桌面壁纸层嵌入窗口(wallpaper engine核心)原理讲解

或者改一下代码

vbnet 复制代码
Public Sub GetWorkerWHandle(ByVal videoPtr As IntPtr) As IntPtr
    Dim windows_version As Double = Environment.OSVersion.Version.Major
    progmanPtr = FindWindow("Progman", Nothing)
 
    If progmanPtr = IntPtr.Zero Then
        MessageBox.Show("当前系统可能不支持运行本程序或者卡死")
        Return
    Else
        SendMessageTimeout(progmanPtr, &H52C, IntPtr.Zero, IntPtr.Zero, 0, &H3E8, sendMessageBack)
        EnumWindows(Function(hwnd, param)
 
                        If Win32.FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", Nothing) <> IntPtr.Zero Then
                            workWPtr = Win32.FindWindowEx(IntPtr.Zero, hwnd, "WorkerW", Nothing)
 
                            If windows_version < 6.2 Then
                                Win32.ShowWindow(workWPtr, 0)
                            End If
                        End If
 
                        Return True
                    End Function, 0)
 
        If windows_version < 6.2 Then
            return progmanPtr
        Else
            return workWPtr
        End If
 
        
    End If
End Sub

经过测试,至此窗口可以被正确的嵌入桌面背景层了

相关推荐
ACP广源盛139246256731 天前
ASW3742@ACP# 产品规格详解
网络·人工智能·嵌入式硬件·计算机外设·电脑
nashane1 天前
HarmonyOS 6学习:悬浮键盘抖动修复与长截图“滚动裁缝”实战
学习·计算机外设·harmonyos·harmonyos 5
Joseph Cooper2 天前
Linux HID 子系统实战:从虚拟键盘到 input 事件上报
linux·c语言·计算机外设
私人珍藏库2 天前
[Windows] 鼠标速度锁定/调节工具 KeepMouseSpeedOK v3.55
计算机外设·工具·软件·win·多功能
Name_NaN_None2 天前
Android 手机投屏 iPad :公网+局域网免费方案
网络·计算机外设·电脑·远程工作
善恶怪客2 天前
Vga和Hdmi接口
计算机外设
Jwest20213 天前
佳维视工业显示器在健康体检一体机中的应用
计算机外设
weixin_402278453 天前
解决打开vscode编辑器ctrl+鼠标左键不能跳转定义问题 环境C++
vscode·编辑器·计算机外设
开开心心就好4 天前
专为视障人士设计的免费辅助工具
windows·计算机视觉·计算机外设·excel·散列表·推荐算法·csdn开发云
天下财经热4 天前
2026编程显示器推荐:明基RD270Q的2K144Hz有多实用?
计算机外设