ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 01.02.2002

Diese Seite wurde zuletzt aktualisiert am 01.02.2002
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicActiveX-Komponenten, Controls, Klassen und mehr...AddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für den Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zum ABOUT Visual Basic-Magazin, Kontakt und Impressum

Zurück...

Gefrierschrank

Zurück...


Anzeige

(-hg) mailto:hg_lockedwindows@aboutvb.de

Steuerelemente, die dynamische Sammlungen anderer Elemente enthalten, wie etwa eine ListBox, reagieren auf jede Änderung der Sammlung mit einer Neudarstellung. Sollen viele Elemente unmittelbar nacheinander hinzugefügt, geändert oder entfernt werden (etwa in einer Schleife), flackert die Darstellung des Steuerelements nicht nur unschön, sondern die Neudarstellung kostet unnötig viel Zeit. Im Prinzip würde es genügen, nach der letzten Aktion eine Aktualisierung der Darstellung vorzunehmen. Es müsste eine Möglichkeit geben, die Aktualisierung eines Steuerelements bzw. eines Fensters vorübergehend zu unterbinden - es "einzufrieren".

Tatsächlich bietet Windows zwei Möglichkeiten an. Zum einen die API-Funktion LockWindowUpdate und zum anderen die Nachricht WM_SETREDRAW, die über die API-Funktion SendMessage an ein Fenster gesendet werden kann - näheres dazu finden Sie im Artikel Flackerfreiheit und mehr Rasanz"Flackerfreiheit und mehr Rasanz".

Während Sie per LockWindowUpdate immer nur ein einziges Fenster einfrieren und eingefroren halten können, erlaubt Ihnen die Nachricht WM_SETREDRAW, jedes beliebige Fenster (die meisten Steuerelemente sind ja Fenster) zu jedem beliebigen Zeitpunkt beliebig lange einzufrieren. Falls Sie jedoch von dieser Möglichkeit intensiveren Gebrauch machen sollten, besteht die Gefahr, die Übersicht darüber zu verlieren, welches Fenster nun gerade eingefroren ist und welches nicht. Ebenso haben Sie wenig Kontrolle über die gegebenenfalls von verschiedenen Stellen in Ihrem Code aus erfolgten Einfrierungen.

Das Modul modLockedWindows hilft Ihnen, die Übersicht zu behalten. Es merkt sich in einer Collection, welche Fenster eingefroren sind. Darüber hinaus merkt es sich sogar, wie oft die Anweisung zum Einfrieren eines Fensters erfolgt ist, und hebt die Einfrierung erst wieder auf, wenn die gleiche Anzahl zur Aufhebung erfolgt ist.

Dazu werden Zähler für jedes Fenster in einer Collection abgelegt. Als Schlüssel dient das explizit in einen String konvertierte Fenster-Handle. Ein Einfrieren erfolgt nun über einen Aufruf der Prozedur LockWindow mit dem betreffenden Fenster-Handle als Parameter.

Private Declare Function SendMessage Lib "user32" _
 Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, _
 ByVal wParam As Long, lParam As Long) As Long

Private Const WM_SETREDRAW = &HB

Private mLockedWindows As Collection

Public Sub LockWindow(ByVal hWnd As Long)
  Dim nLockCount As Long
  
  If mLockedWindows Is Nothing Then
    Set mLockedWindows = New Collection
  End If
  On Error Resume Next
  nLockCount = mLockedWindows(CStr(hWnd))
  If Err.Number Then
    nLockCount = 1
  Else
    mLockedWindows.Remove CStr(hWnd)
    nLockCount = nLockCount + 1
  End If
  mLockedWindows.Add nLockCount, CStr(hWnd)
  SendMessage hWnd, WM_SETREDRAW, 0, 0
End Sub

Da ein in eine Collection aufgenommener Wert nicht verändert werden kann, muss der Zähler vorübergehend aus der Collection entfernt, dann erhöht und anschließend wieder eingefügt werden. Falls der Zähler zu einem Fenster-Handle noch nicht in der Collection enthalten gewesen ist, wird er mit dem Wert 1 erstmals aufgenommen. Falls die Collection noch nicht instanziert gewesen sein sollte, wird sie frisch instanziert.

Zum "Auftauen" wird in der Prozedur UnlockWindow der Zähler zum betreffenden Fenster ermittelt und um 1 erniedrigt. Verbleibt der Zählerwert größer

wird der neue Zählerwert wieder in die Collection eingefügt, falls nicht im optionalen Parameter Forced der Wert True übergeben wurde. Ist dagegen der Wert des Zählers auf 0 zurück gegangen, oder wurde in Forced True übergeben, wird er nicht wieder eingefügt, während die Sperrung des Fensters aufgehoben wird. Sollte die Collection danach leer sein, wird sie gelöscht.

Public Enum LockWindowErrorConstants
  lwErrNoLockedWindow = 30001
  lwErrWindowNotLocked = 30002
End Enum
  
Public Sub UnlockWindow(ByVal hWnd As Long, _
 Optional ByVal Forced As Boolean)

  Dim nLockCount As Long
  
  If mLockedWindows Is Nothing Then
    Err.Raise lwErrNoLockedWindow, "UnlockWindow"
  Else
    On Error Resume Next
    nLockCount = mLockedWindows(CStr(hWnd))
    If Err.Number Then
      Err.Raise lwErrWindowNotLocked, "UnlockWindow"
    Else
      mLockedWindows.Remove CStr(hWnd)
      nLockCount = nLockCount - 1
      If Not Forced Then
        If nLockCount > 0 Then
          mLockedWindows.Add nLockCount, CStr(hWnd)
        End If
      End If
      If nLockCount = 0 Then
        SendMessage hWnd, WM_SETREDRAW, 1, 0
      End If
    End If
    If mLockedWindows.Count = 0 Then
      Set mLockedWindows = Nothing
    End If
  End If
End Sub

Auf ähnliche Weise können Sie über die Funktion IsWindowLocked abfragen, ob ein Fenster aktuelle eingefroren ist.

Public Function IsWindowLocked(ByVal hWnd As Long) As Boolean
  Dim nLockCount As Long
  
  If mLockedWindows Is Nothing Then
    Err.Raise lwErrNoLockedWindow, "IsWindowLocked"
  Else
    On Error Resume Next
    nLockCount = mLockedWindows(CStr(hWnd))
    If Err.Number = 0 Then
      IsWindowLocked = True
    End If
  End If
End Function

Mit der Prozedur UnlockAllWindows tauen Sie schließlich alle eingefrorenen Fenster auf einen Schlag wieder auf.

Public Sub UnlockAllWindows()
  Dim l As Long
  
  If Not (mLockedWindows Is Nothing) Then
    For l = 1 To mLockedWindows.Count
      SendMessage CLng(mLockedWindows(l)), WM_SETREDRAW, 1, 0
    Next 'l
    Set mLockedWindows = Nothing
  End If
End Sub

Modul modLockedWindows (modLockedWindows.zip - ca. 0,9 KB)


Artikel
Zum Download-Bereich dieses Artikel
Mail an den Autor dieses Artikels

KnowHow
Zur KnowHow-Übersicht

KnowHow-Themen
Themen - Allgemeines
Themen - Entwicklungsumgebung (VB-IDE)
Themen - Forms
Themen - Steuerelemente (Controls)
Themen - Grafik
Themen - Dateien
Themen - UserControls
Themen - Einsteiger-Tipps
Themen - Wussten Sie...?

Übersicht nach Titeln in alphabetischer Reihenfolge
Übersicht nach Erscheinungsdatum

Schnellsuche




Zum Seitenanfang

Copyright © 1999 - 2017 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...

Download Internet Explorer