środa, 10 lutego 2016

• Funkcje API - ile uruchomiono instancji MS Access

W poprzednim artykule • Funkcje API - jak pobrać nazwę klasy okna o uchwycie hwnd • dowiedzieliśmy się jak wykorzystać interfejs API, aby odczytać nazwę klasy okna. Po uruchomieniu przykładowego kodu wiemy, że nazwa klasy głównego okna MS Access brzmi OMain, a okno formularza jest klasy OForm.

Czasami w trakcie działania aplikacji MS Access potrzebujemy sprawdzić, czy otwarta jest inna baza MS Access, a jeżeli tak, to ile instancji MS Access jest uruchomionych. Do tego celu wykorzystamy interfejs Windows API i jego dwie funkcje:
• GetDesktopWindow - zwracającą uchwyt pulpitu czyli okna obejmującego cały ekran. Na pulpicie osadzone są wszystkie pozostałe okna
• FindWindowEx - zwracającą uchwyt okna potomnego, którego albo nazwa klasy, lub (i) tytuł odpowiadają nazwom przekazanym w argumentach funkcji.

Option Compare Database
Option Explicit
 
' • Function CountAccessInstances( _
'                  Optional ByVal sAccessTitle As String = vbNullString) As Long
' --------------------------------------------------------------------------------
' autor: Zbigniew Bratko - 02.2016

' [sAccessTitle] - argument opcjonalny, tytuł szukanego okna,
'                  dla ciągu zerowej długości lub znaku vbNullString
'                  wyliczane są wszystkie okna MS Access,
' [Out] - zwraca liczbę uruchomionych instancji MS Access,
'         o tytule odpowiadającym argumentowi sAccessTitle
'         Przy niepowodzeniu zwraca 0 (Zero)
'
 
#If VBA7 Then
  Private Declare PtrSafe Function FindWindowEx Lib "user32" _
          Alias "FindWindowExA" _
          (ByVal hWnd1 As LongPtr, _
          ByVal hWnd2 As LongPtr, _
          ByVal lpsz1 As String, _
          ByVal lpsz2 As String) As LongPtr
#Else
  Private Declare Function FindWindowEx Lib "user32" _
          Alias "FindWindowExA" _
          (ByVal hWnd1 As Long, _
          ByVal hWnd2 As Long, _
          ByVal lpsz1 As String, _
          ByVal lpsz2 As String) As Long
#End If


' Funkcja własna CountAccessInstances
Public Function CountAccessInstances( _
                      Optional ByVal sAccessTitle As String = vbNullString) As Long
#If VBA7 Then
  Dim hNext As LongPtr
#Else
  Dim hNext As Long
#End If
  
' licznik
Dim lCount As Long
' nazwa klasy okna MS Access
Const cAccWindowClass As String = "OMain"

  ' konwertuj ciąg zerowej długości "" na vbNullString,
  ' gdyż ciąg zerowej długości "", to nie to samo co vbNullString
  If Len(sAccessTitle) = 0 Then sAccessTitle = vbNullString
  
  ' szukaj pierwszego wystąpienia potomnego okna MS Access klasy "OMain"
  ' i tytule sDbTitle, w oknie rodzica "Pulpit" (domyślnie dla argumentu hWnd1 = 0)
  hNext = FindWindowEx(0, 0, ByVal cAccWindowClass, ByVal sAccessTitle)
    
  Do Until hNext = 0
    ' zwiększ licznik
    lCount = lCount + 1
    ' szukaj następnego wystąpienia okna MS Access klasy "OMain"
    hNext = FindWindowEx(0, ByVal hNext, ByVal cAccWindowClass, ByVal sAccessTitle)
  Loop

  CountAccessInstances = lCount
  
End Function


' przykładowe wywołanie
Private Sub btnTest_Click()
Dim lRet As Long
  
  lRet = CountAccessInstances()
  MsgBox "Uruchomionych instancji MS Access: " & CStr(lRet) & " egz."
 
End Sub