May 1999VB 5 & VB 6 Inter-Dialog Communicationby Steve ColvinRecently, we were asked a question by an accomplished user of QBasic and VB 1.0/2.0/3.0. The question: does VB still require the use of global variables to pass data to/from a dialog box? The answer, of course, is no. This article serves to dispel that rumor and to demonstrate an OO method of passing data to/from a dialog box without the use of global or public variables. Our example application will show you how to create the code for a Text Entry dialog box, shown in Figure A, that you can then extend to meet your own needs.
Figure A: We'll design this modal dialog box that you can extend for your own use.
That's the way it was The method of passing data to, and returning data from, a dialog box has long dogged the VB programming community. Prior to VB4, programmers routinely used global variables in a BAS module to accomplish this communication--a practice whose roots date back to the 1970s COBOL era (yuck!). These variables had unsecured scope and were available for update by all routines. Their contents were always live, even when the processes that used them were completed. We no longer need to continue this approach in VB. In fact, it behooves us to abandon this practice and to instead embrace an objectcentric philosophy. But there's a better way Basic to an objectcentric philosophy is the practice of burying either generalized or specialized functionality in reusable components and exposing only what's necessary to the external process. Your PC, car, and stereo are filled with black box components. The engineer who designed these machines only needed to know the inputs, outputs, and tolerances of the building blocks to make the end product without regard to each component's internals. Developers need to take such an approach. An object, or component, exposes only those contents that are relevant to the user of that object through its public interface. With this in mind, all communication from/to the component must be done through this interface. A solid VB project architecture adheres to this guideline, eliminating the use of global variables for the passing of data from one process to another. Ultimately, this practice minimizes your debugging complexities and maximizes your potential for component reuse. Form a la modal Generically speaking, a dialog box is a GUI mechanism that extends the input of information beyond the confines of a single screen. It unclutters the base form and reduces overall resource consumption via segmentation. It can then be called from various places in the application without the need of process and code redundancy. More specifically, a dialog box is a form that's loaded using the vbModal parameter. It temporarily halts the calling form's thread (message loop) and leaves that thread in a wait for return status. When the modal form closes, control returns to the next line of code in the calling routine. Logically, a modal dialog box extends the thread of the calling routine. Dialog boxes and form-level variables The basic architecture for communication with a dialog box consists of the modal form with form-level variables, property procedures, and a VB class. The form-level variables (defined in the General Declaration section of the dialog box) are the buckets that hold the information to be returned. The contents of form-level variables are always available, whether the form is loaded or not. They can have non-initialized values assigned to them at any time, without the form even being loaded. Also, when the form is unloaded, all its controls' properties are initialized except its form-level variables. Only when the form is set to Nothing do the form-level variables get automatically initialized. We'll demonstrate this later. To retain a property value of a control, simply create a form-level variable in the General Declarations section and use that to store the property of the control you want to return. Then, when the button that closes the modal dialog box is pressed, capture the applicable property from the control into that variable, and unload the form. You'll want to ensure that the dialog box is set to Nothing after the values have been plucked out of the form-level variable. Although the VB compiler accepts form-level variables that are defined as Public, you risk the variables being unintentionally altered. By changing their scope to Private and using Property Get and Property Let procedures, you control access to these Private variables. A class(ic) excuse In our example application, which we'll show you shortly, we've added a layer of abstraction to the process by creating a Public function to encapsulate the loading, initializing, input/output communication, and garbage collection of the dialog box. This function can't reside in the dialog box form itself since the contents of the form-level variables are destroyed during the garbage collection. It's preferable to put the function in a class that can be instantiated to launch the form as opposed to putting it in a BAS module. For instance, if you reuse the dialog box in other applications (good for you if you can!), you can simply drop the class and the dialog box form into that app without having to gut the BAS module of extraneous code that might not apply to the other VB project. Also, by hiding the function in a VB class, it's not necessary to hardcode the name of the form or any of its attributes in the application that uses it. That way, if the form or any of its components are renamed, you can just change the references to them in the class. Our inter-dialog example We'll begin by creating two forms, the dialog box, frmModalTextDialog, and the calling form, frmCallModalTextDialog. We'll also create one class called clsModalTextDialog. Create a project folder called ModalDialog; we'll refer to this folder later. Set frmCallModalTextDialog as the Startup object in the Project Properties dialog box in the Project menu. Figure A, on the cover, shows the structure of our modal dialog box, frmModalTextDialog. Figure B shows the structure of the calling form, frmCallModalDialog. Tables A and B show the properties frmModalTextDialog and frmCallModalDialog, respectively.
Figure B: Design your calling form to look like this (frmCallModalTextDialog).
Table A: Property settings of frmModalTextDialog (the modal form)
Table B: Property settings of frmCallModalTextDialog (the calling form)
Now that you have the screens painted, let's add some code to tie this all together. Listing A defines the private form-level Property variables of the modal dialog box, as well as their corresponding Let and Get Property procedures to control access to the variables. Listing B contains the code to capture the attributes of controls (that is, the Text property) into the dialog box's Property variables so the information will persist after the dialog box is unloaded. Listing A: Form-level variables and Property procedures for modal form (frmModalTextDialog)
Listing B: Private routines in the modal form (frmModalTextDialog)
The only code necessary for the VB class is shown in Listing C. Be sure
to name the VB class file ModalTextDialog.cls. Its ShowDialog function manages
the entire process of launching the modal dialog box and returning the
information to the routine from which it's called. (Two of its arguments,
theInputString and theOutputString, could have shared the same address space.
For example, we could replace these with a single by-reference string variable,
theString; however, they've been segregated for discussion purposes.)
Listing C: Exposed class function to launch modal form and return results
At this point, the dialog box needs only to be given life. Listing D
activates the modal dialog box from frmCallModalTextDialog by passing it the
contents of the Text property of Text1 as the initial value.
Listing D: Calling form's code (frmCallModalTextDialog) to use the reusable object
ShowDialog
is defined as a Boolean function, so the calling routine can recognize that the
user confirmed the text to be returned. If the user clicks Return in the modal
dialog box, ShowDialog returns True; otherwise, it returns False. There are
many other features that could be added to the modal dialog box (MultiLine
options, Search/Replace capabilities) but they go beyond the scope of this
article.
How about a test drive? To see how VB handles the initialization of control properties and form-level variables, follow these steps:
Conclusion In this article, we demonstrated how VB cleans up a form's control properties and its form-level variables when the form is unloaded and when the form is set to Nothing. We also took advantage of what we learned by creating form-level variables to keep the Property values of controls beyond the Unload statement and by launching the form with a class function. The function acted as a middleman between the base form and the modal dialog box by encapsulating the passing of data between these forms prior to setting the dialog box to Nothing. By not using global variables to pass data to a form, we can create a component that can stand alone; that is, a component that's reusable. In our companion article, "Reusability via ActiveX," we'll explore additional reusability opportunities that this methodology offers.
|
Copyright © 1999, ZD
Inc. All rights reserved. ZD Journals and the ZD Journals logo are trademarks of ZD
Inc. Reproduction in whole or in part in any form or medium without
express written permission of ZD Inc. is prohibited. All other product
names and logos are trademarks or registered trademarks of their
respective owners.