请问VB6如何让窗体大小自动适合控件的大小?

时间:2020-12-17 03:46:44
请注意,我的问题不是指让控件去适合窗体的大小,而是反过来,先设定控件的大小,然后让窗体大小随着控件大小自动变化。

我说一下我遇到的具体问题,我的程序类似于一个画板,窗体上主要就是一个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


引用 3 楼 lingshao0909 的回复:
那你的菜单栏高度和宽度是不是固定的呢?


菜单栏的高度是固定的,可以用GetSystemMetrics(SM_CYMENUSIZE)获得,但是菜单栏的宽度是与窗体一致的,而当窗体宽度不能完整显示菜单时,菜单项会自动折成两行或更多行,而GetSystemMetrics(SM_CYMENUSIZE)获得的始终是一行菜单的高度,我又没法知道什么时候才会折行,如果能让菜单不折行也会好办一些。

#7


引用 5 楼 lingshao0909 的回复:
如果菜单栏是固定宽度,那就可以根据窗体宽度计算出菜单栏的高度了


如何让菜单栏宽度固定而不随着窗体宽度变化呢?

#8


你可以调试下,窗体多大的时候菜单栏才会折行,然后就以这个为标准来计算菜单栏的高度。不知道可行不

#9


引用 8 楼 lingshao0909 的回复:
你可以调试下,窗体多大的时候菜单栏才会折行,然后就以这个为标准来计算菜单栏的高度。不知道可行不


这个应该不可行,因为用户可以在Windows显示属性里自定义系统菜单字体、大小的不同,这将使菜单以什么宽度显示,什么时候折行变得不确定。

#10


不过这个方法也够笨的了

#11


自己试验一下,看看窗体宽度缩小到多少时菜单栏会折为两行,多少时会折为三行,然后分别处理就行了。

#12


引用 11 楼 happy_sea 的回复:
自己试验一下,看看窗体宽度缩小到多少时菜单栏会折为两行,多少时会折为三行,然后分别处理就行了。


这个在不同环境下是不确定的,不能用固定的值来判断。


贴几个个图来说明:
请问VB6如何让窗体大小自动适合控件的大小?

请问VB6如何让窗体大小自动适合控件的大小?

请问VB6如何让窗体大小自动适合控件的大小?

#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


引用 13 楼 Tiger_Zhao 的回复:
在 Form_Resize 中进行调整,这样最多由于菜单栏的折行变化多调整一次 

VB codeOption 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 & ","…

跟楼主的意思是一样的,不过效率高多了。

#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


引用 3 楼 lingshao0909 的回复:
那你的菜单栏高度和宽度是不是固定的呢?


菜单栏的高度是固定的,可以用GetSystemMetrics(SM_CYMENUSIZE)获得,但是菜单栏的宽度是与窗体一致的,而当窗体宽度不能完整显示菜单时,菜单项会自动折成两行或更多行,而GetSystemMetrics(SM_CYMENUSIZE)获得的始终是一行菜单的高度,我又没法知道什么时候才会折行,如果能让菜单不折行也会好办一些。

#7


引用 5 楼 lingshao0909 的回复:
如果菜单栏是固定宽度,那就可以根据窗体宽度计算出菜单栏的高度了


如何让菜单栏宽度固定而不随着窗体宽度变化呢?

#8


你可以调试下,窗体多大的时候菜单栏才会折行,然后就以这个为标准来计算菜单栏的高度。不知道可行不

#9


引用 8 楼 lingshao0909 的回复:
你可以调试下,窗体多大的时候菜单栏才会折行,然后就以这个为标准来计算菜单栏的高度。不知道可行不


这个应该不可行,因为用户可以在Windows显示属性里自定义系统菜单字体、大小的不同,这将使菜单以什么宽度显示,什么时候折行变得不确定。

#10


不过这个方法也够笨的了

#11


自己试验一下,看看窗体宽度缩小到多少时菜单栏会折为两行,多少时会折为三行,然后分别处理就行了。

#12


引用 11 楼 happy_sea 的回复:
自己试验一下,看看窗体宽度缩小到多少时菜单栏会折为两行,多少时会折为三行,然后分别处理就行了。


这个在不同环境下是不确定的,不能用固定的值来判断。


贴几个个图来说明:
请问VB6如何让窗体大小自动适合控件的大小?

请问VB6如何让窗体大小自动适合控件的大小?

请问VB6如何让窗体大小自动适合控件的大小?

#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


引用 13 楼 Tiger_Zhao 的回复:
在 Form_Resize 中进行调整,这样最多由于菜单栏的折行变化多调整一次 

VB codeOption 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 & ","…

跟楼主的意思是一样的,不过效率高多了。

#15


谢谢Tiger_Zhao,这个方法很好,也感谢参与讨论的各位,结贴送分~