因要保持窗体大小鼠标可调的状态,在设计时边框设为2(可调)
但在运行时,它总有一个难看的边框,
也带来了无法精确拷贝窗体内容的问题(因边框也有宽度)
请问,如何在窗体运行时去掉边框?最好还能动态恢复 :)
是否用SetWindowLong?具体如何做?
但在运行时,它总有一个难看的边框,
也带来了无法精确拷贝窗体内容的问题(因边框也有宽度)
请问,如何在窗体运行时去掉边框?最好还能动态恢复 :)
是否用SetWindowLong?具体如何做?
Private Sub Form_Load()
Debug.Print Me.Height
Debug.Print Me.Width
Debug.Print Me.ScaleHeight
Debug.Print Me.ScaleWidth
End Sub
但现在不显示边框,仍希望由系统自动完成。自编代码(MouseMove)虽然也能做到,只是有没有更方便的通用办法,交给系统做?
现试过用SETWINDOWLONG把窗体的ReSize去掉,这样边框是没有了,但同时也丧失了系统自动鼠标的调整边框的功能,:( 俺认为这个功能很重要现在有没有办法,在运行时>>>不显示<<<(而不是去掉)边框,仍能让系统自动捕捉鼠标调整事件?之所以不用Scale高度,是因为想让窗体外框显示为指定大小(为了和此窗体背后的大背景精确配合),同时拷贝窗体内部,但正如楼上所说,只有在边框样式为NONE的时候,窗体的宽度高度才会=窗体的Scale高度宽度。
但又没了自动调整边框的功能 :(5555555 真是一对矛盾啊
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPrivate Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As LongPrivate Const GWL_STYLE = (-16)
Private Const WS_CAPTION = &HC00000 ' WS_BORDER 或 WS_DLGFRAME
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_SYSMENU = &H80000Private Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, _
ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As LongPrivate Enum ESetWindowPosStyles
SWP_SHOWWINDOW = &H40
SWP_HIDEWINDOW = &H80
SWP_FRAMECHANGED = &H20 ' The frame changed: send WM_NCCALCSIZE
SWP_NOACTIVATE = &H10
SWP_NOCOPYBITS = &H100
SWP_NOMOVE = &H2
SWP_NOOWNERZORDER = &H200 ' Don't do owner Z ordering
SWP_NOREDRAW = &H8
SWP_NOREPOSITION = SWP_NOOWNERZORDER
SWP_NOSIZE = &H1
SWP_NOZORDER = &H4
SWP_DRAWFRAME = SWP_FRAMECHANGED
HWND_NOTOPMOST = -2
End EnumPrivate Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End TypePrivate Function ShowTitleBar(ByVal bState As Boolean)
Dim lStyle As Long
Dim tR As RECT ' 获取窗口的位置:
GetWindowRect Me.hwnd, tR ' 调整标题栏是否可见:
lStyle = GetWindowLong(Me.hwnd, GWL_STYLE)
If (bState) Then
Me.Caption = Me.Tag
If Me.ControlBox Then
lStyle = lStyle Or WS_SYSMENU
End If
If Me.MaxButton Then
lStyle = lStyle Or WS_MAXIMIZEBOX
End If
If Me.MinButton Then
lStyle = lStyle Or WS_MINIMIZEBOX
End If
If Me.Caption <> "" Then
lStyle = lStyle Or WS_CAPTION
End If
Else
Me.Tag = Me.Caption
Me.Caption = ""
lStyle = lStyle And Not WS_SYSMENU
lStyle = lStyle And Not WS_MAXIMIZEBOX
lStyle = lStyle And Not WS_MINIMIZEBOX
lStyle = lStyle And Not WS_CAPTION
End If
SetWindowLong Me.hwnd, GWL_STYLE, lStyle' 重新设定窗口:
SetWindowPos Me.hwnd, 0, tR.Left, tR.Top, tR.Right - tR.Left, tR.Bottom - tR.Top, SWP_NOREPOSITION Or SWP_NOZORDER Or SWP_FRAMECHANGED
Me.Refresh' 你可能需要在Form_Resize中加一点代码,因为客户区的大小已经改变:
'Form_ResizeEnd Function
'为了试验一下代码,在窗体上放一个CheckBox,将它的Value属性设为1 (Checked)。然后写入以下代码:Private Sub Check1_Click()
If (Check1.Value = Checked) Then
ShowTitleBar True
Else
ShowTitleBar False
End If
End Sub
PrevX = X: PrevY = Y
End SubPrivate Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 1 Then
If Me.MousePointer = 0 Then
Me.Move Me.Left + X - PrevX, Me.Top + Y - PrevY
End If
X = IIf(X <= 1200, 1200, X): Y = IIf(Y <= 900, 900, Y)
Select Case Me.MousePointer
Case 7: Me.Height = Y
Case 8: Me.Width = X: Me.Height = Y
Case 9: Me.Width = X
End Select
End If
If Y > Me.ScaleHeight - 120 Then
Me.MousePointer = IIf(X > Me.ScaleWidth - 120, 8, 7)
Else
Me.MousePointer = IIf(X > Me.ScaleWidth - 120, 9, 0)
End If
End Sub
但进一步想想,却发现很多问题:
有没有注意到系统的自动捕捉边框调整事件,是不区分前台与后台窗体的?
就是说哪怕自己的窗体并不是前台的,也能在边框处显示不同鼠标指针。
虽然说可以用SetCapture捕捉全局鼠标位置,但还要考虑到本窗体是否已显示,是否在前台,是否处于当中(否则的话,在前台窗体的当中出现调整指针,会让用户莫名其妙)
还有一个问题,你这里是定死边框宽度的,而系统的窗体边框宽度是个“全局样式”是可调的,并且对于不同的分辨率有不同的换算比,那
还有一个问题,系统在左上角是一定位于边框才捕捉事件的,而右下角则不同。
另外,由于自编代码用到了ScaleWidth,意为着用户无法更改使用内部坐标了。
总总问题,都无法让自编代码实现完美的通用性。
看来,还是系统自己在这方面做的最好,那我们为啥不交给它呢?(这样可以多考虑程序其它功能嘛)
所以,我的想法是,能否欺骗系统,在不显示边框的情况下,让它仍以为有边框,当鼠标处于合理位置时,自动完成调整事件?
1. 用 GetSystemMetrics()取各部分大小
2. 用 API 的 GetWindowRect 和 GetClientRect,然后用 ClientToScreen 把后一个结果转化为屏幕坐标,比较一下两个矩形就很清楚了。