MACE, Terry
terry.mace at baesystems.com
Sun Feb 15 16:49:22 CST 2009
JC, Should the name be clsDemoMsg (as the first 3 line of code are, or clsMsgDemo as the earlier lesson had us save it? Regards Terry Mace Logistics Support Officer & Maintenance Supervisor -----Original Message----- From: accessd-bounces at databaseadvisors.com [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of jwcolby Sent: Saturday, 14 February 2009 2:57 AM To: Access Developers discussion and problem solving Subject: [AccessD] USING CLSMSGDEMO Unlike all of the previous lectures, THIS ONE is heavy duty. the reason is simply that you will be stepping through the code line by line to watch and understand the program flow. you MUST do this if you ever hope to truly understand classes, methods, Raising an event, sinking an event and how it all interacts. Do NOT skip over stepping through the code or all that you have learned will be so much less helpful. Understanding in your head how it all plays together will be very useful, and perhaps critical to becoming a first class user of classes. I am sure that there will be plenty of questions when we are done so go to it. In the previous lecture we created a class that will sink and source events from clsMsg. This lecture will show you how to set up, cleanup and use freestanding classes (which includes clsMsg by the way). * In the database window, click Insert / Module. This will be a plain module, not a class. * In the module header insert the following code: Private mclsDemoMsgSteve As clsDemoMsg Private mclsDemoMsgGeorge As clsDemoMsg Private mclsDemoMsgLinda As clsDemoMsg This code simply dimensions three variables to hold instances of clsDemoMsg. Notice we dimension them private. In general it is good practice to make variables private unless there is a good reason to make them public, and then expose those variables through functions if they need to be used outside of the current module. * In the module body, type in the following code: Function mDemoMsgInit() If mclsDemoMsgSteve Is Nothing Then Set mclsDemoMsgSteve = New clsDemoMsg mclsDemoMsgSteve.pName = "Steve" Set mclsDemoMsgGeorge = New clsDemoMsg mclsDemoMsgGeorge.pName = "George" Set mclsDemoMsgLinda = New clsDemoMsg mclsDemoMsgLinda.pName = "Linda" End If End Function This code SETs the class instances to a new instance of clsDemoMsg and immediately sets the instances pName property. It does so three times, once for each instance of the class that we will be playing with. Function mDemoMmsgTerm() Set mclsDemoMsgSteve = Nothing Set mclsDemoMsgGeorge = Nothing Set mclsDemoMsgLinda = Nothing End Function This function allows us to clean up the class instances when we are done playing. Function cDemoMsgSteve() As clsDemoMsg mDemoMsgInit Set cDemoMsgSteve = mclsDemoMsgSteve End Function Function cDemoMsgGeorge() As clsDemoMsg mDemoMsgInit Set cDemoMsgGeorge = mclsDemoMsgGeorge End Function Function cDemoMsgLinda() As clsDemoMsg mDemoMsgInit Set cDemoMsgLinda = mclsDemoMsgLinda End Function These three functions get pointers to the three instances of clsDemo dimensioned in the header of the module. It first makes sure that the class instances are initialized by calling mDemoMsgInit. That is all that is required to dimension, initialize, terminate and use instances of ANY class. You can have a single instance of the class, or many instances - in this case three. By the way, we could have stored the instances in a collection and created as many as we wanted but that would have made the code less readable for this demo. * Now... I want you to step through the code to see exactly what is going on so please set a breakpoint on the mDemoMsgInit line of EACH function cDemoMsg() function. * In the debug window type in the following code and hit enter: cDemoMsgSteve.mSendMsg "George", "Tuesday's meeting", "Tuesday morning the entire teem will meet in the conference room at 09:00 am" When you hit enter you should stop at the mDemoMsgInit() line in cDemoMsgSteve(). Start to step through the code. The first thing that will happen is to run mDemoMmsgInit(). The first time through the code the private variables at the top of the module will be Nothing and you will fall into the code that initializes each class instance. Continue to step into the code. You should step into the Class_Initialize for each clsDemoMsg instance, and of course that code initializes the message class itself for THIS instance of clsDemoMsg. Once you step out of that _Initialize code you should be back in mDemoMsgInit(). The next thing that happens is that you step into the pName property and store a name string into the mstrName variable in the top of the class header. When you step out of pName you will be back in mDemoMsgInit. You will then do the next instance and the next. After initializing every private variable in the top of the module, control should return to cDemoMsgSteve and you will get an instance of the class itself, properly initialized. Now that you have an instance of the clsMsgDemo, you will step into the .mSendMsg method of the class. You have passed in some information to this method and basically you will just send a message using the mclsMsg. NOTICE that when you execute mClsMsg.Send, control passes into clsMsg send method. This is where the event is generated (raised) that all the class instances are sinking. Once the event is raised, control will pass to EVERY event sink for that event. We have THREE instances of clsDemoMsg, and each one of them sinks this event so every one of these instances will get control, in the order that they were dimensioned. Go ahead and step into the mclsMsg.Send and step into the RaiseEvent. Control is transferred to some event sink somewhere. You should now be in mclsMsg_Message, about to check "If varTo = mstrName Then". The first thing I want you to do is to use intellisense to hover over VarTo and mstrName. VarTo (George) is of course the intended recipient of this message, and mstrNname (Steve) is the name of the class instance that currently has control. Step the code. Since they do not match you do not fall into the code to display the message but rather just fall down to where you will exit. Step out of this function. Notice that code control immediately transfers to the next event sink. Again step down to the If statement, and hover your mouse cursor over VarTo (George) and mstrName (George). Since George is the class instance that this message is directed to, control will fall into the If Then statement and we will build the message and display it. Figure out and understand the code that generates the message. Continue stepping until the message box pops up and read it. Continue stepping until you exit this function and notice that you are right back in the event sink for the last class instance. Step on through (no message will be built) until you exit the function. Notice that you are back in the clsMsg.Send method and about to exit that method. Step out of that method. Notice that you are back in the mSendMsg() method of clsDemoMsg and about to exit. Step out of that method. Notice that you are back in the debug window. WOAAAAAH. What a rush eh? You have just watched an event be raised, and sunk in three different places. The original message was created by cDemoMsgSteve.mSendMsg (Steve), and the message caused clsMmsg to RAISE an event. That message was sunk by ALL THREE instances of clsDemoMsg, first Steve, then George, then Linda. The ORDER that these instances got control was caused by the ORDER that you instantiated them in mDemoMsgInit(). Had you instantiated them in some other order then they would receive control in that some other order. George was the intended recipient so only George processed the message in the event sink. Now I want you to do this again, stepping through the code. Notice that I am using a different instance of the class (George) to send the message, and a different recipient (Linda). This time use the following code in the debug window: cDemoMsgGeorge.mSendMsg "Linda", "Lunch Today", "After the meeting we will all be meeting for lunch at the deli one building over." Notice first that the mDemoMsgInit does not perform the initialization because the classes were already initialized, so it just steps back out. Finally I want you to use the following code to send a message that no one picks up and displays: cDemoMsgGeorge.mSendMsg "John", "Lunch Today", "After the meeting we will all be meeting for lunch at the deli one building over." The reason no one picks up the message is that there is no class instance with the name of John in mstrName, and so none of the instances process the message. This is about as heavy duty as you will ever get. You would be wise to step through this code as many times as you need to fully understand what is going on at each step. How control passes to a method of a class and parameters are passed in. How an event is raised, and IMMEDIATELY control starts to pass to the event sinks. What order the event sinks process and why they process in that order. If you understand this lesson, you will have class events down pat. I KNOW it will be confusing, but just do it over and over until it sinks in. Then raise an event to pat yourself on the back. This lecture has been the most complex so far in terms of your being able to trace code execution. We have learned how to use a function that initializes our class instances and return an instance of a class. We then step into a method of that class. We watched the method call out to another class (clsMsg). We watched clsMsg RAISE an event. We watched the code control transfer to each of the three event sinks, and we watched the code be processed differently in each event sink because of logic inside of the event sink. We then watched the code unwind back to the calling code and finally back out to the debug window. Congratulations, you are now Class / Event gurus. A diploma will be awarded. -- John W. Colby www.ColbyConsulting.com -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com "Warning: The information contained in this email and any attached files is confidential to BAE Systems Australia. If you are not the intended recipient, any use, disclosure or copying of this email or any attachments is expressly prohibited. If you have received this email in error, please notify us immediately. VIRUS: Every care has been taken to ensure this email and its attachments are virus free, however, any loss or damage incurred in using this email is not the sender's responsibility. It is your responsibility to ensure virus checks are completed before installing any data sent in this email to your computer."