Alan Colburn wrote: > I cannot tell you how frustrated I am that I apparently *still* don't > fully understand communication between classes/forms!
First, I'll point out that forms *are* classes. Every time you define a new form, you're defining a new class. You can see that in the source code. So anything you can do with a class, you can do with a form. > I won't share > all my code with you, but let me tell you what I was trying to do & > hopefully one of you can explain to me what's going on so I can > understand, once and for all. The basic problem is to create a class > which will take care of saving values at shutdown and loading them at > startup, i.e., a config file. [I understand iniFiles and regIniFiles; > that is not the issue.] > > For the sake of argument, suppose I wanted to store values related to > the main form, a component on the form, and a class property. I think > that takes care of most possibilities :-) Well, the main form is a class, and a component is a class. So if you know how to save stuff for entire classes and for single properties, you're all set. > I am apparently confused and clueless regarding issues like what > parameters I need to have in the IniClass's method signatures, > whether they are sent by reference or by value (even though I thought > I understood that, thanks to you folks), Everything is passed by value, unless you specifically tell it not to by using the "var" or "out" keywords. Some confusion with that may come from the fact that class instances are always accessed by reference. When you have a variable in your program like this: var Form1: TForm1; That's not defining an instance of the TForm1 class. Instead, it's just a reference variable. It might refer to _any_ instance of TForm1. There may be many instances of that class, but the Form1 variable can only refer to one of them. It might also refer to none of them, in which case its value is nil. So when you pass Form1 to a procedure by value, you're passing a copy of the reference. You're not passing a copy of the entire form instance, though, since the Form1 variable never held such a thing. Form1 only holds a reference, so the reference gets passed by value. It's possible to pass a reference by reference. That's what you get with a signature like this: procedure Foo(var Bar: TFont); It's not often that you see such a signature. It would mean that Foo might change the value of Bar. That is, it would make Bar _refer_ to a totally different TFont instance. More likely, Foo only needs to change the properties of the TFont instance it's given. That doesn't require changing the value of Bar. Bar can continue refering to the same TFont object it started with. Since the variable doesn't reference anything different, its value stays the same and therefore doesn't need the "var" keyword. > and even where it's best to > instantiate IniClass instances (I don't fully understand why I can > save and retrieve Form1 values when I instantiate the IniClass in the > initialization section of Form1...How can you set Form1's Top, > Height, etc. before Form1 has been created?). You can't. That might be a source of some of your problems. > At first I tried initiating an instance of the IniClass in the Form1 > OnCreate event, Wait just a moment. It's not the Form1 OnCreate event. Form1 is a variable. Like I said above, it may refer to one of many instances of the TForm1 class. OnCreate is a method of TForm1. It doesn't belong to a variable. This is part of a larger issue, which I'll get to. > passing a reference to Form1 itself to the > IniClass--thinking that would allow me to pass not only properties > from Form1 but also therefore Form1's components, or at least Form1 > public properties that I created to hold class level variables. OnCreate belongs to the entire class, not just one variable of that class's type. _Any_ instance of TForm1 might have the OnCreate method called on it. You don't really want _all_ of those invocations to always load or save data for the single instance referenced by the global Form1 variable. Rather, you want each invocation to load or save data associated with the TForm1 instance upon which the OnCreate method was just called. In other words, you want each form to have data loaded or saved for itself. That's what the Self variable is for. In fact, it would be best if you simply deleted the Form1 variable from your program altogether. There is (almost) absolutely no need for it. All it does is encourage poor programming practice. (Don't take this personally. I blame Borland, not you!) There is just one place where you need a standalone variable for Form1. That's in your DPR file, right above the one (!) call to Application.CreateForm. CreateForm needs a variable, but you don't need that variable anywhere else. var Form1: TForm1; begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. > Form1's properties are properly set, but Form1 component properties > and variables aren't passed: > > type > TIniClass=class(TObject) > private > public > procedure readConfig (var Form1:TForm); > procedure write Config (var Form1:TForm); Based on what I wrote above, you should now recognize that you don't need the "var" part on either of those methods. Neither one of those methods will cause the actual parameter to refer to a different TForm instance. But there's another problem with those declarations. Those methods are declared to receive references to a TForm. That's *any* TForm. That's the TForm class declared in the Forms unit. So you ask why you can't access any fields or properties of your form class? Well, that's because TForm doesn't _have_ any such fields or properties. TForm only has what was given to it in Forms.pas. All your fields and properties were added in your TForm1 class declaration. If those configuration methods are always going to act on TForm1 instances, then change their declarations to use TForm1 instead of the generic TForm. > I sort of understand why component properties would be inaccessible, > but I don't understand why the class properties wouldn't be > accessible. Just a note on terminology. When you place a component on your form in the Form Designer, the IDE declares a new *field* in the corresponding class declaration. Those components aren't properties. Properties are things declared using the "property" keyword. And just to add to the confusion, Delphis 2005 and 2006 support the notion of a "class property," which is different from a regular property. They're like class methods, which are methods that can be accessed without referring to any instance of the class. Likewise with class properties. You don't need an instance of the class, and accessing the property through an instance reference will always access the same value shared between all instances. Probably not what you were intending to talk about. -- Rob _______________________________________________ Delphi mailing list -> [email protected] http://www.elists.org/mailman/listinfo/delphi

