Übersicht
0001 NT-Betriebssystem?
Damit Ihre Applikation auf den verschiedenen Windows-Plattformen lauffähig ist, ist es manchmal notwendig zwischen NT (NT/2000/XP/Vista/usw.) und Nicht-NT (Win9x/ME) Systemen zu unterscheiden, da zum Beispiel einige API-Aufrufe nur auf NT-Plattformen zur Verfügung stehen. Wenn auch die benutzte "GetVersionEx"-Funktion die genaue Betriebssystem-Version ermitteln kann, wollen wir uns in diesem Fall auf die Prüfung von NT-Basis beschränken. Diese Abfrage ist z.B. dann wichtig, wenn wir eine unicodefähige Anwendung schreiben wollen, da Unicode grundsätzlich erst ab Windows NT/2000 zur Verfügung steht: ' Deklaration: Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" _ (lpVersionInformation As OSVERSIONINFO) As Long ' Typendefinition: Private Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long szCSDVersion As String * 128 End Type Private Const VER_PLATFORM_WIN32_NT = 2 ' Funktion: ' Prüft auf NT-Betriebssysteme: True ab Windows NT/2000 und neuer, sonst False Public Function isSystemNT() As Boolean Dim info As OSVERSIONINFO info.dwOSVersionInfoSize = Len(info) GetVersionEx info isSystemNT = (info.dwPlatformId = VER_PLATFORM_WIN32_NT) End Function | |
Autor: ralf schlegel |
0002 vbzMsgBox
Jeder nutzt sie - die VB-integrierte MsgBox Funktion! Sie erspart einem das Erstellen einer Form und ist einfach ideal für Benutzer-Informationen, oder interaktive Abfragen. Doch das Einfache hat auch wieder seinen Preis: Mit dem hier zum Download bereit gestellten Beispiel können Sie die MsgBox endlich im vollen Umfang nutzen:
Die Funktionen sind in einem einzigen Modul gekapselt und lassen sich so problemlos in Ihre Anwendungen implementieren, da Sie dort nur den Aufruf Ihrer bisherigen MsgBox durch vbzMsgBox ersetzen, bzw. erweitern müssen. | |
Autor: ralf schlegel |
0003 UAC in Vista und Winows 7
Das leidige Thema des UAC (User Account Control, oder zu Deutsch: Benutzerkontensteuerung) beschäftigt uns VB-Programmierer immer wieder; haben wir doch plötzlich nicht mehr das Recht Dateien in unserem Applikationsverzeichnis zu ändern, wenn die Installation unter "..\Program Files\.." erfolgte - und das Registrieren von DLLs oder OCXs zur Laufzeit ist auch nicht mehr so leicht wie früher... Private Declare Function IsUserAnAdmin Lib "shell32.dll" () As Long ' Hat der Benutzer Administrator-Rechte? Public Function isAdmin() As Boolean If isSystemNT Then ' Siehe Tipp 0001 isAdmin = CBool(IsUserAnAdmin()) Else ' auf Einzelbenutzersystemen ' hat der User immer Adminrechte isAdmin = True End If End Function Lösungsansatz: glbDataPath = getSpecialFolder(CSIDL_COMMON_APPDATA)
Laden und speichern Sie zusätzliche Programmdaten, wie Konfigurationen und INI-Files im Verzeichnis glbDataPath. Egal unter welchem System Ihre Anwendung läuft: die Daten können nun problemlos geschrieben und verändert werden... | |
Autor: ralf schlegel |
0004 Hat die eigene Anwendung den Fokus? - WM_ACTIVATEAPP
| Mit den Prozeduren Form_GotFocus und Form_LostFocus können wir ermitteln, ob die aktuelle Form gerade aktiv ist (den Fokus hat), oder nicht. Manchmal wäre es jedoch besser zu wissen, ob die gesamte Anwendung den Fokus hat, oder nicht. So lassen sich z.B. aufwendigere Hintergrundarbeiten erledigen, wenn der Benutzer gerade mit einer anderen Anwendung arbeitet. Option Explicit Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _ (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _ (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Private Const GWL_WNDPROC = -4 Private Const WM_ACTIVATEAPP = &H1C ' Locale Variablen: Private mainOldProc As Long ' Pointer auf original Fensterprozedur Global glbAppActive As Boolean ' globale Überwachungsvariable ' Subclassing initialisieren: Public Sub MainHook(ByVal hWnd As Long) glbAppActive = True ' Wenn wir starten, sind wir die aktive Anwendung mainOldProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf winMain) End Sub ' Subclassing beenden: Public Sub MainUnHook(ByVal hWnd As Long) SetWindowLong hWnd, GWL_WNDPROC, mainOldProc End Sub ' Unsere Erweiterung der Fensterprozedur: Private Function winMain(ByVal hWnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&) As Long Select Case uMsg Case WM_ACTIVATEAPP If wParam Then ' Anwendung wurde aktiviert glbAppActive = True Else ' Anwendung wurde deaktiviert glbAppActive = False End If End Select winMain = CallWindowProc(mainOldProc, hWnd, uMsg, wParam, lParam) End Function In der Hauptform unserer Anwendung rufen wir dann in der Load Anweisung die Funktion MainHook auf und übergeben ihr das Handle der Form, also "Me.hWnd". In der QueryUnload Anweisung muss nun das Pendant MainUnHook (Me.hWnd) aufgerufen werden, sonst stürzt die Anwendung ab! Das war schon alles. - Die globale Variable glbAppActive kann dann z.B. über einen Timer abgefragt werden. Verfügt Ihre Anwendung bereits über ein Hooking, so ist es noch einfacher: |
Autor: ralf schlegel |
0005 32- oder 64Bit Betriebssystem?
VB6 Anwendungen leben weiter! Warum auch nicht: alle Hürden der neuen Betriebssysteme lassen sich bis heute meistern. Beispiele für Unicode oder den Umgang mit dem UAC gibt es genug im Netz. Die neue Herausforderung heißt 64Bit, die nun seit geraumer Zeit zum Auslieferungsstandard von Microsoft geworden ist. Je nach Art und Umfang der Anwendung ist es erforderlich zu wissen, ob wir auf einem 32 oder 64 Bit Betriebssystem unterwegs sind. Auch hier ist die Lösung per API relativ einfach zu realisieren. ' Deklaration: ' Globale Variable: In der Programminitialisierungs-Routine Ihrer Anwendung fügen Sie nun folgende Zeilen ein: If GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process") Then Die Variable "is64BitWin" können Sie nun an beliebiger Stelle im Programm abfragen und entsprechend reagieren. Zum Verständnis: | |
Autor: ralf schlegel |
0006 Die eigene Anwendung "sauber" beenden
Kennen Sie das: Sie haben eine aufwendige Applikation geschrieben, in der IDE getestet und alles scheint zu funktionieren. Nach dem Kompilieren läuft die Anwendung auch als EXE, bis sie beendet wird und nun das: Nach kurzer Zeit meldet sich der Windows Problemreport und meckert Ihre Anwendung an! Sie öffnen den Taskmanager, wechsel auf die Registerkarte "Prozesse" und starten Ihre Anwendung erneut. Ihre Anwendung wird im Taskmanager sichtbar. Nun beenden Sie Ihre Anwendung und... Möglichkeit A:
Möglichkeit B:
| |
Autor: ralf schlegel |
0007 Fremdanwendung mit Adminrechten starten
Wenn Sie aus Ihrer eigenen Applikation heraus eine Anwendung starten wollen, so kann es vorkommen, dass diese zum reibungslosen Ablauf über Administratorrechte verfügen muss. Spätestens seit Windows Vista führt dies immer dann zum Problem, wenn der UAC (User Access Control) eingeschaltet ist, da man dann - selbst als angemeldeter Administrator - nicht über die erforderlichen Rechte verfügt um z.B. den Registrierungseditor ("regedit") aufzurufen. Neben der VBA internen Shell Funktion, kennen Sie vielleicht die Alternative des Windows API, "ShellExecute", mit der sich u. A. eine Anwendung starten läßt. In der Parameterübergabe zu dieser Funktion gibt es das so genannte "Operation-Verb" - ein String, der die Art des Programmstarts beeinflussen kann. Neben den Schlüsselwörtern "Open", "Edit" und "Print" gibt es auch das Schlüsselwort "RunAs", das uns so auf einfachste Weise in den Administratormodus bringt! Hier ein simples Beispiel für den Aufruf des Registrierungseditors: Private Declare Function ShellExecuteA Lib "shell32" (ByVal hWnd As Long, _ ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _ ByVal lpDirectory As String, ByVal nShowCmd As VbAppWinStyle) As Long ShellExecuteA 0, "RunAs", "regedit.exe", vbNullString, vbNullString, vbNormalFocus Oder Sie möchten zur Laufzeit nachträglich ein OCX oder eine DLL registrieren; ein klassischer Fall für ein Updateprogramm. ShellExecuteA 0, "RunAs", "regsvr32", """" & ocxName & """", vbNullString, vbNormalFocus wobei "ocxName" eine Stringvariable darstellt, die den kompletten Pfad und Namen der Datei beinhaltet. | |
Autor: ralf schlegel |