JWColby
jwcolby at colbyconsulting.com
Sat Jan 6 22:39:01 CST 2007
Yes! Maybe. If you are talking about a callback function then the answer is "damned tough". However for objects like forms and controls.... That is exactly what I have been talking about for the last few years. I call these classes "wrappers" because they wrap up the functionality of an object, and then allow you the programmer to "extend" the functionality of the wrapped object. I have a clsFrm, a clsCtlCbo, clsCtlTxt, clsCtlCmd, clsCtlChkBox etc. As you can tell from the name, each class "wraps" some native Access object such as a form, a command button, a combo etc. My classes then add functionality that I find useful for those objects. My form class has a control scanner which scans the form as it opens looking for controls. That "scanner" is functionality that I find useful and have added in my form class. The scanner then loads a clsCtlCbo for every combo object it finds, a clsCtlTxt for every text box etc. Each of these classes provides me a place to store code to implement functionality that I find useful for those objects. As an example, I find it useful to have the clsCtlCbo sink the combo's DblClick event and open a form for editing the list behind the form. In order to enable this behavior, I simply feed the clsCtlCbo a DblClick form name, into a string property. If the property holds a form name, then when the dblclick event occurs, my code opens that form. Of course it does much more as well. For example if a combo has been fed a form name to open, then the dbl-click will open that form. I cause the labels for the combo to change background color as a visual cue to the user that the form can be Dbl Clicked and something will happen. They have to learn that rule, but once learned, it works the same in every form (that uses the form class), in every application. When controls such as text boxed and combos get the focus, I cause my control class to change the background color so that the user can tell that control has the focus. And the list goes on and on. All these things are behaviors that I think are useful, and so I include them in MY control classes. Thus every one of my projects just automatically has the ability to DblClick a combo and have a form open to edit the combo's list, have text and combos change background color when they get the focus etc. Every form, every project. I believe that kind of consistency is critical to making a project usable. The user should be able to see, "oh, the label for this combo is a different color... That means I can double click it and open the form. Of course my framework also has what I call LWS (light weight security) so that the application can determine which groups users belong to, and the application can decide which user groups see the label change color and can dbl-click the combos to edit the list tables. All automatically, every form, every application. Once you understand the concept, once you start creating your framework, then your imagination can take over. Want an audit trail? Every control already has a class, automatically loaded by the form class. Between the form class and the various control classes, you have the tools to create an audit trail behavior. I can log what users log in to what workstations, what forms open, what controls get the focus, what data is edited, what reports are run, all neatly date stamped. Turn it on and off with SysVars. Do you want the ability to have user groups be able to see and edit specific forms, and controls in forms? Once you have a form class and control classes, you have the tools to implement a Light Weight Security functionality. Need data logging to files on the disk? Need emails to an admin when errors occur? Need to be able to turn on / off functionality in the framework or the application? Ever hear the term SysVars? All these kinds of things are things I call service classes, and all these things exist in my framework. Write once, use forever, you applications become consistent throughout (and EXTREMELY powerful). But it is not the application providing the power, it is your framework. That's how I do it. John W. Colby Colby Consulting www.ColbyConsulting.com -----Original Message----- From: accessd-bounces at databaseadvisors.com [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Jim Lawrence Sent: Saturday, January 06, 2007 4:46 PM To: 'Access Developers discussion and problem solving' Subject: Re: [AccessD] Log Class part 1B Hi John: The last group of messages forms an excellent reusable class. As you are so skilled in Access class design, I would like to pose a class related question. Can a MS Access class, like the class used to populate lists and combo boxes be encapsulated within a user defined/managed class? If this is not clear I will supply code off-line as it is a little large for the list. TIA Jim -----Original Message----- From: accessd-bounces at databaseadvisors.com [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of JWColby Sent: Saturday, January 06, 2007 10:14 AM To: 'Access Developers discussion and problem solving' Subject: [AccessD] Log Class part 1B BTW, for those of you who follow the concept of a framework, I have a framework object which is itself a class. I have now built a new method of the framework object that can initialize these log files and hold them in a collection. Given that my apps all use the framework, syntax becomes: cfw.log("MyLogName").Init("C:\Dev\DISNEW\", "Test", "LOG", "YYYYMMDD", "HHMMSS") cfw.log("MyLogName").Log "Write some test text" cfw.log("MyLogName").Term 'closes the log file and unloads it from the framework collection Notice that this syntax looks strikingly similar to the syntax you would use to work with any other object such as the database object, the form object etc. My framework is just an object, with methods and properties. The first line causes the framework (cfw) to create an instance of the log class, initialize it with the filespec information, and store a pointer to the log class instance in a collection for future use. The second line uses a previously initialized log class instance to write text. The last line unloads the class from memory and the collection of log files available for use. Doing things "the framework way" allows me to create a ton of log files as required. For example: ' 'From inside of the ULLICO export process class I call the framework and set up two log files. ' cfw.log("ULLICOExport-Error").Init(C:\Dev\DISNEW\Export\ULLICO\", "ULLICO-Error", "ERR", "YYYYMMDD", "HHMMSS") cfw.log("ULLICOExport-Data").Init(C:\Dev\DISNEW\Export\ULLICO\", "ULLICO-Data", "DAT", "YYYYMMDD", "HHMMSS") ' 'From inside of the HV Export class I call the framework and set up two log classes. ' cfw.log("HVExport-Error").Init(C:\Dev\DISNEW\Export\HV\", "HV-Error", "ERR", "YYYYMMDD", "HHMMSS") cfw.log("HVExport-Data").Init(C:\Dev\DISNEW\Export\HV\", "HV-Data", "DAT", "YYYYMMDD", "HHMMSS") Now I have two different processes (a ULLICO export process and a HV export process), each using two log files. The Error log file is used to log any processing errors that the export process runs into. The Data log file is the actual data file that is being assembled by the export process. BTW, It took me almost as long to write this email as it did to write the log class and hook it into my framework. Classes are simple to write and use once you understand them. A framework magnifies the effectiveness of service classes such as this log class enormously, making them dead simple to set up, use and tear down. That's how I do it. John W. Colby Colby Consulting www.ColbyConsulting.com