好的,在这里给你更大的图片;我有一个列表视图,显示数据库中的记录,我想改变列表框和窗体窗口的大小相对于listview包含的行数。简单。
这是我的代码,接缝使表单消失 - 注意程序仍然以图标运行,但根本没有可见的形式。
frmMain
是包含列表视图的窗体 - 它的高度为228。
lvRec
是列表视图 - 它的高度为85。
此代码存储在文件中,并在表单
需要时调用Public Sub Resizer()
'Count records/rows with data
Dim i As Integer
i = frmMain.lvRec.Items.Count
'Set window Size
If i = 3 Then
If frmMain.Height < 247 Then
Do Until frmMain.Height = 247
frmMain.Height = +1
System.Threading.Thread.Sleep(100)
Loop
Do Until frmMain.lvRec.Height = 104
frmMain.Height = +1
System.Threading.Thread.Sleep(100)
Loop
ElseIf frmMain.Height > 247 Then
Do Until frmMain.Height = 247
frmMain.Height = -1
System.Threading.Thread.Sleep(100)
Loop
Do Until frmMain.lvRec.Height = 104
frmMain.lvRec.Height = -1
System.Threading.Thread.Sleep(100)
Loop
End If
它们目前在listview中有3行,但是这段代码使表格消失,即使我已经说明要扩展247
答案 0 :(得分:0)
考虑您当前的代码:
Do Until frmMain.Height = 247
frmMain.Height = +1
System.Threading.Thread.Sleep(100)
Loop
如果您始终将frmMain.Height
设置为+1
,{{1}}是否会变得大于或等于247?
答案 1 :(得分:0)
我怀疑你的代码陷入无限循环。
通过你的例子......
假设i = 3
...
If i = 3 Then
If frmMain.Height < 247 Then
' Most likely > 247 as that's a very small height. Let's skip on for now...
ElseIf frmMain.Height > 247 Then
'Else would suffice - not need for ElseIf as it ignores the case frmMain.Height = 247
Do Until frmMain.Height = 247
'Shrink form height (very slowly - we're talking pixels here)
frmMain.Height = -1 'Not correct as discussed in the other answer and below
System.Threading.Thread.Sleep(100)
Loop
Do Until frmMain.lvRec.Height = 104
' Who says frmMain.lvRec.Height is > 104? It may well be less in which case this loop will never end. See note below.
frmMain.lvRec.Height = -1
System.Threading.Thread.Sleep(100)
Loop
End If
一般情况下,只有当你某些时,才会尝试在逻辑条件下使用精确值。
想象一下frmMain.lvRec.Height
从103
开始的场景......它会永远减少1
,这意味着主UI线程将被锁定,表单永远不会重绘。
更好(但仍然不完美)的例子是......
While frmMain.lvRec.Height <> 104
If frmMain.lvRec.Height > 104
frmMain.lvRec.Height -= 1 'Same as frmMain.lvRec.Height = frmMain.lvRec.Height -1
Else
frmMain.lvRec.Height += 1 'vice-versa
End If
System.Threading.Thread.Sleep(100)
End While
理想情况下,您希望大小的转换需要一段固定的时间。假设它应该持续2秒(2,000毫秒),步长为100毫秒= 20步......
Dim Current = frmMain.lvRec.Height
Dim Desired = 104
For i = 1 to 20 '1 to 20 since we're aiming for exactly 20 steps. Normally a for would start at 0 but in this case that would cause 21 steps
Dim Pos = Desired * (i/20) + Current * ((20-i)/20)
frmMain.lvRec.Height = Pos
System.Threading.Thread.Sleep(100)
End While
我们在这里做的是创建一个非常简单的线性'缓和'。有效地获取旧值的百分比和随时间变化的新值的百分比(随着i
增加)
示例...当前值= 200
,期望值= 100
,共20步(中间值显示在[]中,以使其更易于理解)...
SizeThisLoop = Desired * (i/20) + Current * ((20-i)/20)
100 * (01/20) [=05] + 200 * (19/20) [=190] = 195
100 * (02/20) [=10] + 200 * (18/20) [=180] = 190
...
100 * (05/20) [=25] + 200 * (15/20) [=150] = 175
...
100 * (20/20) [=100] + 200 * (0/20) [=000] = 100
这为您提供了一个很好的线性过渡。
值得注意的是,Windows窗体(又名WinForms)在这种情况下特别糟糕。如果主(UI)线程正在使用,用户界面通常不会更新。有很多方法可以使用DoEvents
,但它们最好是黑客 - 所以除非你实现某种形式的背景线程,否则UI很可能会锁定,直到你完成循环(这就是为什么你的表单消失了 - 它正在永远调整大小并且没有机会重绘。
有几种选择。 WPF在设计时考虑到了很好的效果,但行为方式完全不同,无法以这种方式编写。
如果不这样做,后台线程的使用会有所帮助 - 后台线程会随着时间的推移调整大小并告诉前台线程尽可能调整窗口大小。
像...一样的东西。
Public Sub Resizer()
'Set up a background thread to do the resizing
Dim T As New Threading.Thread(Sub() ResizeWorker())
T.Start()
End Sub
Private Sub ResizeWorker()
'The background thread. Takes approx 2 seconds to complete
Dim Current = frmMain.lvRec.Height
Dim Desired = 104
For i = 1 to 20 '1 to 20 since we're aiming for exactly 20 steps. Normally a for would start at 0 but in this case that would cause 21 steps
Dim Pos = Desired * (i/20) + Current * ((20-i)/20)
UIResize(Cint(Pos)) 'Do a resize
System.Threading.Thread.Sleep(100)
End While
End Sub
Private Sub UIResize(NewSize As Integer)
'Only the UI thread is allowed to update controls. Check if we're allowed to do so? (Can we make a change without invoking another thread?)
If Me.InvokeRequired
'This code isn't being executed on the UI thread. Ask the UI thread to run this method with the same parameters when it when it can
Me.Invoke(Sub() UIResize(NewSize))
Else
'We're now running on the UI thread... Resize at will!
Me.lvRec.Height = NewSize
End IF
End Sub