John W Colby
jwcolby at gmail.com
Thu Mar 12 19:03:11 CDT 2009
I have to apologize for some miscommunications in this email. >clsCboRecSel is declared Withevents back in the form. clsCboRecSel is declared Withevents back in the CLASS clsFRM. I have worked so long with classes that I think of my class as the object, I refer to my clsFrm as "the form", when in fact my class is the form's wrapper. My class sinks all of the form's events, and it also sinks events coming back from specific other classes of my own, in this case clsCboRecSel. Apologies for the confusion. John W. Colby www.ColbyConsulting.com Charlotte Foust wrote: >> IMO classes really need to *try* to be independent of each other. >> Sometimes it is not possible, sometimes specific sets of classes form a >> > system and need each other to perform the whole task. > > I agree with the first statement, John. But I can't think of a reason > it wouldn't be possible. When two independent objects need to > coordinate, they do it through another class. > > Charlotte Foust > > -----Original Message----- > From: accessd-bounces at databaseadvisors.com > [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of John W Colby > Sent: Thursday, March 12, 2009 2:39 PM > To: Access Developers discussion and problem solving > Subject: Re: [AccessD] Building a control class > > AD, > > >In your view, what could be the best strategy for projecting the > events pertaining to form object variable in form class, into the > control class ? > > In general a control class should not be aware of the form and > particularly its events. If the form needs to have a control do > something in response to one of the form's events, you should expose a > method in the control class to call from the form's event. Let's take > an example: > > I use a combo control to cause the form to select a record. The form > and the combo should "stay in sync" or it is visually confusing. IOW, > if the form moves to a specific record, the record selector combo should > "move to" and display that same record. Obviously if the combo selects > a record, the form should move to that record. The form and combo "stay > in sync". > > I created a "mSyncToForm(lngPKID)" method in the combo class. In the > form's Current event the clsCboRecSel.mSyncToForm is called passing in > the form's PKID. The combo class then causes the combo control to > display the record with that value in column 0. Thus the combo "syncs" > to the form. > > OTOH, if the user selects a record that they want to move to, the form > should move to that record. clsCboRecSel defines an Event > evAfterUpdate(lngPKID as long). The clsCboRecSel raises the > 'evAfterUpdate event in the combo's AfterUpdate event stub in the class. > clsCboRecSel is declared Withevents back in the form. An event stub is > created in clsFrm sinking evAfterUpdate. When evAfterUpdate fires, > control passes back to the form's evAfterUpdate event stub and the form > has to grab a copy of the RecordsetClone, move to that record, grab the > bookmark, then set the form's bookmark to that bookmark, causing the > form to move to the right place. > > Notice that the clsCboRecSel doesn't need to know anything about the > form in either case. It can sync to the form simply by exposing a > method for the form to call, and the form can sync to the record > selector simply by sinking an event raised by the record selector class. > > So the answer is to build functionality into the control class, and > expose that functionality via methods of the control class. Raise > events in the control class as required to notify the form that the > control class did something that the form class might want to know > about. > > Often times the control class behaviors simply don't matter to the form. > For example my combo control wrapper class can be programmed to open a > specific list form in the dbl-click event so that the list behind the > form can be programmed. The form that carries the combo control doesn't > care about that, in fact that is a behavior that might be useful in any > combo in any form. It is the combo control classes' business, not the > form class' business. > > IMO classes really need to *try* to be independent of each other. > Sometimes it is not possible, sometimes specific sets of classes form a > system and need each other to perform the whole task. On the other hand > even when they might need to know about each other, you should try to > use an interface - an exposed method or raising an event - to allow the > partner object to get something done. Programming an interface helps to > disentangle the objects themselves. > > >If a WithEvents variable of form type is declared in control class and > is set equal to the form variable belonging to form class, it hampers > proper closing. > > Yes, it definitely can. a circular reference is formed where the form > refers to the form class which refers to the control class and the > control class refers to the form. The answer is being rigorous in your > cleanup. Sometimes just setting the pointer to the control class to > nothing back in the form class is enough to cause the control class to > close properly. The class terminate MUST set pointers to all objects to > nothing. If the terminate event fires then the form pointer is cleaned > up as is the pointer to the wrapped control(s). If this cleanup is not > performed then things start to break. Occasionally I have had to expose > a mTerm() method that I explicitly called back in the parent class > before setting the pointer to the child class to nothing. That mTerm > class performs all of the cleanup. The Class_Terminate() event then > calls mTerm in cases where the pointer in the parent is just set to > nothing. > > Cleanup is CRITICAL. If you do cleanup correctly, then it is quite > possible to grab pointers to the form, and even sink form events. > Sinking form events can be risky though in the earlier versions of > Access, and can cause page faults in weird situations. > > >On the other hand, if a custom event is raised in form object's event > (say current event) in form class, thereby enabling setting up of > WithEvents object of form class type (set equal to the form class) in > the control class, the said event does come up in the intellisense but > does not show any activity. > > The event should fire in the control class, as long as the event > property is set to [Event Property]. I have done so before and it does > work. It is not clear whether you intend for the clsFrm to raise an > event and be sunk in the control class, or for the form itself to have > an event sunk in the control class. Either one *should* work. I have > never tried to sink an event raised by my clsFrm inside of a control > class, nor have I even declared clsFrm Withevents in a control class. > > > I have to say I am heartened to have you asking so many questions about > classes and events. From your general Access knowledge level I long ago > assumed that you were probably way above me in this stuff. From the way > you study stuff I assume that you soon will be anyway. ;) > > > John W. Colby > www.ColbyConsulting.com > > >