Code zur Anwendungsentwicklung in Classic Visual Basic

Inhaltsverzeichnis

Kopieren von Eigenschaften zugewiesenen Bildern

Visual Basic speichert der Picture-Eigenschaft von PictureBox-Steuerelementen zugewiesene Bilddaten in der FRX-Datei des Formulars. Aus dieser Datei können die Bilder nicht mehr mit einfachen Mitteln in eine Bilddatei exportiert werden.

Allerdings lassen sich die einer Picture-Eigenschaft zugewiesenen Bilddaten in die Zwischenablage kopieren. In der rechten Spalte der Eigenschaft im Eigenschaftenfenster steht das Bildformat (also z. B. (Bitmap) oder (Symbol)). Das Bild kann in die Zwischenablage kopiert werden, indem man die Einfügemarke auf diese Bezeichnung setzt und Strg+C drückt. Das Bildformat wird beibehalten, d. h., ein Metafile wird auch als Metafile in die Zwischenablage übertragen. Das funktioniert mit allen Steuerelementen, die eine Picture-Eigenschaft besitzen. Übrigens können auf diese Weise nicht nur Bilder kopiert, sondern auch ausgeschnitten (Strg+X) und eingefügt (Strg+V) werden. Das Kopieren und Einfügen funktioniert nur mittels der Tastaturbefehle, über das Kontextmenü des Eigenschaftenfensters kann nur die Bezeichnung als Text in die Zwischenablage kopiert werden.

Registrieren von ActiveX-Komponenten mittels API-Aufruf

ActiveX-Steuerelemente müssen in Windows registriert werden, bevor sie in Anwendungen eingesetzt werden können. Meist wird dies in Installationsroutinen über einen Aufruf der RegSvr32.exe mit den entsprechenden Parametern gemacht. Die Steuerelemente exportieren aber zu diesem Zweck auch die Funktionen DllRegisterServer und DllUnregisterServer, die zudem eine einfachere Handhabung von Registrierungsfehlern ermöglicht. Die folgenden beiden Funktionen geben True zurück, wenn der Vorgang erfolgreich war, andernfalls False:

Private Declare Function RegComCtl32 Lib "comctl32.ocx" _
    Alias "DllRegisterServer" _
( _
) As Long

Private Declare Function UnRegComCtl32 Lib "comctl32.ocx" _
    Alias "DllUnregisterServer" _
( _
) As Long

Private Const ERROR_SUCCESS As Long = 0&

Private Function RegisterCommonControls() As Boolean
    RegisterCommonControls = (RegComCtl32 = ERROR_SUCCESS)
End Function

Private Function UnregisterCommonControls() As Boolean
    UnregisterCommonControls = (UnRegComCtl32 = ERROR_SUCCESS)
End Function

Bei der Verwendung dieser Funktionen ist aber zu bedenken, daß jeder Aufruf bis zu 5 Sekunden in Anspruch nehmen kann. Bei anderen ActiveX-Komponenten ist der entsprechende Dateiname in der Deklaration einzutragen.

Ermitteln der Fehlertexte zu Visual-Basic-Fehlern

Die Beschreibungen den Fehler 1 bis 98 werden mit ihrer Nummer im Direktfenster der Entwicklungsumgebung ausgegeben:

Dim i As Integer
For i = 1 To 98   ' ...
    Debug.Print CStr(i) & ":  " & Error(i)
Next i

Entfernen der Anwendung aus der Prozeßliste

Unter Windows 9x ist es möglich, einen Prozeß nicht in der Liste der Tasks anzeigen zu lassen, indem man ihn als Dienst tarnt:

Private Declare Function GetCurrentProcessId Lib "kernel32.dll" ( _
) As Long

Private Declare Function RegisterServiceProcess Lib "kernel32.dll" ( _
    ByVal dwProcessId As Long, _
    ByVal dwType As Long _
) As Long

Private Const RSP_SIMPLE_SERVICE As Long = 1&

Private Sub RemoveProgramFromList()
    Call RegisterServiceProcess(GetCurrentProcessId, RSP_SIMPLE_SERVICE)
End Sub

Starten einer Anwendung unter beliebigem Datum

Manche Programme prüfen vor dem Start, ob ein bestimmtes Datum überschritten wurde, um dann eine Aktion durchzuführen. Dieser Quellcode startet die Anwendung unter einem Datum vor diesem Tag, wartet ein paar Sekunden und setzt dann das Datum wieder zurück. Es wird nicht berücksichtigt, daß während der Wartezeit eventuell ein Datumswechsel eintreten kann:

Private Sub Main()
    Dim OldDate As Date     ' Sicherung des alten Datums.
    OldDate = Date
    
    ' Aktuelles Datum manipulieren bzw. je nach Anwendung ein beliebiges festes
    ' Datum angeben.
    Date = CDate(Format$(OldDate, "dd.mm.") & "2001")
    
    ' Der Pfad auf das Programm muß hier eingestellt werden.
    Call Shell("C:\Program Files\MyApp\MyApp.exe", vbNormalFocus)
    
    ' Ein wenig warten, bis das Programm gestartet hat.
    Call Sleep(2)
    
    ' Jetzt kann das Datum wieder auf das Originaldatum zurückgesetzt werden.
    Date = OldDate
End Sub

'
' Wartet die angegebene Zahl von Sekunden und setzt danach die Abarbeitung
' fort.
'
Private Sub Sleep(ByVal Seconds As Single)
    Dim StartTime As Single
    StartTime = Timer
    Do While Timer < StartTime + Seconds
        Call DoEvents
    Loop
End Sub

Erhöhen der Priorität des Anwendungsthreads

Die Prozedur SetThreadToHighPriority aus dem nächsten Codeausschnitt setzt die Priorität des Threads, in dem die Anwendung ausgeführt wird, auf die höchstmögliche Stufe. Die Anwendung ist dann eine Echtzeitanwendung, deren Ausführung zeitkritisch ist. Besonders bei aufwendigen Berechnungen kann diese Methode zu bedeutend schnelleren Resultaten führen:

Private Declare Function GetCurrentThread Lib "kernel32.dll" ( _
) As Long

Private Declare Function GetCurrentProcess Lib "kernel32.dll" ( _
) As Long

Private Declare Function SetThreadPriority Lib "kernel32.dll" ( _
    ByVal hThread As Long, _
    ByVal nPriority As Long _
) As Long

Private Declare Function SetPriorityClass Lib "kernel32.dll" ( _
    ByVal hProcess As Long, _
    ByVal dwPriorityClass As Long _
) As Long

Private Const THREAD_BASE_PRIORITY_IDLE As Long = -15&
Private Const THREAD_BASE_PRIORITY_LOWRT As Long = 15&
Private Const THREAD_BASE_PRIORITY_MIN As Long = -2&
Private Const THREAD_BASE_PRIORITY_MAX As Long = 2&

Private Const THREAD_PRIORITY_LOWEST As Long = THREAD_BASE_PRIORITY_MIN
Private Const THREAD_PRIORITY_HIGHEST As Long = THREAD_BASE_PRIORITY_MAX
Private Const THREAD_PRIORITY_ABOVE_NORMAL As Long = THREAD_PRIORITY_HIGHEST - 1&
Private Const THREAD_PRIORITY_BELOW_NORMAL As Long = THREAD_PRIORITY_LOWEST + 1&
Private Const THREAD_PRIORITY_IDLE As Long = THREAD_BASE_PRIORITY_IDLE
Private Const THREAD_PRIORITY_NORMAL As Long = 0&
Private Const THREAD_PRIORITY_TIME_CRITICAL As Long = THREAD_BASE_PRIORITY_LOWRT
Private Const THREAD_PRIORITY_ERROR_RETURN As Long = &H7FFFFFFF&

Private Const IDLE_PRIORITY_CLASS As Long = &H40&
Private Const NORMAL_PRIORITY_CLASS As Long = &H20&
Private Const HIGH_PRIORITY_CLASS As Long = &H80&
Private Const REALTIME_PRIORITY_CLASS As Long = &H100&

Private Sub SetThreadToHighPriority()
    Call SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL)
    Call SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS)
End Sub

Ein selbstzerstörendes VBA-Makro

Das folgende VBA-Makro ist eine programmiererische Kuriosität: Es löscht sich selbst, wenn es ausgeführt wird. In VBA von Word, Excel etc. kann man nämlich direkt aus dem Quellcode heraus auf den Quellcode zugreifen und diesen manipulieren. Nach Ausführen des Makros sind nur mehr die Kommentare und dazwischen zwei leere Zeilen zu sehen. Mittels dieser Vorgehensweise lassen sich selbstmodifizierende Makros realisieren:

'*************************************
' Das steht davor.
'*************************************

Public Sub KamikazeMacro()
    With Application.VBE.ActiveCodePane.CodeModule
        Dim StartLine As Long, Line As Long
        For Line = 1 To .CountOfLines
            If .Lines(Line, 1) = "Public Sub KamikazeMacro()" Then
                StartLine = Line
            End If
            If StartLine > 0 Then
                If .Lines(Line, 1) = "End Sub" Then
                    Call .DeleteLines(StartLine, Line + 1 - StartLine)
                    Exit For
                End If
            End If
        Next Line
    End With
End Sub

'*************************************
' Das steht danach.
'*************************************