Warsztat 2: Otwieranie formularzy: Jak przekazać obiekt w OpenArgs?

Pointers.zip
Autor: Krzysztof Naworyta
Baza w formacie MsAccess 97
71kB, 16-10-2002

Opis problemu:

Oddajmy głos Krzysztofowi Naworycie:

Czy można przekazać obiekt poprzez OpenArgs? Pewnie, że Nie! przecież to string! No właśnie. Teoretycznie można by przekazać np. nazwę formularza ... No ale jeśli mamy otwartych kilka instancji? Wtedy możemy posiłkować się niestandardowymi właściwościami i traktować wołany formularz jako klasę:
Dim f As Access.Form
DoCmd.OpenForm "form1"
 Set f=Forms!form1
 Set f.PrzekazywanyArgument = Me
No fajnie, ale to niestety wymusza zrezygnowanie z wywołania acDialog, które przerywa wykonywanie procedury. Można posiłkować się pętelką z DoEvents - aby symulować przerwanie kodu. Ale jeśli jedyna "niestandardowa właściwość" jaką chcemy przekazać do formularza, to kontrolka, która ma oczekiwać na zwróconą wartość? Tak by się chciało przekazać ją przez OpenArgs ... No to jest!

Rozwiązanie:

Działa doskonale z formularzami, kontrolkami, co kto chce ... Formularz 1  (pole tekstowe Tekst1, przycisk Polecenie1)
'******************************************************************
Private Sub Polecenie1_Click()
  Dim oData As Object
  Set oData = Me!Tekst1

  DoCmd.OpenForm "Drugi", WindowMode:=acDialog, OpenArgs:=ObjPtr(oData)
  ' tu sobie spokojnie czeka na zamknięcie wywołanego formuarza
  MsgBox "ok"  
End Sub
'******************************************************************
Formularz 2 ("Drugi") (pole tekstowe Tekst2, przycisk Polecenie2)
'******************************************************************
Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" _
      (Destination As Any, _
       Source As Any, _
       ByVal Length As Long)
       
Dim loData As Object

Private Sub Form_Open(Cancel As Integer)
  Dim lngPointer As Long
  Dim tmpData As Object                    ' nowa zmienna pomocnicza

On Error GoTo err_exit

  lngPointer = CLng(Me.OpenArgs)
  Call CopyMemory(tmpData, lngPointer, 4)  ' przechwyć obiekt
  Set loData = tmpData                     ' przekaż do docelowej zmiennej
  Call CopyMemory(tmpData, 0&, 4)          ' zwolnij przechwyt

  ' i juz można śmiało korzystać z loData ...
  Me!Tekst2 = loData.Value ' ustaw wartość z przekazanej kontrolki
  Exit Sub
err_exit:
  MsgBox Err.Description
End Sub
'******************************************************************
-- KN

Rozbudowana dyskusja na powyższy temat, dostępna jest tutaj, w archiwum grupy dyskusyjnej.

Dociekliwi znajdą tam szereg informacji także o kontekscie zagadnienia, które jak się okazuje ma swoje pułapki. A dla wszystkich, prezentuję program Pointers.mdb (autorstwa Krzysztofa Naworyty), który zawiera ostatecznie wypracowany sposób wykorzystania wskaźników obiektowych do kilku praktycznych zastosowań.