Hauptseite >Tips zu VB5/6 >  Modernisierte Refresh-Methode     view this document in English view this document in English
 
Wenn Sie eine länger laufende Prozedur haben, die ihren Verarbeitungsfortschritt visualisieren soll, müssen Sie Windows explizit die Gelegenheit geben, die Visualisierung durchzuführen. Beispiel:

Private Sub Command1_Click()
Dim l As Long
  For l = 1 To 50000
    Label1.Caption = CStr(l)
  Next
End Sub
            
Wenn Sie diesen Code ablaufen lassen, werden Sie feststellen, dass das Label mitnichten anzeigt, beim wievielten Schleifendurchlauf die Routine gerade ist. Mit folgender Ergänzung hingegen klappt's:

Private Sub Command1_Click()
Dim l As Long
  For l = 1 To 50000
    Label1.Caption = CStr(l)
    Label1.Refresh
  Next
End Sub
            
Statt Label1.Refresh könnten Sie auch DoEvents verwenden, jedoch führt dies zur Abarbeitung aller anstehenden Ereignisse, z.B. auch einen erneuten Klick auf den Button, der die Routine ein weiteres Mal starten würde. Gegen solche unerwünschten Nebenwirkungen müssten Sie Vorkehrungen treffen, auf die Sie mit der Refresh-Methode getrost verzichten können.

Seit Windows XP funktioniert das aber nur noch für kurze Zeit; nach einigen Sekunden ohne DoEvents-Rückmeldung meint Windows, das Programm sei zu beschäftigt zum Neuzeichnen, und fertigt deshalb einen Screenshot von ihm an, der über das Formular gelegt wird, bis sich das Programm wieder "vollständig zurückmeldet". Das ist zwar nett gemeint, konterkariert aber unsere obigen Bemühungen. Mit DoEvents wäre das Problem wieder aus der Welt geschafft, aber das wollten wir aus den besprochenen Gründen eigentlich gerade vermeiden.

Was tun? Der folgende Ersatz für Refresh schafft Abhilfe:

Option Explicit

'Deklarationen (in ein Standard-Modul)

Public Const WM_PAINT = &HF
Public Const PM_REMOVE = &H1

Public Type POINTAPI
  x As Long
  y As Long
End Type

Public Type MSG
  hwnd As Long
  message As Long
  wParam As Long
  lParam As Long
  time As Long
  pt As POINTAPI
End Type

Public Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" _
  (lpMsg As MSG, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, _
  ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
Public Declare Function TranslateMessage Lib "user32" _
  (lpMsg As MSG) As Long
Public Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" _
  (lpMsg As MSG) As Long

Ersatz für die Refresh-Methode

Sub RefreshEx(ByVal hwnd As Long)
Dim mMSG As MSG
  If PeekMessage(mMSG, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE) Then
    TranslateMessage mMSG
    DispatchMessage mMSG
  End If
End Sub
            
Dieser Methode - die im Übrigen auch unter allen Win32-Versionen vor XP funktioniert - übergeben Sie das Fensterhandle (hWnd) desjenigen Controls oder derjenigen Form, die aktualisiert werden soll. Da ein Label als "windowless control" kein Fensterhandle besitzt, übergeben Sie einfach das Handle der übergeordneten Form:

Private Sub Command1_Click()
Dim l As Long
  For l = 1 To 50000
    Label1.Caption = CStr(l)
    RefreshEx Me.hwnd
  Next
End Sub
            
Hauptseite >  Tips zu VB5/6 >  diese Seite