情境
我正在开发一个用户控件,用于镜像目标窗口。它内部使用Win32 DWM API来注册/注销缩略图,并在父窗体调整大小或移动时更新缩略图的位置和位置。
这是我的应用程序的结构:
在“正常”的条件下(也就是在操作系统中使用默认的Windows主题时),我的应用程序/用户控件能够按预期工作。我录制了下面的视频来演示用户控件的用法和行为,以便您更好地了解所有这些内容并查看控件是否按预期工作:
问题
问题出现在我设法为操作系统使用不同的主题时,具体来说是任何添加非隐藏窗口边框的主题。例如使用第三方软件如WindowBlinds(使用名为“Flat Dark”的主题),也可以通过修改注册表中的一些窗口度量值来复制Windows 10中的可见边框添加,但是我不记得如何通过注册表实现这一点,抱歉。
好吧,当在Windows 10中设法使用带有非隐藏边框的窗口(通过上述第三方软件或其他可能的方法)时,我用户控件类内部的算法用于检索其相对于父窗体的坐标就会出问题,然后我得到意外的坐标,因此DWM缩略图未在正确的位置绘制。
我录制了下面的视频,您可以看到其中的差异并了解问题:
在视频中,首先我展示了程序在“正常”条件下运行的情况,然后我关闭了程序,更改了操作系统主题,再次运行程序,从这一点开始,您可以看到DWM缩略图没有在正确的位置绘制...
所有我的推测都表明我遇到的问题与我的Form的客户机/非客户机区域有关,当应用非隐藏的Windows 10边框时。
为什么我这样认为呢?因为如果我更改主题以使用带有可见边框的窗口,然后像这样删除我的窗体的边框:
this.FormBorderStyle = FormBorderStyle.None;
当我的窗体没有边框时,我的应用程序能够正常工作,因此在这种特定情况下,问题必须与窗体的客户端/非客户端区域有关。但是,在这些情况下计算控件的相对位置时,我不知道自己做错了什么,当窗体有边框时。
源代码
最后,我在这里分享完整的解决方案,其中包括我正在开发的用户控件以及演示应用程序(与上面的视频相同)。
请注意,源代码是用VB.NET编写的,但是这个事实与我在这个问题中标记的语言无关,因为我接受C#或VB.NET的任何解决方案,请不要因为问题中标记的语言与共享解决方案使用的语言不同而责备我。
不需要下载和检查源代码,所有源代码中唯一相关的部分是relativePos
的坐标赋值,如下所示:
Public Class ElektroDwmThumbnail : Inherits UserControl
Protected Function GetThumbnailRectangle() As Rectangle
Dim relativePos As Point = Me.ParentForm.PointToClient(Me.PointToScreen(Point.Empty))
' ...
Dim dstRectangle As New Rectangle(relativePos, thumbnailSize)
Return dstRectangle
End Function
End Class
这在C#中将是:
public class ElektroDwmThumbnail: UserControl {
protected Rectangle GetThumbnailRectangle() {
Point relativePos = this.ParentForm.PointToClient(this.PointToScreen(Point.Empty));
// ...
Rectangle dstRectangle = new Rectangle(relativePos, thumbnailSize);
return dstRectangle;
}
}
...在我所解释的情况下,它会给relativePos
分配意外的坐标,这就是我需要解决并询问的问题,我需要高效(通用地)确定我的用户控件相对于父窗体的真实相对坐标,而不考虑父窗体窗口的边框大小...