多显示器窗口分布规律探索(包括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

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

相关推荐
土星云SaturnCloud10 小时前
液冷“内卷”:在局部优化与系统重构之间,寻找第三条路
服务器·人工智能·ai·计算机外设
李斯维16 小时前
MBR 和 GPT 区别
windows·嵌入式硬件·bootstrap·计算机外设
TESmart碲视18 小时前
如何为超宽屏显示器选择 KVM 切换器?
计算机外设·kvm切换器·宽屏显示
ACP广源盛1392462567321 小时前
GSV1011@ACP#1011产品规格详解及产品应用分享
嵌入式硬件·计算机外设·音视频
liliangcsdn1 天前
如何在mac m1模拟鼠标与键盘的自动化操作
自动化·计算机外设
民乐团扒谱机2 天前
【微实验】基于Python实现的实时键盘鼠标触控板拾取检测(VS2019,附完整代码)
python·c#·计算机外设
码点3 天前
ShareMouse 在多台设备间共用一套鼠标键盘
计算机外设
私人珍藏库3 天前
[吾爱大神原创工具] FlowMouse - 心流鼠标手势 v1.0【Chrome浏览器插件】
前端·chrome·计算机外设
未知原色3 天前
阿里验证码Web和H5客户端V3架构接入鼠标拖拽滑块离开对话框释放鼠标时一直处于验证中问题
计算机外设
SamtecChina20233 天前
Electronica现场演示 | Samtec前面板解决方案
大数据·人工智能·算法·计算机外设