[AccessD] Doing some thing the class way... was Toolbar

Bill Benson bensonforums at gmail.com
Sat Jan 29 10:32:21 CST 2022


Some things here that don't sit right with me. My own faulty programming
may lead to these questions, so please answer them politely as they are not
criticisms, though I may state them as I understand them, and not according
to reality/best-practice:

Don’t you need to use WithEvents in the class if you expect to sync the
events?
Don't you need to declare the main variable in the Class publicly if you
intend to have access to it from outside the class? Or are you intending to
write some kind of public property Set/Get routines? Also, I have not been
successful trying the latter, I kept getting a invalid property type when
compiling.
Where are you putting Function_Init?.
What command calls this function and what are you passing to it?

Where is the New keyword? If you don't use the New keyword, how can you
create an instance of your class?


On Sat, Jan 29, 2022 at 8:57 AM John Colby <jwcolby at gmail.com> wrote:

> Bill,
>
> If I create my own class to "wrap" an object, I have to dimension a
> variable to hold a pointer to my class after I open it.  Let's assume I
> want to create a clsFrm to wrap my form and sink events from my form.
>
> 1) I create my clsFrm.
> 2) In the header of my clsFrm I create a variable
>
> dim frm as form
>
> 3) I create an Init function
>
> function finit(lfrm as form)
>    set frm = lfrm
> end function
>
> Back in the header of my form's cbf module I dim a pointer to my class
>
> dim gclsFrm as clsFrm
>
> In The OnOpen of my form I instantiate my class
>
> function form_OnOpen()
>
>
>
>
> On Sat, Jan 29, 2022 at 7:38 AM Bill Benson <bensonforums at gmail.com>
> wrote:
>
> > John - I need to ask for clarification on a few definitions and
> procedures
> > in your explanation.
> >
> > 1. What does CBF stand for?
> > 2. Where and how do you create instances of the class module you are
> > assigning forms to?
> >
> > I have a new database with only one form named Form1, which has no code
> in
> > its code module, and which has had added to it, in design view before I
> > closed and saved it, a single control (command button) named Command0. I
> > will next write some code in a class module I named clsForm, and a
> > procedure named LoadForms in a standard module named Module1; I will
> single
> > step through LoadForms and report on intermediary results. As I will hit
> a
> > runtime error very quickly, I will ask you some questions.
> >
> > 'clsForm
> > Option Compare Database
> > Option Explicit
> > Public WithEvents MyForm As Form
> >    Private Sub MyForm_Load()
> >        g_i_IncrementForms = g_i_IncrementForms + 1
> >        MsgBox "Instance " & g_i_IncrementForms & " of Form_" &
> > Me.MyForm.Name & " was unloaded"
> >    End Sub
> >
> >    Private Sub MyForm_Unload(Cancel As Integer)
> >        MsgBox "Instance " & g_i_IncrementForms & " of Form_" &
> > Me.MyForm.Name & " was unloaded"
> >    End Sub
> >
> > 'Module1
> > Option Compare Database
> > Option Explicit
> > Public g_i_IncrementForms   As Long
> > Public g_col_Forms          As Collection
> > Sub LoadForms()
> >    Dim clsForm     As clsForm
> >    Dim Form        As Object
> >    Dim Forms       As Object
> >
> >    Set Forms = Application.CurrentProject.AllForms
> >    For Each Form In Forms
> >       Set clsForm = New clsForm
> >       g_i_IncrementForms = 0
> >       Set clsForm.MyForm = Form
> >       If g_col_Forms Is Nothing Then
> >         Set g_col_Forms = New Collection
> >       End If
> >       g_col_Forms.Add clsForm
> >    Next
> > End Sub
> >
> > Single-Stepping through Module1.LoadForms: Before the line Set
> > clsForm.MyForm = Form, the immediate window can give me these results:
> >    ?TypeName(Forms)
> >      AllObjects
> >    ?TypeOf Forms is AllForms
> >      True
> >    ?TypeOf Form is Object
> >      True
> >    ?TypeOf Form is Form
> >      False
> >    ?Forms(0).name
> >      Form1
> >
> > Some things to note:
> >     In the construction above, Form is declared as Object.
> >     The line Set clsForm.MyForm = Form, will throw a runtime error.
> >
> > If instead this declaration had been used
> >    Dim Form        As Form
> >
> > then this line would have produced a runtime error:
> >    For Each Form In Forms
> >
> > Therefore, in order to have some kind of collection to loop *prior* to
> > opening any forms, I have to deal with the AllObjects class with members
> of
> > type Object. Declaring the MyForm object in the clsForm class module is
> > what causes the assignment  Set clsForm.MyForm = Form to result in a type
> > mismatch error.
> >
> > So given my results, I concluded - you will apparently tell me WRONGLY -
> > that using class modules to house a Form's events was not possible until
> > the Form itself has been opened.
> >
> > So in order for me to understand what you are implying by stating the
> class
> > module approach can be used to hold the Form's events, I need you to show
> > me some code that will create an instance of clsForm for each Form type
> > access object. That will enable me to apply your methods. Your
> explanation
> > so far confuses me, since you talk about declaring things "in the Form
> > header". What Form header, in the code module of the Form? If that is so,
> > then the Form has to be opened in order for those objects to get assigned
> > something in memory. Until them, I assume they are either allocated some
> > memory, or are in fact nothing at all, prior to a particular Form
> opening.
> >
> >
> > On Fri, Jan 28, 2022 at 9:44 PM John Colby <jwcolby at gmail.com> wrote:
> >
> > > Bill, I am in no way dissing your answer, your experience, or point of
> > view
> > > - in fact I highly respect all of the above.
> > >
> > > The original author asked if it could be done in a class called from
> each
> > > form that wanted to do this.  Seems like that is worthy of asking,
> worthy
> > > of consideration.
> > >
> > > There are more ways to kill a cat than choking it to death on butter as
> > my
> > > mamma used to say.  Sometimes quick is good or even best.  I wasn't
> even
> > > really addressing the original thread since I wasn't following it
> > closely.
> > > I was addressing the concepts.
> > >
> > > I understand quite well that to the majority of Access developers what
> I
> > do
> > > with classes is, shall we say, not understood well, if even at all.  I
> > try
> > > occasionally to poke ideas into conversations just to stimulate
> thinking
> > > about how we do things. So...
> > >
> > > Frameworks are everywhere.  In the 80s I learned to program in Turbo
> > > Pascal, whereupon I stumbled on their database framework.  It was a
> > SYSTEM
> > > of code which allowed me to use a database for Turbo Pascal.  From that
> > > experience and others a little later grew my passion for creating my
> own
> > > framework for Access, office and VBA.
> > >
> > > Using a class to wrap a form is the foundation for a framework.  Using
> a
> > > class to wrap each control is another piece of that framework.  I wrote
> > > every single piece of my framework as code behind form, calling
> functions
> > > in a library of functions, because where else does code go?
> > >
> > > It didn't take long to discover that I was coding a concept over and
> over
> > > in many of my forms.  And my CBF was looooonnnnnnngggggg.  Out the door
> > and
> > > down the hall loooonnnnnnnggggg..... because I was sinking events in
> each
> > > form, doing exactly the same thing in form A as in form B.  Except I
> was
> > > embedding the event sinks to do that in each form.  Identical code,
> > > everywhere.  A maintenance nightmare.  And I ran square into that
> > > maintenance nightmare myself.
> > >
> > > When I discovered classes and the fact that I could write a clsFrm,
> wrap
> > my
> > > form with my clsFrom and then sink form events into that clsFrm, all
> of a
> > > sudden all of those event sinks in all those CBF modules doing exactly
> > the
> > > same thing went away.  Any code that was used everywhere went into my
> > > clsFrm and those events that used to be sunk in the CBF of all those
> > forms
> > > was now sunk in my clsFrm.  Except that I was still sinking events for
> > > other objects directly in my clsFrm.  IOW modeling more than one thing
> in
> > > my class.
> > >
> > > CAUTION... In OOP, one of the foundational ideas is that an object
> models
> > > one thing (or a system).  A clsFrm models a form, a clsCbo models a
> combo
> > > box etc.  If I think about the CBF module behind a form, it is
> instantly
> > > obvious that I am writing a class which models a form, AND EVERY combo,
> > > text box, radio button etc placed onto that form.  NOT GOOD!!!
> > >
> > > Convenient yes.  It allows us as nube programmers to get our feet wet
> > > writing event sinks, to learn event driven programming, to learn about
> > the
> > > dozens of events for the dozens of controls, but hey... what a friggin
> > mess
> > > we make as a result.  Microsoft did us all a favor with the CBF module
> > > behind forms, making all that "event sinking" stuff easy precisely so
> > that
> > > we would learn it.  But... MSFT expects us to learn that stuff and then
> > > think about moving on.
> > >
> > > It isn't like I never did that CBF thing, I did!  For the first 10
> years,
> > > the entire decade of the nineties I did exactly that.  Forms with
> dozens
> > of
> > > controls embedded in them, with any events for any of those controls
> sunk
> > > directly in the CBF class module.  Code out the door and down the hall
> in
> > > every form.  There is a better way.
> > >
> > > Not a faster way, not more convenient in any given situation, not even
> > > appropriate in every given situation, but fundamentally better from an
> > OOP
> > > perspective.   If the same code is in events in many forms, move those
> > > events into a clsFrm and have them written in one place.  Reference the
> > > class in the CBF and pass in a pointer to the form.  Sink those events
> in
> > > clsFrm now.  Voila, all that repetitive code in all those CBF modules
> is
> > > gone.  Which makes my code much more readable, much more maintainable.
> > >
> > > We can have a conversation about frameworks if we want.  We can discuss
> > how
> > > it is done, why it is good, when it is and isn't useful.  What we can't
> > do
> > > is discuss is how doing xyz is always better, because that isn't true.
> > >
> > > In this specific case, the toolbar thingie, it may not even work to try
> > and
> > > do it from a class.  TBH I didn't even look or think about it.  I was
> > > addressing "can it be done" not "is that the best way".
> > >
> > > --
> > > John W. Colby
> > > Colby Consulting
> > > --
> > > AccessD mailing list
> > > AccessD at databaseadvisors.com
> > > https://databaseadvisors.com/mailman/listinfo/accessd
> > > Website: http://www.databaseadvisors.com
> > >
> > --
> > AccessD mailing list
> > AccessD at databaseadvisors.com
> > https://databaseadvisors.com/mailman/listinfo/accessd
> > Website: http://www.databaseadvisors.com
> >
>
>
> --
> John W. Colby
> Colby Consulting
> --
> AccessD mailing list
> AccessD at databaseadvisors.com
> https://databaseadvisors.com/mailman/listinfo/accessd
> Website: http://www.databaseadvisors.com
>


More information about the AccessD mailing list