Access

  MS Access 2010+  |  Aplication Programming Interface API  |   VBA 7.0

• API. Funkcje zarządzania oknami.

Niektóre właściwości okien.

Podczas projektowania bazy danych czasami potrzebujemy niektórych danych o oknie głównym MS Access, bądź jego okna potomnych (dzieciach). Istotna może być szerokość obramowanie okna, gdyż okno może posiadać cienkie obramowanie, bądź obramowanie pogrubione, takie jak mają okna dialogowe. Czy okno posiada przycisk maksymalizacji i minimalizacji, pasek tytułowy, obramowanie oraz systemowe menu na swoim pasku tytułowym. Czy jest aktywne, czy jest zminimalizowane bądź zmaksymalizowane. A także czy okno jest oknem potomnym (dzieckiem) i czy można zmieniać rozmiar okna. Najistotniejsze, jak dla mnie jest, czy okno posiada poziomy pasek przewijania i (lub) okno posiada pionowy pasek przewijania.
Potrzebny nam może być także uchwyt okna rodzica, bądź uchwyt do instancji programu.

Jak pobrać właściwości okna MS Access

Aby pobrać niektóre właściwości okna o uchwycie hwnd powinniśmy użyć funkcji GetWindowsLong(...) z argumentem nIndex = GWL_STYLE i zwracaną wartość przypisać do zmiennej lStyle. Po wywołaniu:

lStyle = GetWindowLong(hWind, GWL_STYLE)

zwrócona wartość liczbowa lStyle zawiera wszystkie interesujące informacje dotyczące okna o uchwycie hwnd. Ładnie to brzmi, ale co można wywnioskować z takich liczb:

1445986305, 1409286144, 1442840577, 1442840576, 382664704, 399441920, -1811677180

wiedząc, że każda z tych liczb zawiera informacje o stylu i właściwościach różnych, widocznych na ekranie, okien. Jak zinterpretować zwracane dane. Co ciekawego mogą zawierać te liczby?

Interpretacja danych zwracanych przez funkcję GetWindowsLong(...)

Operator bitowy AND, iloczyn bitowy, koniunkcja bitowa.

Operator bitowy AND to operacja, w wyniku której włączone pozostają tylko te bity, które są włączone w obu argumentach. Wynik operacji AND na pojedynczych bitach został zobrazowany poniżej:

14 AND 7 = 6
------------------
14 dwójkowo to 1110
 7 dwójkowo to  111
-------------------
 6 dwójkowo to  110

Aby sprawdzić, czy w liczbie są ustawione bity odpowiadające bitom sprawdzanej liczby, powinniśmy zastosować operator bitowy AND. Jeżeli w wyniku otrzymamy sprawdzaną liczbę, to oznacza że w obu liczbach ustawione są te same bity:

If (14 AND 6) = 6 Then
  ------------------
  14 dwójkowo to 1110
   6 dwójkowo to  110
  -------------------
   6 dwójkowo to  110
End If

Sprawdzanie jakie elementy stylu ma okno.

Aby sprawdzić, czy styl okno zawiera konkretny element stylu, należy zastosować operator bitowy AND by sprawdzić bitowo, czy wartość liczbowa stylu okna ma ustawione bity odpowiadające bitom elementu stylu okna.

If (lWindowStyle AND WS_HSCROLL) = WS_HSCROLL Then ' jest poziomy pasek przewijania

If (lWindowStyle AND WS_VSCROLL) = WS_VSCROLL Then ' jest pionowy pasek przewijania

Problem stylu WS_OVERLAPPED

• Okno nakładające się WS_OVERLAPPED
Okno nakładające się jest oknem najwyższego poziomu, które ma pasek tytułu, obramowanie i obszar klienta (roboczy). Może również zawierać menu okna, przyciski minimalizacji i maksymalizacji oraz paski przewijania. Nakładające się okno używane jako główne okno aplikacji zazwyczaj zawiera wszystkie te elementy.

Dla stylu WS_OVERLAPPED = 0 (Zero) istnieje problem odczytania stylu takiego. Iloczyn bitowy dowolnej liczby z liczbą 0 (Zero) daje 0 (Zero), gdyż liczba 0 (Zero) nie ma ustawionego żadnego bitu. Tak więc dla każdego okna otrzymamy, że posiada ono styl WS_OVERLAPPED.

If (lWindowStyle AND WS_OVERLAPPED) = WS_OVERLAPPED Then ' zawsze będzie styl WS_OVERLAPPED

Rozwiązaniem jest sprawdzenie, czy okno nie jest oknem potomnym (dzieckiem) WS_CHILD i czy okno nie jest oknem typu wyskakującym (popup) WS_POPUP.

• Okno potomne WS_CHILD
Okno potomne jest ograniczone do obszaru roboczego jego okna nadrzędnego. Aplikacja zazwyczaj używa okien potomnych do podziału obszaru roboczego okna nadrzędnego na obszary funkcjonalne.
• Okno wyskakujące WS_POPUP
Okno wyskakujące to specjalny rodzaj nakładających się okien używanych w oknach dialogowych, okienkach komunikatów i innych tymczasowych oknach, które pojawiają się poza głównym oknem aplikacji.

If ((lWindowStyle AND WS_POPUP) = 0) AND ((lWindowStyle AND WS_CHILD) = 0) Then ' styl WS_OVERLAPPED

bądź krócej

If (lWindowStyle AND (WS_POPUP OR WS_CHILD)) = 0 Then ' styl WS_OVERLAPPED

⊗ Private Function accGetWindowStyle(lWindowStyle As Long) As String
  • Opisowa informacja o elementach stylu okna.
  • argumenty:
    • lWindowStyle
    • wartość liczbowa określająca styl okna, zwrócona przez funkcję GetWindowsLong(hwnd, GWL_STYLE
  • zwraca:
  • Przy powodzeniu zwraca ciąg znaków zawierający opis elementów stylu okna. Przy niepowodzeniu zwraca ciąg zerowej długości "".
  • autor: Zbigniew Bratko
  • data: 07.01.2019
Option Compare Database
Option Explicit

#If Win64 Then
  Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
          Alias "GetWindowLongPtrA" _
          (ByVal hwnd As LongPtr, _
          ByVal nIndex As Long) As LongPtr
#ElseIf VBA7 Then
  Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
          Alias "GetWindowLongA" _
          (ByVal hwnd As LongPtr, _
          ByVal nIndex As Long) As LongPtr
#Else
  Private Declare Function GetWindowLong Lib "user32" _
          Alias "GetWindowLongA" _
          (ByVal hwnd As Long, _
          ByVal nIndex As Long) As Long
#End If

' stałe określające przesunięcie argumentu nIndex :
Private Const GWL_WNDPROC = (-4)            'adres procedury okna
Private Const GWL_HINSTANCE = (-6)          'uchwyt do instancji programu
Private Const GWL_HWNDPARENT = (-8)         'uchwyt do okna rodzica
Private Const GWL_ID = (-12)                'identyfikator okna potomnego
Private Const GWL_STYLE = (-16)             'style okna
Private Const GWL_EXSTYLE = (-20)           'rozszerzony styl okna
Private Const GWL_USERDATA = (-21)          'dane użytkownika powiązane z oknem.
' stałe określające styl okna
Private Const WS_BORDER = &H800000          'okno z cienkim obramowaniem
Private Const WS_CAPTION = &HC00000         'okno z paskiem tytułowym, (zawiera WS_BORDER)
Private Const WS_CHILD = &H40000000         'okno typu child, bez paska menu, nie może być
                                            'użyte łącznie z WS_POPUP
Private Const WS_CHILDWINDOW = WS_CHILD     'jak WS_CHILD
Private Const WS_CLIPCHILDREN = &H2000000   'wyklucza obszar zajmowany przez okna podrzędne
                                            'podczas rysowania w oknie nadrzędnym.
Private Const WS_CLIPSIBLINGS = &H4000000   'oddzielny obszar okien klienta i child,
                                            'gdy okno potomne otrzymuje komunikat WM_PAINT,
                                            'obcinane są inne nakładające się okna potomne
Private Const WS_DISABLED = &H8000000       'okno jest nieaktywne po utworzeniu. By uaktywnić
                                            'okno należy użyć funkcji EnableWindow
Private Const WS_DLGFRAME = &H400000        'pogrubiona obramowanie typu okna dialogowego,
                                            'nie może mieć paska tytułowego
Private Const WS_GROUP = &H20000            'wyznacza pierwsze okno z grupy okien
Private Const WS_HSCROLL = &H100000         'okno posiada poziomy pasek przewijania
Private Const WS_MAXIMIZE = &H1000000       'okno jest zmaksymalizowane po utworzeniu
Private Const WS_MAXIMIZEBOX = &H10000      'widoczny  przycisk maksymalizacji, używany
                                            'wraz ze stylem WS_SYSMENU
Private Const WS_MINIMIZE = &H20000000      'okno jest zminimalizowane po utworzeniu
Private Const WS_ICONIC = WS_MINIMIZE       'jak WS_MINIMIZE
Private Const WS_MINIMIZEBOX = &H20000      'widoczny przycisk minimalizacji, używany
                                            'wraz ze stylem WS_SYSMENU
Private Const WS_OVERLAPPED = &H0&          'okno ma pasek tytułowy oraz ramkę, jak WS_TILED
Private Const WS_POPUP = &H80000000         'okno PopuUp, nie może być użyte łącznie z WS_CHILD
Private Const WS_SYSMENU = &H80000          'okno posiada menu systemowe. Razem z WS_CAPTION
Private Const WS_TABSTOP = &H10000          'możliwe przełączanie za pomocą TAB
Private Const WS_THICKFRAME = &H40000       'jak WS_SIZEBOX
Private Const WS_SIZEBOX = WS_THICKFRAME    'możliwa jest zmiana rozmiaru okna,
Private Const WS_TILED = WS_OVERLAPPED      'jak WS_OVERLAPPED
Private Const WS_VISIBLE = &H10000000       'okno jest widoczne po utworzeniu
Private Const WS_VSCROLL = &H200000         'okno posiada pionowy pasek przewijania
Private Const WS_OVERLAPPEDWINDOW = _
                                    (WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or _
                                     WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX)
Private Const WS_POPUPWINDOW = (WS_POPUP Or WS_BORDER Or WS_SYSMENU)
Private Const WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW


#If VBA7 Then
  Private Function accGetWindowStyle(lWindowStyle As LongPtr) As String
#Else
  Private Function accGetWindowStyle(lWindowStyle As Long) As String
#End If
Dim vArrStyle As Variant
Dim sStyle    As String
Dim i         As Byte

	' nieprawidłowa wartość argumentu lWindowStyle
	If lWindowStyle = 0 Then Exit Function

	' tablica zawierająca pary powiązanych danych:
	' styl okna i odpowiadająca mu wartość
	' UWAGA! bez stylu WS_OVERLAPPED = 0,
	 vArrStyle = Array( _
							"WS_BORDER", WS_BORDER, _
							"WS_CAPTION", WS_CAPTION, _
							"WS_CHILD", WS_CHILD, _
							"WS_CLIPCHILDREN", WS_CLIPCHILDREN, _
							"WS_CLIPSIBLINGS", WS_CLIPSIBLINGS, _
							"WS_DISABLED", WS_DISABLED, _
							"WS_DLGFRAME", WS_DLGFRAME, _
							"WS_GROUP", WS_GROUP, _
							"WS_HSCROLL", WS_HSCROLL, _
							"WS_MAXIMIZE", WS_MAXIMIZE, _
							"WS_MAXIMIZEBOX", WS_MAXIMIZEBOX, _
							"WS_MINIMIZE", WS_MINIMIZE, _
							"WS_MINIMIZEBOX", WS_MINIMIZEBOX, _
							"WS_POPUP", WS_POPUP, _
							"WS_POPUPWINDOW", WS_POPUPWINDOW, _
							"WS_SYSMENU", WS_SYSMENU, _
							"WS_TABSTOP", WS_TABSTOP, _
							"WS_THICKFRAME", WS_THICKFRAME, _
							"WS_VISIBLE", WS_VISIBLE, _
							"WS_VSCROLL", WS_VSCROLL)
							'"WS_OVERLAPPED", WS_OVERLAPPED,

	' sprawdź, czy styl okna to WS_OVERLAPPED
	If (lWindowStyle And (WS_POPUP Or WS_CHILD)) = 0 Then
		sStyle = sStyle & "WS_OVERLAPPED" & vbNewLine
		' sprawdź, czy styl okna to WS_OVERLAPPEDWINDOW
		If (lWindowStyle And (WS_OVERLAPPEDWINDOW)) = WS_OVERLAPPEDWINDOW Then
			sStyle = sStyle & "WS_OVERLAPPEDWINDOW" & vbNewLine
		End If
	End If

	If Len(sStyle) > 1 Then
		sStyle = sStyle & String(35, 45) & vbNewLine
	End If

	' porównaj bitowo styl okna z poszczególnymi elementami stylu
	For i = LBound(vArrStyle) To UBound(vArrStyle) Step 2
			 If (lWindowStyle And vArrStyle(i + 1)) = vArrStyle(i + 1) Then
					sStyle = sStyle & vArrStyle(i) & vbNewLine
			 End If
	Next

	' utnij ostatni znak nowej linii
	If Len(sStyle) > 1 Then
		sStyle = Left$(sStyle, Len(sStyle) - 2)
		accGetWindowStyle = sStyle
	End If

	End Function

	' przykładowe wywołanie:
	Private Sub btnTest_Click()
	#If VBA7 Then
	Dim lStyle  As LongPtr
	Dim hWind  As LongPtr
	#Else
	Dim lStyle  As Long
	Dim hWind  As Long
	#End If
	Dim sStyleWindow As String

	' pobierz styl okna MS Access
	hWind = Application.hWndAccessApp

	#If VBA7 Then
		'hWind = GetWindowLongPtr(Me.hwnd, GWL_HWNDPARENT)
		lStyle = GetWindowLongPtr(hWind, GWL_STYLE)
	#Else
		'hWind = GetWindowLong(Me.hwnd, GWL_HWNDPARENT)
		lStyle = GetWindowLong(hWind, GWL_STYLE)
	#End If

	' pobierz opisowy styl okna
	sStyleWindow = accGetWindowStyle(lStyle)

	MsgBox "Uchwyt: " & hWind & vbNewLine & _
					"Styl: " & lStyle & vbNewLine & _
					String(25, 45) & vbNewLine & _
					sStyleWindow, , "Styl okna"
End Sub

Styl okna MS Access
Opisowy styl okna MS Access

 

Pobierz Do pobrania:Opisowy styl okna pobrano ()