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

John Colby jwcolby at gmail.com
Sat Jan 29 09:57:03 CST 2022


http://jwcolby.blogspot.com/2013/02/a-form-wrapper-to-control-them-all-in.html?view=sidebar


On Sat, Jan 29, 2022 at 10:08 AM Bill Benson <bensonforums at gmail.com> wrote:

> Where does Function form_onOpen come into the picture? When I go to the
> form, And choose Form from the dropdown at the top of the code module, I
> see Open, when I select that I get
>
> Private Sub Form_Open(Cancel as Integer)
>
> If you are really writing a function named form_OnOpen when does it get
> called (or by what?)
>
> 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
> >
> --
> AccessD mailing list
> AccessD at databaseadvisors.com
> https://databaseadvisors.com/mailman/listinfo/accessd
> Website: http://www.databaseadvisors.com
>


-- 
John W. Colby
Colby Consulting


More information about the AccessD mailing list