|
| | | |
• I.2. Access - Tabele i kwerendy [2] •
- 2.1 Jak policzyć rekordy w tabeli ?
- 2.2 Jak sprawdzić, czy istnieje tabela ?
- 2.3 Jak sprawdzić, czy istnieje pole w tabeli ?
- 2.4 Jak dodać pole do tabeli bazowej lub tabeli połączonej ?
- 2.5 Jak zmienić nazwę pola w tabeli bazowej lub tabeli połączonej ?
- 2.6 Jak wywołując funkcję DLookup przekazać kwerendzie parametr ?
- 2.7 Dlaczego kwerenda wywołuje => Błąd wykonania '3061' Za mało parametrów. Oczekiwano np. 2 ?
- 2.8 Czy można odzyskać usuniętą przez pomyłkę tabelę ?
- 2.9 Jak obliczyć średnią liczb z 2 lub więcej pól tego samego rekordu ?
- 2.10 Jak ukryć tabelę, by nie była widoczna w oknie bazy (nawet po ustawieniu w menu Narzędzia/Opcje/Widok/Pokaż obiekty ukryte(systemowe) = True ?
- 2.11 Jak pobrać współrzędne kursora myszy nad oknem tabeli (kwerendy) poza obszarem danych ?
- 2.12 Jak sprawdzić czy zdarzenie MouseUp kwerendy, zainicjowane zdarzeniem MouseDown nad nagłówkiem kolumny lub selektorem rekordów, zaszło nad obszarem danych ?
- 2.13 Jak sprawdzić, czy tabela lub kwerenda otwarta jest w widoku Arkusz danych (DataSheet), a formularz lub raport nie jest w widoku Projekt (DesignView) ?
| | | | |
|
| | |
|
2.12 Jak sprawdzić czy zdarzenie MouseUp kwerendy, zainicjowane zdarzeniem MouseDown nad nagłówkiem kolumny lub selektorem rekordów, zaszło nad obszarem danych ?

Jest to próba odpowiedzi na problem poruszony w wątku: Przechwytywanie zdarzeń tabel/kwerend (czyżby ostatnia wersja ?) dotyczący przechwytu zdarzenia MouseUp.
Otóż, jeżeli wciśniemy lewy przycisk myszy w oknie formularza w widoku Datasheet nad nagłówkiem kolumny, selektorem rekordów, nad kwadratem w lewym górnym rogu lub obszarem okna gdzie nie ma danych, to zachodzi zdarzenie Form_MouseUp.
I wydaje się oczywiste, że zdarzenie Form_MouseUp wystąpi zawsze, gdy puścimy lewy przycisk myszy (nawet poza obszarem formularza). Ale niestety, tak nie jest. Zdarzenie Form_MouseUp nie zachodzi nad obszarem danych. I w przykładzie chodzi o przechwycenie zdarzenia Form_MouseUp nad obszarem danych.
Dodatkowo potrzebna jest informacja, czy zdarzenie Form_MouseUp zaszło w formularzu. Jeżeli zaszło zdarzenie, to w funkcji przechwytujacej nie robimy nic, jeżeli nie to coś tam musimy wykonać. "Dowiadujemy się" o tym uruchamiając po przechwyceniu komunikatu w formularzu kwerendy Timer, w którym następuje zmiana stanu publicznej zmiennej fHoook.
Jak się okazało moje twierdzenie że : gdy puścimy lewy przycisk myszy poza obszarem formularza to zajdzie zdarzenie Form_MouseUp nie jest prawdziwe.
Cytuję wypowiedź Krzysztof Pozorka:
<cyt>
Troche jednak te komunikaty w tytule okna nie zawsze sa trafne. Np taki scenariusz:
Klikam naglowek kolumny -> MouseUp poza obszarem danych
Klikam myszka poza oknem -> MouseUp nad obszarem danych
Czyli w pierwszej czesci rozpoznal dobrze, ale pozniejsze klikniecie poza
obszarem daje informacje, ze MouseUp wystapilo nad obszarem. Z punktu
widzenia uzytkownika to nie jest prawda.
A swoja droga to zwarta realizacja przechwytu zdarzen myszki. Mozna by
powiedziec, ze bardzo dydaktyczna, gdyby... nie oszczednosc komentarzy;-)
</cyt>
I okazuje się, że jeżeli kursor myszy po naciśnięciu przycisku myszy ma postać strzałki (domyślny kształt) to po przeciągnięciu kursora poza obszar okna i puszczeniu przycisku nie jest generowane zdarzenie Form_MouseUp.
Aby wiedzieć, z jakim kursorem mamy do czynienia pobieram uchwyt kursora przed otwarciem kwerendy i sprawdzam w zdarzeniu Form_MouseDown, czy aktualny uchwyt kursora jest zgodny z wcześniej pobranym. Jeżeli jest taki sam, to sprawdzam czy Form_MouseDown było nad kwadratem w górnym lewym rogu (tym co zaznacza wszystkie rekordy). Jeżeli tak to kończymy, jeżeli nie, to uruchamiamy przechwyt komunikatów myszy.
ΔΔΔ | | | | |
|
| | |
|
2.13 Jak sprawdzić, czy tabela lub kwerenda otwarta jest w widoku Arkusz danych (DataSheet), a formularz lub raport nie jest w widoku Projekt (DesignView) ?
Najpierw za pomocą funkcji SysCmd z argumentem acSysCmdGetObjectState sprawdzamy, czy dany obiekt jest otwarty:
ObjectState = SysCmd(acSysCmdGetObjectState, typ_obiektu, nazwa_obiektu)
gdzie:
typ_obiektu: acTable, acQuery, acForm, acReport, acMacro, acModule
Funkcja zwraca dowolną kombinację trzech poniższych stałych:
acObjStateOpen - otwarty
acObjStateNew - nowy
acObjStateDirty - zmodyfikowany, ale nie zapisany
Jeżeli obiekt, do którego odwołuje się argument nazwa_obiektu nie jest otwarty lub nie istnieje, funkcja SysCmd zwraca wartość ZERO.
Jeżeli ObjectState = 0 to wiemy, że obiekt nie jest otwarty, lub nie istnieje. W przeciwnym wypadku musimy sprawdzić, czy tabela lub kwerenda jest w widoku Arkusz Danych. Możemy to zrobić znajdując kolejno okna dzieci w oknie klasy "MDIClient" . Poszukiwane okna posiadają klasę "OTable" lub "OQry". Po znalezieniu okna sprawdzamy, czy tytuł tego okna zawiera nazwę naszego poszukiwanego obiektu.
Jeżeli tak, to sprawdzamy, czy jest widoczne okno dziecko klasy "OSUI" (te nad dolną krawędzią okna, służące do nawigcji pomiędzy rekordami). Jeżeli jest widoczne to tabela lub kwerenda jest w widoku Arkusz Danych (DataSheet).

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
Declare Function IsWindowVisible Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function GetParent Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long

' pobiera nazwę obiektu i jego typ,
' dla tabeli lub kwerendy zwraca TRUE jeżeli jest otwarta w widoku Arkusz danych,
' dla formularzu i raportu zwraca TRUE nie jest otwarty w widoku "Projekt",
' dla makra i modułu zwraca TRUE nie jest on otwarty.

Public Function zbIsObjLoaded( _
sObjName As String, _
lObjType As Long) As Boolean
Dim hObj As Long
Dim sObjTitle As String
Dim hWind As Long
Dim lSepInObjName As Long
Dim lSepInTitle As Long
Dim sClassName As String
Const MY_FORM_DESIGN_VIEW = 0
Const MY_OBJECT_CLOSED = 0
Const MY_SEP_NAME As String = " : "
Select Case lObjType
' sprawdź, czy argument lObjType ma prawidłową wartość
Case acTable, acQuery, acForm, acReport, acMacro, acModule
If SysCmd(acSysCmdGetObjectState, _
lObjType, sObjName) = MY_OBJECT_CLOSED Then
Exit Function
End If
Case Else
Err.Raise vbObjectError + 1, "Function zbIsObjLoaded ()", _
"Nieprawidłowa wartość parametru 'lObjType'"
End Select
Select Case lObjType
Case acTable, acQuery
' ustaw nazwę klasy poszukiwanego okna
If lObjType = acTable Then
sClassName = "OTable"
Else
sClassName = "OQry"
End If
' szukaj okna rodzica dla wszystkich okien Tabel i Kwerend
hWind = FindWindowEx(Application.hWndAccessApp, _
ByVal 0&, "MDIClient", vbNullString)
Do
' szukaj okna Tabeli (Kwerendy) klasy: sClassName
hObj = FindWindowEx(hWind, ByVal hObj, _
sClassName, vbNullString)
If hObj > 0 Then
' pobierz tytuł okna tabeli, kwerendy
sObjTitle = zbGetTextWind(hObj)
' szukaj od tyłu ciągu " : "
lSepInObjName = InStrRev(sObjName, _
MY_SEP_NAME, , vbBinaryCompare)
lSepInTitle = InStrRev(sObjTitle, _
MY_SEP_NAME, , vbBinaryCompare)
'w nazwie nie ma " : "
' Access 2007 w oknie tabeli i kwerendy nie dopisuje
' po nazwie obiektu ciągu " : Tabela" lub " : Kwerenda"
' Przytnij nazwę do ostatniego wystąpienia " : " za nazwą sObjName
If lSepInObjName = 0 Then
If lSepInTitle > 0 Then
sObjTitle = Left$(sObjTitle, lSepInTitle - 1)
End If
Else
If lSepInTitle > lSepInObjName Then
sObjTitle = Left$(sObjTitle, lSepInTitle - 1)
End If
End If
' porównaj tytuł okna z wzorcem: sObjName
If StrComp(sObjTitle, sObjName, vbTextCompare) = 0 Then
' szukaj okna z przyciskami nawigacyjnymi
hWind = FindWindowEx(hObj, ByVal 0&, "OSUI", vbNullString)
zbIsObjLoaded = CBool(IsWindowVisible(hWind))
Exit Function
End If
End If
Loop Until hObj = 0
Case acForm
If Forms(sObjName).CurrentView <> MY_FORM_DESIGN_VIEW Then
zbIsObjLoaded = True
End If
Case acReport
' spróbuj pobrać właściwość dostępną tylko w widoku acPreviw
On Error Resume Next
zbIsObjLoaded = CBool(Reports(sObjName).Page)
On Error GoTo 0
Case acMacro, acModule
zbIsObjLoaded = True
End Select
End Function

' funkcja pomocnicza zwracająca tytuł okna o uchwycie hWind,
Private Function zbGetTextWind(hWind As Long, _
Optional lMaxSizeBuffer As Long = 256) As String
Dim sBff As String
Dim lRet As Long
sBff = String(lMaxSizeBuffer, vbNullChar)
lRet = GetWindowText(hWind, sBff, lMaxSizeBuffer)
zbGetTextWind = Left$(sBff, lRet)
End Function
ΔΔΔ | |
| | |
|
| |