Rozdział z książki "Visual Basic 6 - księga eksperta". © 1999 Wydawnictwo Helion

Rozdział 8.
Konsumenci danych
i źródła danych

Rob Thayer

Wprowadzenie

VB6 umożliwia tworzenie kontrolek ActiveX, które działają jako konsumenci i źródła danych. Konsument może być związany ze źródłem danych. Na przykład kontrolka TextBox może być związana z kontrolką Data poprzez odpowiednie ustawienie właściwości DataSource i DataField. Tworzone przez Ciebie kontrolki ActiveX, będące konsumentami danych, mogą działać w ten sam sposób.

Kontrolka pełniąca rolę źródła danych dostarcza interfejsu umożliwiającego dostęp do bazy danych. Na przykład kontrolka ADO Data funkcjonuje jako źródło danych i pozwala na poruszanie się po zestawie rekordów za pomocą przycisków umieszczonych na kontrolce. Baza danych i zestaw rekordów, które mają zostać użyte, są definiowane we właściwościach ConnectionString i RecordSource kontrolki. Można stowarzyszyć z kontrolką ADO Data kilka innych kontrolek, a wówczas ich zawartość będzie automatycznie uaktualniana przy każdej zmianie bieżącego rekordu z zestawu rekordów kontrolki ADO Data.

W tym rozdziale zobaczysz jak się tworzy własnych konsumentów danych oraz własne źródła danych. Poligonem doświadczalnym będzie prosta kontrolka, którą zbudujesz, skompilujesz i zastosujesz we własnych aplikacjach zamiast kontrolki ADO Data.

W VB6 możesz tworzyć źródła danych jako komponenty ActiveX DLL oraz ActiveX EXE korzystające z klas. Te typy źródeł danych nie będą w książce omawiane.

Tworzenie źródła danych

Jak zobaczysz, stworzenie kontrolki ActiveX, która działa jako źródło danych to sprawa prosta. Przede wszystkim jednak musisz rozumieć sam proces tworzenia kontrolki. Zanim przejdziesz do szczegółowej tematyki tego rozdziału, sugeruję, abyś raz jeszcze przeczytał rozdział 5., "Tworzenie kontrolek ActiveX".

Budowana przez nas w tym rozdziale kontrolka wygląda podobnie jak ADO Data, aczkolwiek jest nieco inaczej używana. Zamiast obszaru tekstowego, w którym pojawia się nazwa kontrolki, i dwóch przycisków umożliwiających przemieszczanie się pomiędzy rekordami, stosowany jest poziomy pasek przewijania. Oprócz tego, że przyciski paska przewijania mogą pełnić rolę przycisków przechodzenia do kolejnych rekordów zestawu, sam pasek przewijania umożliwia płynną zmianę aktualnej pozycji. Dwa przyciski (Command Button), podobnie jak w kontrolce ADO Data, pozwalają użytkownikowi jednym krokiem przejść do pierwszego lub ostatniego rekordu.

Nazwiemy tę kontrolkę ScrollData (i zapiszemy jako ScrData) – co jest akronimem nazwy Scrolling Data Control.

Zadbamy o prostotę interfejsu kontrolki, aby jej konstrukcja była zrozumiała. Zbudujemy go z pięciu właściwości i trzech metod – nie będziemy stosować zdarzeń.

Tabela 8.1 prezentuje listę właściwości i metod, z których będziemy korzystać, wraz z krótkimi opisami.

Tabela 8.1. Właściwości i metody kontrolki ScrollData
Nazwa Właściwość/Metoda Opis
BOFAction Właściwość Określa działanie, które ma być podjęte w przypadku wystąpienia warunku BOF (Beginning of File; początek pliku)
ConnectionString Właściwość Łańcuch łączący używany w celu połączenia z bazą danych
EOFAction Właściwość Określa działanie, które ma być podjęte w przypadku wystąpienia warunku EOF (End of File; koniec pliku)
LargeChange Właściwość Liczba rekordów, które mają być przeskoczone w przypadku kliknięcia na pasku przewijania
RecordSource Właściwość Nazwa źródła rekordów (np. nazwa tablicy)
MoveFirst Metoda Powoduje przejście do pierwszego rekordu zestawu
MoveLast Metoda Powoduje przejście do ostatniego rekordu zestawu
MoveToRecord Metoda Powoduje przejście do rekordu zestawu o wyspecyfikowanym numerze

Właściwości ConnectionString oraz RecordSource są łańcuchami, a właściwości BOFAction i EOFAction korzystają z typu wyliczeniowego – tak więc za pośrednictwem okna Property kontrolki można im przypisać tylko określone wartości. Właściwość LargeChange jest przesyłana bezpośrednio do paska przewijania i jest wartością typu Integer.

W zwykłych okolicznościach wolałbyś rozszerzyć możliwości kontrolki, dodając do jej interfejsu więcej właściwości, metod i zdarzeń. Ta prosta kontrolka może jednak stanowić punkt wyjścia dla znacznie bardziej skomplikowanego projektu. Pamiętaj jednak, że w przypadku tworzenia kontrolek prostota to cnota – a szczególnie dotyczy to kontrolek danych.

Zanim rozpoczniesz prace nad tym projektem, musisz upewnić się, że są ustanowione referencje do biblioteki ADO Object Library. W menu Project okna VB wybierz pozycję References. Na liście możliwych referencji sprawdź, czy zaznaczono pole wyboru obok pozycji Microsoft ActiveX Data Objects 2.0 Library. Jeśli pole jest czyste, umieść w nim znacznik.

Budowanie interfejsu użytkownika kontrolki

Jak w przypadku wszystkich innych projektów, tworzenie kontrolki DataScroll musisz rozpocząć od zbudowania jej interfejsu użytkownika. Będzie to raczej prosty interfejs składający się z poziomego paska przewijania i pary przycisków. Pozycje tych elementów nie są istotne, ponieważ wszystko zostanie automatycznie rozmieszczone w zdarzeniu Resize kontrolki. Ważne są natomiast rozmiary pewnych elementów, ponieważ zostaną wykorzystane do określenia domyślnego rozmiaru kontrolki.

W budowie interfejsu pomogą Ci tabela 8.2 oraz rysunek 8.1 – dowiesz się z nich jakie kontrolki składowe należy dodać do obiektu UserControl i jak zmienić ich właściwości. Pliki FIRST.BMP i LAST.BMP, które są stosowane z obiema kontrolkami ControlButton, znajdziesz w podkatalogu SAMPLES\AXDATA.

Jedynie właściwość DataSourceBehavior kontrolki UserControl wymaga szerszego omówienia, jako nowość w VB6. Przypisanie jej wartości vbDataSource to jeden z podstawowych kroków w kierunku przekształcenia jej w kontrolkę źródła danych. Powoduje to dodanie do obiektu UserControl zdarzenia GetDataMember, co umożliwia kontrolce interakcję z bazą danych. W dalszej części rozdziału zobaczysz jak zdarzenie to jest stosowane.

Jak już wspomniano, dokładne rozmieszczenie kontrolek składowych na obiekcie UserControl zostanie przeprowadzone automatycznie w zdarzeniu Resize.

Wydruk 8.1 pokazuje kod, który należy dodać do procedury obsługi tego zdarzenia.

Rysunek 8.1.

Interfejs użytkownika dla kontrolki ScrollData

Tabela 8.2. Właściwości kontrolki UserControl i kontrolek składowych wykorzystywane do budowy interfejsu kontrolki DataScroll

Typ kontrolki Właściwość Wartość

UserControl Name ScrollData
  DataSourceBahavior 1 - vbDataSource
  Height 3600
  Width 4110

CommandButton Name cmdFirst
  AutoSize True
  Caption (nic)
  Left 240
  Picture FIRST.BMP
  Style 1 – Graphical
  Top 1080

HScrollBar Name hsbRecScroll
  Height 255
  LargeChange 10
  Left 600
  Min 1
  Top 1000

HScrollBar Value 1
  Width 3135

CommandButton Name cmdLast
  AutoSize True
  Caption (nic)
  Left 3840
  Picture LAST.BMP
  Style 1 – Graphical
  Top 1080

Zdarzenie Resize zachodzi, gdy kontrolka zostaje zainicjowana, lub gdy użytkownik zmienia jej rozmiary. Choć wysokość kontrolki się nie zmienia (głównie z tego powodu, by nie zniekształcić obrazów na przyciskach), jej szerokość może być dopasowywana dowolnie. Oba przyciski pozostaną w ustalonym miejscu, ale rozmiar paska przewijania zmieni się wraz z rozmiarem kontrolki.

Wydruk 8.1. R08W01.txt – zdarzenie UserControl_Resize rozmieszcza kontrolki składowe w obrębie obiektu UserControl
Private Sub UserControl_Resize()
' Przesuń kontrolki składowe
' i zmień ich rozmiary.
cmdFirst.Move 0, 15
hsbRecScroll.Move cmdFirst.Width, 0, _
    UserControl.Width - cmdFirst.Width - cmdLast.Width, _
    cmdFirst.Height + 15
cmdLast.Move cmdFirst.Width + hsbRecScroll.Width, 15

' Zmień rozmiar kontrolki użytkownika.
UserControl.Height = cmdFirst.Height + 15
UserControl.Width = cmdFirst.Width _
    + hsbRecScroll.Width + cmdLast.Width

End Sub

Zanim przejdziemy dalej, zapiszmy kontrolkę na dysku. Najpierw wyświetl okienko dialogowe Project Properties (wybierając pozycję Project Properties z menu Project) i zmień nazwę projektu na ScrData, a w polu Project Description wpisz Scrolling Data Control. Zapisz teraz kontrolkę jako ScrollData.ctl, a projekt jako ScrData.vbp.

Dodawanie właściwości

Kolejnym etapem tworzenia kontrolki ScrollData jest dodanie właściwości. Najpierw musisz jednak zadeklarować pewne zmienne, które będą przechowywać wartości właściwości. Warto zdefiniować kilka stałych, w których przechowywane będą wartości domyślne właściwości. Odpowiedni kod przedstawiony jest na wydruku 8.2. Należy go dodać do sekcji General Declarations obiektu UserControl.

Wydruk 8.2. R08W02.txt – deklaracje zmiennych i stałych (i nie tylko). Należy je dodać do sekcji General Declarations obiektu UserControl
' Wartości dla właściwości BOFAction.
Public Enum sdcBOFActionConstants
    sdcMoveFirst = 0
    sdcStayAtBOF
End Enum

' Wartości dla właściwości EOFAction.
Public Enum sdcEOFActionConstants
    sdcMoveLast = 0
    sdcStayAtEOF
    sdcAddNewRecord
End Enum

' Deklaracja zmiennych ADO (obiekty zestaw rekordów 
' i połączenie).
Private cnMain As ADODB.Connection
Private WithEvents rsMain As ADODB.RecordSet

' Domyślne wartości właściwości.
Const DefaultBOFAction = sdcBOFActionConstants.sdcMoveFirst
Const DefaultEOFAction = sdcEOFActionConstants.sdcMoveLast
Const DefaultConnectionString = ""
Const DefaultLargeChange = 10
Const DefaultRecordSource = ""

' Zmienne przechowujące właściwości.
Private msdcBOFAction As sdcBOFActionConstants
Private msdcEOFAction As sdcEOFActionConstants
Private mstrConnectionString As String
Private mstrRecordSource As String

W kodzie przedstawionym na wydruku 8.2 są dwa wyliczenia, które są stosowane z właściwościami BOFAction oraz EOFAction. Umożliwiają one użytkownikowi wybranie wartości właściwości z listy, co zmniejsza ewentualność przypisania niepoprawnej wartości. Kod zawiera także deklaracje dla obiektów ADO Connection i Recordset, które będą potrzebne później.

Wszystkie właściwości w interfejsie kontrolki korzystają z procedur Property LetProperty Get. Aby zaoszczędzić sobie wpisywania kodu, możesz zlecić środowisku VB dodanie tych procedur – wystarczy, że wybierzesz z menu Tools pozycję Add Procedure, a w polu Name pojawiającego się okienka dialogowego wpiszesz nazwę właściwości. Musisz pamiętać o wybraniu typu (Type) Property i zakresu (Scope) Public. Po naciśnięciu przycisku OK, procedury zostaną dodane.

Dodając procedury automatycznie lub wpisując je ręcznie powinieneś zwracać baczną uwagę na wyrażenia deklarujące procedur. Muszą one zawierać poprawne nazwy argumentów i właściwe typy danych.

Wydruk 8.3 prezentuje kod procedur, które należy dodać.

Wydruk 8.3. R08W03.txt – właściwości kontrolki są implementowane za pomocą procedur Property Let i Property Get
Public Property Get BOFAction() As sdcBOFActionConstants

' Zwraca wartość właściwości BOFAction.
BOFAction = msdcBOFAction

End Property


Public Property Let BOFAction(ByVal NewValue As sdcBOFActionConstants)

' Przechowuje nową wartość dla właściwości BOFAction.
msdcBOFAction = NewValue
UserControl.PropertyChanged "BOFAction"

End Property


Public Property Get EOFAction() As sdcEOFActionConstants

' Zwraca wartość właściwości EOFAction.
EOFAction = msdcEOFAction

End Property


Public Property Let EOFAction(ByVal NewValue As sdcEOFActionConstants)

' Przechowuje nową wartość dla właściwości EOFAction.
msdcEOFAction = NewValue
UserControl.PropertyChanged "EOFAction"

End Property


Public Property Get LargeChange() As Integer

' Zwraca wartość właściwości LargeChange,
' która jest taka sama jak wartość właściwości
' LargeChange kontrolki hsbRecScroll.

LargeChange = hsbRecScroll.LargeChange

End Property


Public Property Let LargeChange(ByVal NewValue As Integer)

' Zapisuje nową wartość właściwości LargeChange 
' bezpośrednio w właściwości LargeChange kontrolki
' hsbRecScroll.
hsbRecScroll.LargeChange = NewValue
UserControl.PropertyChanged "LargeChange"

End Property


Public Property Get ConnectionString() As String

' Zwraca wartość właściwości ConnectionString.
ConnectionString = mstrConnectionString

End Property


Public Property Let ConnectionString(ByVal NewValue As String)

' Przechowuje nową wartość dla właściwości 
' ConnectionString. Dodatkowe spacje na początku
' lub na końcu łańcucha są usuwane.

mstrConnectionString = Trim$(NewValue)
UserControl.PropertyChanged "ConnectionString"

End Property


Public Property Get RecordSource() As String

' Zwraca wartość właściwości RecordSource.
RecordSource = mstrRecordSource

End Property


Public Property Let RecordSource(ByVal NewValue As String)

' Przechowuje nową wartość dla właściwości RecordSource.
' Dodatkowe spacje na początku
' lub na końcu łańcucha są usuwane.

mstrRecordSource = Trim$(NewValue)
UserControl.PropertyChanged "RecordSource"

End Property

Konieczna jest jeszcze jedna procedura właściwości, ale jest to tylko procedura Property Get, bez odpowiadającej jej procedury Property Let.

Wynika to z tego, że właściwość jest tylko do odczytu (read-only). Zwraca ona nazwę obiektu Recordset, który jest używany przez kontrolkę. Obiekt ten był deklarowany w sekcji General Declarations i nazywa się rsMain. Dodaj procedurę korzystając z wydruku 8.4.

W celu zaimplementowania właściwości konieczne są także procedury obsługi zdarzeń InitProperties, ReadProperties i WriteProperties. Procedura InitProperties dokonuje inicjalizacji wartości właściwości, korzystając z wartości domyślnych zdefiniowanych jako stałe w sekcji General Declarations – jest ona wywoływana w trakcie tworzenia kontrolki. Zdarzenia ReadProperties i WriteProperties czytają i zapisują wartości właściwości z i do przechowalni właściwości.

Kod dla tych trzech procedur podany jest na wydruku 8.5.

Wydruk 8.4. R08W04.txt – procedura Property Get zwraca nazwę obiektu Recordset używanego przez kontrolkę
Public Property Get RecordSet() As ADODB.RecordSet

' Zwróć odnośnik do obiektu RecordSet,
' który jest używany przez kontrolkę.
Set RecordSet = rsMain

End Property
Wydruk 8.5. R08W05.txt – procedury zdarzeń InitProperties, ReadProperties i WriteProperties
Private Sub UserControl_InitProperties()

' Przypisz właściwościom ich wartości domyślne.
msdcBOFAction = DefaultBOFAction
msdcEOFAction = DefaultEOFAction
mstrConnectionString = DefaultConnectionString
mstrRecordSource = DefaultRecordSource

' Przypisz właściwości hsbRecScroll.LargeChange 
' wartość domyślną.
hsbRecScroll.LargeChange = DefaultLargeChange

End Sub


Private Sub UserControl_ReadProperties(PropBag As PropertyBag)

' Czytaj wartości właściwości z przechowalni właściwości.
msdcBOFAction = PropBag.ReadProperty("BOFAction", _
    DefaultBOFAction)
msdcEOFAction = PropBag.ReadProperty("EOFAction", _
    DefaultEOFAction)
mstrConnectionString = PropBag.ReadProperty("ConnectionString", _
    DefaultConnectionString)
mstrRecordSource = PropBag.ReadProperty("RecordSource", _
    DefaultRecordSource)
hsbRecScroll.LargeChange = PropBag.ReadProperty("LargeChange", _
    DefaultLargeChange)

End Sub


Private Sub UserControl_WriteProperties(PropBag As PropertyBag)

' Zapisz wartości właściwości w przechowalni właściwości.
Call PropBag.WriteProperty("BOFAction", _
    msdcBOFAction, DefaultBOFAction)
Call PropBag.WriteProperty("EOFAction", _
    msdcEOFAction, DefaultEOFAction)
Call PropBag.WriteProperty("ConnectionString", _
    mstrConnectionString, DefaultConnectionString)
Call PropBag.WriteProperty("RecordSource", _
    mstrRecordSource, DefaultRecordSource)
Call PropBag.WriteProperty("LargeChange", _
    hsbRecScroll.LargeChange, DefaultLargeChange)
    
End Sub

Zwróć uwagę, że w kodzie zdarzenia InitProperties domyślna wartość właściwości LargeChange nie jest przechowywana – jest natomiast przekazywana bezpośrednio do kontrolki hbsRecScroll.

Próba kontrolki

Po skonfigurowaniu właściwości kontrolki, możesz ją wypróbować, aby zobaczyć jak wygląda na formatce. W tym celu musisz dodać nowy projekt do swej sesji VB. W menu File okna VB wybierz pozycję Add Project. Gdy pojawi się okienko dialogowe, wybierz opcję Standard EXE i naciśnij OK. Spowoduje to dodanie do grupy standardowego projektu (Project2).

W oknie Project Explorer wskaż Project2, naciśnij prawy klawisz myszki i wybierz z menu kontekstowego pozycję Set as Start Up. Sprawi to, że ten właśnie projekt będzie wykonywany po naciśnięciu przycisku Run lub klawisza F5.

Zapisz wszystkie projekty wybierając z menu File pozycję Save Project Group. W przypadku projektu Project2 zapisz formatkę jako ScrDataTest.frm, a projekt jako ScrDataTest.vbp. Grupę projektów zapisz jako ScrDataTest.vbg.

Przejdź do formatki projektu Project2 i dodaj kontrolkę ScrData – jej ikona powinna być wyświetlana w przyborniku jako ostatnia. Pamiętaj, że zanim przejdziesz do projektu Project2, najpierw musisz zamknąć okno projektowe dla projektu kontrolki. W przeciwnym wypadku kontrolka będzie niedostępna.

Jeśli zdarzenie Resize działa poprawnie, powinieneś zobaczyć instancję kontrolki ScrData, która przypomina tę rysunku 8.2.

Rysunek 8.2.

Instancja kontrolki ScrData – zauważ, że różne komponenty kontrolki zostały rozmieszczone automatyczne dzięki zdarzeniu Resize

Implementacja obsługi bazy danych

Po wypróbowaniu kontrolki i stwierdzeniu poprawnego działania zdarzenia Resize, czas powrócić do projektu kontrolki i dodać kod, który umożliwi kontrolce realizację jej zadań. W przypadku kontrolki ScrData oznacza to dodanie obsługi baz danych. Dla obiektów UserControl główny ciężar tej obsługi spoczywa na zdarzeniu GetDataMember, o którym wspominaliśmy na początku. Wydruk 8.6 prezentuje kod dla tego zdarzenia.

Wydruk 8.6. R08W06.txt – zdarzenie GetDataMember to główny element obsługi baz danych w kontrolce
Private Sub UserControl_GetDataMember(DataMember As String, _
    Data As Object)

    On Error GoTo ErrorHandler

    If (cnMain Is Nothing) Or (rsMain Is Nothing) Then
        ' Jeśli nie wskazano właściwości ConnectionString,
        ' wykaż błąd i wyjdź z procedury.
        If mstrConnectionString = "" Then
            MsgBox "Please specify a value for the " _
                & "ConnectionString property.", _
                vbInformation, Ambient.DisplayName
            Exit Sub
        End If
        ' Jeśli nie wskazano właściwości RecordSource,
        ' wykaż błąd i wyjdź z procedury.
        If mstrRecordSource = "" Then
            MsgBox "Please specify a value for the " _
                & "RecordSource property.", _
                vbInformation, Ambient.DisplayName
            Exit Sub
        End If
        ' Skonfiguruj połączenie ADO 
        ' korzystając z wartości 
        ' właściwości ConnectionString.
        Set cnMain = New ADODB.Connection
        cnMain.ConnectionString = mstrConnectionString
        cnMain.Open
        ' Skonfiguruj zestaw rekordów ADO 
        ' korzystając z wartości określonej dla 
        ' właściwości RecordSource.
        Set rsMain = New ADODB.RecordSet
        rsMain.Open mstrRecordSource, cnMain, _
            adOpenKeyset, adLockPessimistic
        rsMain.MoveFirst
        ' Określ górne ograniczenie wartości
        ' kontrolki hsbRecScroll jako liczbę rekordów
        ' w zestawie (plus jeden na dodanie rekordu).
        hsbRecScroll.Max = rsMain.RecordCount + 1
    Else
        Set cnMain = Nothing
        Set rsMain = Nothing
    End If
    
    ' Zwróć zestaw rekordów w argumencie Data.
    Set Data = rsMain
    
    Exit Sub

ErrorHandler:
    ' Wystąpił błąd, więc wyświetl komunikat
    ' i wyjdź z procedury.
    MsgBox "Error: " & CStr(Err.Number) _
        & vbCrLf & Err.Description, vbOKOnly, _
        Ambient.DisplayName
    
End Sub

Pierwsza rzecz, która rzuca się w oczy w przypadku tej procedury, to dodana do niej prymitywna obsługa błędu. Usiłując ustanowić połączenie z bazą danych możesz mieć do czynienia z różnymi problemami, ważne jest więc, aby zaimplementować jakąkolwiek procedurę obsługi błędu.

Najpierw kod sprawdza, czy przypisano obiekty Connection i Recordset (cnMainrsMain), oraz czy przypisano właściwościom ConnectionString i RecordSource wartości typu String. Jeśli warunki te nie zostały spełnione, wyświetlany jest komunikat o błędzie i procedura jest zakańczana.

W przypadku, gdy wszystko jest w porządku, nawiązywane jest połączenie z bazą danych przy wykorzystaniu zmiennej mstrConnectionString przechowującej wartość ConnectionString. Jeśli nie pojawi się błąd, zestaw Recordset jest otwierany przy wykorzystaniu zmiennej mstrRecordSource przechowującej wartość dla właściwości RecordSource. Jeśli nadal nie ma komplikacji, właściwości Max kontrolki składowej hsbRecScroll przypisywana jest liczba wszystkich rekordów w zestawie RecordSet.

Zanim procedura zakończy działanie, argumentowi Data procedury przypisywany jest wskaźnik do zestawu RecordSet (rsMain). Możesz umożliwić kontrolce określanie wartości DataMember na podstawie argumentu DataMember, który jest także przesyłany do tego zdarzenia. Projektując kontrolkę pod kątem pracy ze środowiskiem Data Environment, które może zawierać wiele elementów danych (data members) korzystających z tego samego połączenia z bazą danych, powinieneś zaimplementować właściwość DataMember.

Chociaż ta kontrolka korzysta z ADO jako metody dostępu do bazy danych, równie dobrze możesz użyć metod DAO lub RDO.

Kolejny fragment kodu, który dodamy do kontrolki, dotyczy zdarzenia hsbRecScroll _Change. Zdarzenie to zachodzi ilekroć zmienia się wartość paska przewijania. Posłużymy się nim, by zmienić bieżący rekord w zestawie.

Dodaj do kontrolki kod z wydruku 8.7.

Ta procedura jest w rzeczywistości bardzo prosta. Najpierw sprawdza, czy przypisano obiektowi rsMain wskaźnik. Jeśli nie, oznacza to, że nie ustanowiono połączenia z bazą danych, nie ma więc sensu próbować zmiany pozycji w zestawie Recordset.

Wydruk 8.7. R08W07.txt – zdarzenie hsbRecScroll_Change jest stosowane do natychmiastowej aktualizacji bieżącego rekordu w zestawie
Private Sub hsbRecScroll_Change()

' Jeśli zmiennej rsMain nie przypisano wartości,
' nie rób nic.
If Not (rsMain Is Nothing) Then
    ' Przejdź do rekordu o numerze wskazanym
    ' przez pasek przewijania.
    rsMain.AbsolutePosition = hsbRecScroll.Value
    ' Check for a BOF condition...
    If rsMain.BOF Then
        ' Dla zestawu rekordów spełniony jest warunek BOF. 
        ' Działanie określone jest przez BOFAction.
        Select Case msdcBOFAction
            Case sdcBOFActionConstants.sdcMoveFirst
                rsMain.MoveFirst
            Case Else
                Exit Sub
        End Select
        Exit Sub
    End If
    ' Sprawdź warunek EOF...
    If rsMain.EOF Then
        ' Dla zestawu rekordów spełniony jest warunek EOF. 
        ' Działanie określone jest przez EOFAction.
        Select Case msdcEOFAction
            Case sdcEOFActionConstants.sdcMoveLast
                rsMain.MoveLast
            Case sdcEOFActionConstants.sdcAddNewRecord
                ' Dodaj nowy rekord i uaktualnij
                ' właściwości Max i Value
                ' dla paska przewijania.
                rsMain.AddNew
                hsbRecScroll.Max = rsMain.RecordCount + 1
                hsbRecScroll.Value = rsMain.RecordCount + 1
            Case Else
                Exit Sub
        End Select
        Exit Sub
    End If
End If

End Sub

Jeżeli rsMain zawiera wskaźnik do zestawu Recordset, zmieniana jest właściwość AbsolutePosition obiektu rsMain, której przypisywana jest teraz wartość Value paska przewijania. Właściwość AbsolutePosition zmienia bieżący rekord na rekord o określonym numerze logicznym, dostarczając w ten sposób wygodnej metody aktualizacji pozycji Recordset za pomocą paska przewijania.

Po ustanowieniu nowej pozycji, przeprowadzany jest test wystąpienia warunków BOFEOF. W zależności od wartości właściwości BOFAction i EOFAction dla kontrolki, przeprowadzane są określone działania. Na przykład, jeśli wystąpi warunek EOF, a właściwości EOFAction przypisano wartość sdcAddNewRecord, wywoływana jest metoda AddNew obiektu rsMain i do zestawu Recordset dodawany jest nowy rekord. Właściwości Max i Value dla paska przewijania zostaną zaktualizowane, bowiem zakres numerów rekordów zwiększył się o jeden.

Po rozwiązaniu kwestii zmian wartości paska przewijania, dodamy kod przycisków. Zdarzenia Click dla tych przycisków są krótkie i wdzięczne – po stwierdzeniu, że połączenie zostało nawiązane, wywołują po prostu metody MoveFirst lub MoveLast obiektu rsMain. Wartość paska przewijania jest także aktualizowana, by odzwierciedlała nową liczbę rekordów.

Wydruk 8.8 prezentuje kod zdarzeń cmdFirst_Click i cmdLast_Click.

Wydruk 8.8. R08W08.txt – zdarzenia cmdFirst_Click i cmdLast_Click umożliwiają przemieszczenie do pierwszego lub ostatniego rekordu w zestawie Recordset
Private Sub cmdFirst_Click()

' Jeśli rsMain przypisano wartość, przejdź
' do pierwszego rekordu w zestawie
' i dokonaj aktualizacji pozycji paska przewijania.

If Not (rsMain Is Nothing) Then
    rsMain.MoveFirst
    hsbRecScroll.Value = 1
End If

End Sub


Private Sub cmdLast_Click()

' Jeśli rsMain przypisano wartość, przejdź
' do ostatniego rekordu w zestawie
' i dokonaj aktualizacji pozycji paska przewijania.

If Not (rsMain Is Nothing) Then
    rsMain.MoveLast
    hsbRecScroll.Value = hsbRecScroll.Max
End If

End Sub

Kontrolka jest niemal skończona. Pozostało jedynie dodanie metod, które zostały określone w jej interfejsie.

Dodawanie metod

W interfejsie kontrolki określono trzy metody: MoveFirst, MoveLast i MoveToRecord. Metody to po prostu procedury typu Public, a implementujący je kod przypomina kod niedawno dodawany w celu określenia reakcji na zdarzenia paska przewijania i przycisków poleceń.

Wspomniane metody uwzględniono w kodzie z wydruku 8.9 – dodaj go do kontrolki.

Wydruk 8.9. R08W09.txt – ten kod implementuje metody MoveFirst, MoveLast i MoveToRecord kontrolki
Public Sub MoveFirst()

' Jeśli rsMain przypisano wartość, przejdź
' do pierwszego rekordu w zestawie
' i dokonaj aktualizacji pozycji paska przewijania.

If Not (rsMain Is Nothing) Then
    rsMain.MoveFirst
    hsbRecScroll.Value = 1
End If

End Sub


Public Sub MoveLast()

' Jeśli rsMain przypisano wartość, przejdź
' do ostatniego rekordu w zestawie
' i dokonaj aktualizacji pozycji paska przewijania.

If Not (rsMain Is Nothing) Then
    rsMain.MoveLast
    hsbRecScroll.Value = hsbRecScroll.Max
End If

End Sub


Public Sub MoveToRecord(RecNumber As Long)

' Jeśli rsMain przypisano wartość, przejdź
' do określonego rekordu zestawu, ale
' musi się on zawierać w poprawnym zakresie.

If Not (rsMain Is Nothing) Then
    If RecNumber >= 1 And RecNumber <= rsMain.RecordCount Then
        rsMain.AbsolutePosition = RecNumber
    End If
End If

End Sub

Teraz kontrolka jest gotowa. Pamiętaj, by ją zapisać przed powtórnym wypróbowaniem.

Skończony produkt

Aby wypróbować kontrolkę, przełącz się do projektu Project2. Usuń istniejącą instancję kontrolki, a następnie utwórz nową. Dodaj pole tekstowe do formatki. W przypadku kontrolki ScrData, dobierz odpowiednie wartości dla właściwości ConnectionString i RecordSource. Aby ustanowić połączenie na przykład z bazą danych BIBLIO.MDB, możesz je zdefiniować w ten sposób: ConnectionString "Provider=Microsoft. Jet.OLEDB.3.51;Data Source=C:\VStudio98\VB98\Biblio.mdb", zmieniając ścieżkę do pliku Biblio.mdb, tak aby odpowiadała sytuacji na Twoim komputerze. Właściwości RecordSource mógłbyś następnie przypisać nazwę Publishers lub nazwę innej tablicy z bazy danych.

W przypadku pola tekstowego, przypisz właściwości DataSource nazwę kontrolki ScrData (ScrollData1). Zmień następnie właściwość DataField, przypisując jej nazwę pola tablicy, z którym chcesz stowarzyszyć pole tekstowe.

Rysunek 8.3 pokazuje efekt końcowy. Tutaj kontrolka ScrData jest stosowana do szybkiego przemieszczania się między rekordami bazy danych Biblio tablicy Publishers.

Rysunek 8.3.

Kontrolka ScrData

Po sprawdzeniu poprawności działania kontrolki, możesz ją rozbudować i skompilować do pliku .OCX. W takiej postaci możesz z niej korzystać w wielu swoich projektach.

Tworzenie konsumenta danych

Stworzenie kontrolki ActiveX, która działa jako konsument to sprawa równie prosta. Chociaż nie znajdziesz w tym podrozdziale przykładu kontrolki działającej jako konsument, dowiesz się, co jest potrzebne, by takie kontrolki tworzyć.

Najpierw musisz zmienić właściwość DataBindingBehavior obiektu UserControl. Można jej przypisać wartość vbNone, vbSimpleBound lub vbComplexBound. W przypadku drugiej wartości (simple bound control), kontrolka jest stowarzyszona z pojedynczym polem w określonym źródle danych. Trzecia wartość (complex bound control) oznacza, że kontrolka stowarzyszona jest z całym wierszem danych w źródle danych.

Aby zdefiniować, że kontrolka posiada zdolność do bycia związaną ze źródłem danych, skorzystaj z opcji Procedure Attributes menu Tools. Aby ta opcja była dostępna, musisz znajdować się w okienku kodowym tworzonej kontrolki. W okienku dialogowym Procedure Attributes naciśnij przycisk Advanced. Wskaż nazwę stowarzyszanej właściwości na liście Name i zaznacz pole Property is Data Bound. Są tu jeszcze cztery inne pola, które możesz zaznaczyć:

Tworząc konsumenta danych typu SimpleBound, przypisz właściwości DataBindingBehavior wartość vbSimpleBound. Wówczas możesz zdefiniować właściwość tylko do odczytu, która zawiera wartość stowarzyszonego pola.

Wybierz w okienku dialogowym Procedures Attribute właściwość i zaznacz pole Property Binds to DataField.

Tworzenie kontrolki ActiveX działającej jako konsument nie jest trudne, ale trzeba prób i błędów, aby się tego nauczyć. Konieczna jest także solidna wiedza na temat samych kontrolek ActiveX.

Podsumowanie

Ostatnia wersja języka Visual Basic umożliwia projektowanie kontrolek ActiveX, które działają jako źródła danych i konsumenci danych. Możesz tworzyć takie kontrolki i korzystać z nich w celu pobierania i wyświetlania informacji z baz danych we własnych programach.

W tym rozdziale zapoznałeś się z podstawami tworzenia źródeł danych i konsumentów. Krok po kroku przeszedłeś procedurę tworzenia źródła danych, uzyskując w efekcie prostą kontrolkę, która może być stosowana do łączenia z bazami danych za pośrednictwem metody ADO.


Rozdział z książki "Visual Basic 6 - księga eksperta". © 1999 Wydawnictwo Helion