为什么在 vb.net 中调整表单顶部或左侧时无边框表单会闪烁?
why borderless form is flickering when resizing form top or left in vb.net?
我看到这段代码可以调整大小和移动我的无边框表单,我将它复制到我的项目中。
这很好我一直在寻找类似的东西,我能看到的都是为 c# 制作的教程。我可以知道使用它是否有缺点吗?还有一件事,当我从顶部或左侧调整它的大小时,表单会闪烁,但如果我从右侧或底部调整它的大小时,它就很好,就像普通表单一样。我不知道可能是什么问题,因为老实说,我不明白下面写的是什么。它似乎使用了一些十六进制值。
我尝试设置表格double buffered = true
它不起作用。
Public Class Form2
Private Const WM_NCHITTEST As Integer = &H84
Private Const WM_MOUSEMOVE As Integer = &H200
Private Const WM_LBUTTONDOWN As Integer = &H201
Private Const WM_LBUTTONUP As Integer = &H202
Private Const MK_LBUTTON As Integer = &H1
Private Const HTLEFT As Integer = &HA
Private Const HTRIGHT As Integer = &HB
Private Const HTTOP As Integer = &HC
Private Const HTTOPLEFT As Integer = &HD
Private Const HTTOPRIGHT As Integer = &HE
Private Const HTBOTTOM As Integer = &HF
Private Const HTBOTTOMLEFT As Integer = &H10
Private Const HTBOTTOMRIGHT As Integer = &H11
Private OffSet As Point = Point.Empty
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.FormBorderStyle = FormBorderStyle.None
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_NCHITTEST Then
Dim loc As New Point(m.LParam.ToInt32 And &HFFFF, m.LParam.ToInt32 >> 16)
loc = PointToClient(loc)
Dim bTop As Boolean = (loc.Y < ClientRectangle.Y + 4)
Dim bLeft As Boolean = (loc.X < ClientRectangle.X + 4)
Dim bRight As Boolean = (loc.X > Width - 4)
Dim bBottom As Boolean = (loc.Y > Height - 4)
If bTop And bLeft Then
m.Result = CType(HTTOPLEFT, IntPtr)
Return
ElseIf bTop And bRight Then
m.Result = CType(HTTOPRIGHT, IntPtr)
Return
ElseIf bBottom And bLeft Then
m.Result = CType(HTBOTTOMLEFT, IntPtr)
Return
ElseIf bBottom And bRight Then
m.Result = CType(HTBOTTOMRIGHT, IntPtr)
Return
ElseIf bLeft Then
m.Result = CType(HTLEFT, IntPtr)
Return
ElseIf bTop Then
m.Result = CType(HTTOP, IntPtr)
Return
ElseIf bRight Then
m.Result = CType(HTRIGHT, IntPtr)
Return
ElseIf bBottom Then
m.Result = CType(HTBOTTOM, IntPtr)
Return
End If
ElseIf m.Msg = WM_LBUTTONDOWN Then
OffSet = New Point(MousePosition.X - Me.Location.X, MousePosition.Y - Me.Location.Y)
ElseIf m.Msg = WM_MOUSEMOVE AndAlso m.WParam.ToInt32 = MK_LBUTTON Then
Me.Location = New Point(MousePosition.X - OffSet.X, MousePosition.Y - OffSet.Y)
End If
MyBase.WndProc(m)
End Sub
End Class
通常,WndProc 是一个应用程序定义的函数,用于处理发送到 window 的消息。在您的示例中,Form2 被认为是无框架 window。在原始无框架 window 中,您不能移动或调整 window 的大小,除非您覆盖其 WndProc 保护函数。在您的示例中,将 m.Msg(指示消息的 ID 号)与不同的操作系统消息(WM_NCHITTEST、WM_LBUTTONDOWN 等)进行比较,以确定应该采取什么操作进行(调整大小,移动,...)。您可以找到系统消息 ID here 的完整列表。
关于闪烁问题。老实说,这个问题不会发生在我的系统上。这可能取决于您的操作系统和 windows 版本。
我看到这段代码可以调整大小和移动我的无边框表单,我将它复制到我的项目中。
这很好我一直在寻找类似的东西,我能看到的都是为 c# 制作的教程。我可以知道使用它是否有缺点吗?还有一件事,当我从顶部或左侧调整它的大小时,表单会闪烁,但如果我从右侧或底部调整它的大小时,它就很好,就像普通表单一样。我不知道可能是什么问题,因为老实说,我不明白下面写的是什么。它似乎使用了一些十六进制值。
我尝试设置表格double buffered = true
它不起作用。
Public Class Form2
Private Const WM_NCHITTEST As Integer = &H84
Private Const WM_MOUSEMOVE As Integer = &H200
Private Const WM_LBUTTONDOWN As Integer = &H201
Private Const WM_LBUTTONUP As Integer = &H202
Private Const MK_LBUTTON As Integer = &H1
Private Const HTLEFT As Integer = &HA
Private Const HTRIGHT As Integer = &HB
Private Const HTTOP As Integer = &HC
Private Const HTTOPLEFT As Integer = &HD
Private Const HTTOPRIGHT As Integer = &HE
Private Const HTBOTTOM As Integer = &HF
Private Const HTBOTTOMLEFT As Integer = &H10
Private Const HTBOTTOMRIGHT As Integer = &H11
Private OffSet As Point = Point.Empty
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.FormBorderStyle = FormBorderStyle.None
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_NCHITTEST Then
Dim loc As New Point(m.LParam.ToInt32 And &HFFFF, m.LParam.ToInt32 >> 16)
loc = PointToClient(loc)
Dim bTop As Boolean = (loc.Y < ClientRectangle.Y + 4)
Dim bLeft As Boolean = (loc.X < ClientRectangle.X + 4)
Dim bRight As Boolean = (loc.X > Width - 4)
Dim bBottom As Boolean = (loc.Y > Height - 4)
If bTop And bLeft Then
m.Result = CType(HTTOPLEFT, IntPtr)
Return
ElseIf bTop And bRight Then
m.Result = CType(HTTOPRIGHT, IntPtr)
Return
ElseIf bBottom And bLeft Then
m.Result = CType(HTBOTTOMLEFT, IntPtr)
Return
ElseIf bBottom And bRight Then
m.Result = CType(HTBOTTOMRIGHT, IntPtr)
Return
ElseIf bLeft Then
m.Result = CType(HTLEFT, IntPtr)
Return
ElseIf bTop Then
m.Result = CType(HTTOP, IntPtr)
Return
ElseIf bRight Then
m.Result = CType(HTRIGHT, IntPtr)
Return
ElseIf bBottom Then
m.Result = CType(HTBOTTOM, IntPtr)
Return
End If
ElseIf m.Msg = WM_LBUTTONDOWN Then
OffSet = New Point(MousePosition.X - Me.Location.X, MousePosition.Y - Me.Location.Y)
ElseIf m.Msg = WM_MOUSEMOVE AndAlso m.WParam.ToInt32 = MK_LBUTTON Then
Me.Location = New Point(MousePosition.X - OffSet.X, MousePosition.Y - OffSet.Y)
End If
MyBase.WndProc(m)
End Sub
End Class
通常,WndProc 是一个应用程序定义的函数,用于处理发送到 window 的消息。在您的示例中,Form2 被认为是无框架 window。在原始无框架 window 中,您不能移动或调整 window 的大小,除非您覆盖其 WndProc 保护函数。在您的示例中,将 m.Msg(指示消息的 ID 号)与不同的操作系统消息(WM_NCHITTEST、WM_LBUTTONDOWN 等)进行比较,以确定应该采取什么操作进行(调整大小,移动,...)。您可以找到系统消息 ID here 的完整列表。 关于闪烁问题。老实说,这个问题不会发生在我的系统上。这可能取决于您的操作系统和 windows 版本。