John W Colby
jwcolby at gmail.com
Thu Mar 12 16:38:55 CDT 2009
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 A.D.Tejpal wrote: > John, > > Thanks for clarifying the points raised in earlier posts. > > 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 ? > > 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. Similar is the case if it is set equal to parent of the incoming control argument. > > 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. > > Best wishes, > A.D. Tejpal > ------------ >