• Czy w 64-bitowym VBA 7 właściwość Me.hwnd jest liczbą typu LongLong ?
Z artykułu VBA 7.0 i MS Access 2010+ wiemy, że w 32-bitowym środowisku wszystkie
uchwyty i wskaźniki są liczbą typu Long, a w środowisku 64-bitowym liczbą typu LongLong. W celu ułatwienia pisanie przenośnego kodu wprowadzono
w środowisku VBA 7 nową liczbę typu LongPtr, która przyjmuje w 32-bitowym środowisku typ Long (liczba 4 bajtowa),
a w 64-bitowej wersji typ LongLong (8 bajtowa liczba).
Przypisanie uchwytu lub wskaźnika w środowisku 64-bitowym do zmiennej typu Long jest niepoprawne i może prowadzić do nieprzewidzianych błędów,
ponieważ 64-bitowy uchwyt lub wskaźnik może zostać „ucięty” do wartości 32-bitowej i wskazywać na nieprawidłowy obiekt.
Piszę, „może zostać ucięty”, gdyż w przypadku nieprzekroczenia przez uchwyt zakresu liczby Long, nie zmieni on wartości przy przypisaniu
do zmiennej typu Long.
• Jak przekazać uchwyt hwnd w 32-bitowej i 64-bitowej wersji MS Access 2010+ ?
Napiszmy prostą przykładową funkcję by pobrać i przypisać do zmiennej hWind uchwyt hwnd okna formularza MS Access
i odczytać jego tytuł za pomocą funkcji API GetTextWindow(...).
#If VBA7 Then Private Declare PtrSafe Function GetWindowText Lib "user32" _ Alias "GetWindowTextA" ( _ ByVal hwnd As LongPtr, _ ByVal lpString As String, _ ByVal cch As Long) As Long #Else Private Declare Function GetWindowText Lib "user32" _ Alias "GetWindowTextA" ( _ ByVal hwnd As Long, _ ByVal lpString As String, _ ByVal cch As Long) As Long #End If #If VBA7 Then Private Function GetFormCaption(hWind As LongPtr) As String #Else Private Function GetFormCaption(hWind As Long) As String #End If Dim lRet As Long Dim sBuffer As String Const conSize_Buffer = 256 ' przygotuj buffor na przyjęcie tytułu okna sBuffer = String(conSize_Buffer, vbNullChar) ' pobierz do bufora tytuł okna i zwróć ilość pobranych znaków lRet = GetWindowText(hWind, sBuffer, conSize_Buffer) GetFormCaption = Left$(sBuffer, lRet) End Function ' przykładowe wywołanie Private Sub btnTest_Click() ' ustaw nowy tytuł formularza Me.Caption = "Nowy tytuł formularza" ' odczytaj tytuł formularza MsgBox GetFormCaption(Me.hwnd) End Sub
Po uruchomieniu kodu pojawia się okno komunikatu:
Wszystko się zgadza. Odczytany tytuł formularza jest taki sam, jaki został ustawiony za pomocą właściwości:Me.Caption = "Nowy tytuł formularza"
Praktycznie w tym miejscu, w poczuciu dobrze spełnionego obowiązku, powinienem zakończyć ten artykuł. Jednakże przeprowadzę jeszcze jeden malutki test odnośnie typu uchwytu hwnd. Zgodnie z wszystkimi wytycznymi Microsoftu uchwyt w 64-bitowym środowisku powinien być 8-bajtową liczbą typu LongLong, a w 32-bitowym środowisku 4-bajtową liczbą typu Long. Do sprawdzenia typu zmiennej użyję funkcji VarType( varname ), która dla zmiennej typu LongLong zwraca wartość vbLongLong = 20, a dla zmiennej typu Long zwraca wartość vbLong = 3 i tylko te dwa typy będą uwzględnione w procedurze testowej.
Private Sub GetTypeHwnd() #If VBA7 Then Dim hWind As LongPtr #Else Dim hWind As Long #End If Dim sRet As String 'sprawdź typ zmiennej hWind sRet = sRet & "Zmienna hWind jest typu: " & _ IIf(VarType(hWind) = vbLongLong, "LongLong", "Long") sRet = sRet & vbNewLine & vbNewLine ' sprawdź typ uchwytu okna sRet = sRet & "Uchwyt Me.hwnd jest typu: " & _ IIf(VarType(Me.hwnd) = vbLongLong, "LongLong", "Long") MsgBox sRet End Sub
Znowu ZONK ! Co widać na poniższym oknie komunikatu:
Zmienna hWind jest typu LongLong, bo tak została zadeklarowana:
Dim hWind As LongPtr
Ale dlaczego właściwość Me.hwnd jest liczbę typu Long w 64-bitowym VBA 7.0 ? Aby odpowiedzieć na to pytanie wystarczy spojrzeć na deklarację tej właściwości w oknie „Object Browser”
Property Hwnd As LongProblem ten dotyczy także metody Application.hWndAccessApp, która ma postać:
Function hWndAccessApp() As Longi w 64-bitowym środowisku VBA 7.0 zwróci uchwyt okna MS Access jako liczbę typu Long zamiast liczby typu LongLong.
Brak komentarzy:
Prześlij komentarz