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

Rocky Smolin rockysmolin2 at gmail.com
Sat Jan 29 09:59:19 CST 2022


Another pice of gratuitous unsolicited advice - because of my career as an
indie SW developer I did a lot of beta testing before releasing a product.
So I did the same with my book - about 30 people read the pre-release and I
got a lot of feedback about "bugs" in the book - inconsistencies, what the
film business calls 'continuity' problems, passages that were unclear, etc.
For a book with SW, I would think a long period of beta testing would be
important.

r

On Sat, Jan 29, 2022 at 5: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