我说一下我遇到的具体问题,我的程序类似于一个画板,窗体上主要就是一个picturebox控件,充满了整个窗体。
而这个picturebox的width和height是由用户明确指定的,比如800×600像素等等。
当picturebox的大小确定以后,我需要知道该把窗体的width和height设置成多少才能把picturebox完整显示出来。
窗体的宽度还好办,我可以算出窗体边框的宽度,把picturebox的宽度加上两个边框的宽度就能得出窗体的宽度。
但是计算窗体的高度就出问题了,这个窗体上有菜单栏,而当窗体的宽度小到不能完整显示菜单时,菜单栏会自动折行,从而使窗体高度和picturebox高度之间的差距成了一个不确定的值。
我希望知道如何能解决这个问题,让窗体的大小自动适应picturebox的大小。
~~
或者换个问法:如何精确设定窗体工作区的大小?
用form.width和form.height指定的是窗体外轮廓的大小,包括标题栏、菜单栏、边框等,而这些对象的尺寸在不同环境下是不确定的,如果能直接指定窗体工作区的大小,让picturebox的大小等于工作区大小就行了。
我试过用GetSystemMetrics去获取菜单栏等非工作区对象的大小,但是无法解决菜单折行的问题,还是无法确定窗体的高度。
15 个解决方案
#1
Me.ScaleWidth , Me.ScaleHeight属性
#2
使用Me.ScaleWidth和Me.ScaleHeight可以获取工作区的大小,但是如果直接给这两个属性赋值,会使ScaleMode变成0(User),只是改变了窗体大小的计算单位而已,并不会真正改变窗体大小,解决不了我的问题呀。
#3
那你的菜单栏高度和宽度是不是固定的呢?
#4
我想到了下面这种方法,虽然能够实现我的目的,但这种方法太笨了,我想绝对不应该是唯一的办法,而且从运行效果上看也是让人难以接受的。
Private Sub Form_Load()
Me.ScaleMode = vbPixels
Picture1.Top = 0
Picture1.Left = 0
Call SetFormSize(800, 600)
End Sub
Private Sub Form_Resize()
Picture1.width = Me.ScaleWidth
Picture1.height = Me.ScaleHeight
End Sub
Private Sub SetFormSize(lWidth As Long, lHeight As Long)
Me.width = 0
Do
Me.width = Me.width + 1
DoEvents
Loop Until Picture1.width = lWidth
Me.height = 0
Do
Me.height = Me.height + 1
DoEvents
Loop Until Picture1.height = lHeight
End Sub
#5
如果菜单栏是固定宽度,那就可以根据窗体宽度计算出菜单栏的高度了
#6
菜单栏的高度是固定的,可以用GetSystemMetrics(SM_CYMENUSIZE)获得,但是菜单栏的宽度是与窗体一致的,而当窗体宽度不能完整显示菜单时,菜单项会自动折成两行或更多行,而GetSystemMetrics(SM_CYMENUSIZE)获得的始终是一行菜单的高度,我又没法知道什么时候才会折行,如果能让菜单不折行也会好办一些。
#7
如何让菜单栏宽度固定而不随着窗体宽度变化呢?
#8
你可以调试下,窗体多大的时候菜单栏才会折行,然后就以这个为标准来计算菜单栏的高度。不知道可行不
#9
这个应该不可行,因为用户可以在Windows显示属性里自定义系统菜单字体、大小的不同,这将使菜单以什么宽度显示,什么时候折行变得不确定。
#10
不过这个方法也够笨的了
#11
自己试验一下,看看窗体宽度缩小到多少时菜单栏会折为两行,多少时会折为三行,然后分别处理就行了。
#12
这个在不同环境下是不确定的,不能用固定的值来判断。
贴几个个图来说明:
#13
在 Form_Resize 中进行调整,这样最多由于菜单栏的折行变化多调整一次
Option Explicit
Private Sub Form_Load()
Me.ScaleMode = vbTwips '与屏幕坐标系一致方便调整
Picture1.Move 0, 0, ScaleX(800, vbPixels, vbTwips), ScaleY(600, vbPixels, vbTwips)
End Sub
Private Sub Form_Resize()
Dim deltaX As Long, deltaY As Long
With Me
Debug.Print "(" & .Width & "," & .Height & ")", _
"(" & .ScaleWidth & "," & .ScaleHeight & ")"
deltaX = (.ScaleWidth - Picture1.Width)
deltaY = (.ScaleHeight - Picture1.Height)
If (deltaX <> 0) Or (deltaY <> 0) Then
Debug.Print , "Call Me.Move"
.Move .Left, .Top, .Width - deltaX, .Height - deltaY
End If
End With
End Sub
#14
跟楼主的意思是一样的,不过效率高多了。
#15
谢谢Tiger_Zhao,这个方法很好,也感谢参与讨论的各位,结贴送分~
#1
Me.ScaleWidth , Me.ScaleHeight属性
#2
使用Me.ScaleWidth和Me.ScaleHeight可以获取工作区的大小,但是如果直接给这两个属性赋值,会使ScaleMode变成0(User),只是改变了窗体大小的计算单位而已,并不会真正改变窗体大小,解决不了我的问题呀。
#3
那你的菜单栏高度和宽度是不是固定的呢?
#4
我想到了下面这种方法,虽然能够实现我的目的,但这种方法太笨了,我想绝对不应该是唯一的办法,而且从运行效果上看也是让人难以接受的。
Private Sub Form_Load()
Me.ScaleMode = vbPixels
Picture1.Top = 0
Picture1.Left = 0
Call SetFormSize(800, 600)
End Sub
Private Sub Form_Resize()
Picture1.width = Me.ScaleWidth
Picture1.height = Me.ScaleHeight
End Sub
Private Sub SetFormSize(lWidth As Long, lHeight As Long)
Me.width = 0
Do
Me.width = Me.width + 1
DoEvents
Loop Until Picture1.width = lWidth
Me.height = 0
Do
Me.height = Me.height + 1
DoEvents
Loop Until Picture1.height = lHeight
End Sub
#5
如果菜单栏是固定宽度,那就可以根据窗体宽度计算出菜单栏的高度了
#6
菜单栏的高度是固定的,可以用GetSystemMetrics(SM_CYMENUSIZE)获得,但是菜单栏的宽度是与窗体一致的,而当窗体宽度不能完整显示菜单时,菜单项会自动折成两行或更多行,而GetSystemMetrics(SM_CYMENUSIZE)获得的始终是一行菜单的高度,我又没法知道什么时候才会折行,如果能让菜单不折行也会好办一些。
#7
如何让菜单栏宽度固定而不随着窗体宽度变化呢?
#8
你可以调试下,窗体多大的时候菜单栏才会折行,然后就以这个为标准来计算菜单栏的高度。不知道可行不
#9
这个应该不可行,因为用户可以在Windows显示属性里自定义系统菜单字体、大小的不同,这将使菜单以什么宽度显示,什么时候折行变得不确定。
#10
不过这个方法也够笨的了
#11
自己试验一下,看看窗体宽度缩小到多少时菜单栏会折为两行,多少时会折为三行,然后分别处理就行了。
#12
这个在不同环境下是不确定的,不能用固定的值来判断。
贴几个个图来说明:
#13
在 Form_Resize 中进行调整,这样最多由于菜单栏的折行变化多调整一次
Option Explicit
Private Sub Form_Load()
Me.ScaleMode = vbTwips '与屏幕坐标系一致方便调整
Picture1.Move 0, 0, ScaleX(800, vbPixels, vbTwips), ScaleY(600, vbPixels, vbTwips)
End Sub
Private Sub Form_Resize()
Dim deltaX As Long, deltaY As Long
With Me
Debug.Print "(" & .Width & "," & .Height & ")", _
"(" & .ScaleWidth & "," & .ScaleHeight & ")"
deltaX = (.ScaleWidth - Picture1.Width)
deltaY = (.ScaleHeight - Picture1.Height)
If (deltaX <> 0) Or (deltaY <> 0) Then
Debug.Print , "Call Me.Move"
.Move .Left, .Top, .Width - deltaX, .Height - deltaY
End If
End With
End Sub
#14
跟楼主的意思是一样的,不过效率高多了。
#15
谢谢Tiger_Zhao,这个方法很好,也感谢参与讨论的各位,结贴送分~