How to get list of objects accessible to a project? - delphi

I'm trying to figure out how to access a list of objects available in the Delphi IDE (ie., from different namespaces) from within a component editor. (Also from the same editor form running independently.) LiveBindings do it, and there's a video where they say you have to have a unit listed in a uses clause in order for the LiveBinding editor to see the classes defined inside that unit. But it does not have to be a form.
I can access forms through the Application.components array, but that only gives me access to the TForm objects. Any classes defined in the same units with the form aren't visible, nor are classes defined in any units that are not forms.
Someone suggested the answer lies buried somewhere in the Open Tools API.
I thought there might be someone here who could shed a bit more light on the subject.
BTW, I'm using DXE5, but anything from version XE and up is probably the same.
NOTE: I did find a property somewhere that lists every single class and record defined in the entire freaking ecosystem. There are hundreds of them! That's not much help. Still looking.

Related

dwscript - how to enumerate all available types?

Hey,
Delphi Web Script is really great scripting engine. I'm trying to use it in one of my projects. However, I'm not sure if it is possible to enumerate all the types, functions that are available within the scripting engine, e.g. I want to have a list with all the methods which I could use while scripting (this includes all the internal and external types, functions, procedures, etc.). Fast script has the treeview component which exposes all the types you can use. I'm looking for something like this in dwscript. Thanks in advance.
You'll find all the types in the symbol tables (TSymbolTable) that are attached to every compiled DWScript entity, you have one in the compiled programs, in the compiled functions/methods, and in the blocks that have a scope.
If you want to enumerate all the symbols visible in a particular scope, you'll have not only to look at what a particular TSymbolTable contains, but also look at its parents (which are TSymbolTable too), which hold the symbols from the parent scopes (including unit and library symbols). For class methods & types, you'll find them in the Members[] of a TClassSymbol.
DWS2 repository on sourceforge contains some samples which haven't been converted yet in the DWS2.x repository, but should be reasonably straightforward to adapt.

Where should I put my utility methods? How can I used my customized form? (Delphi)

I've been using Delphi for a little over a month, but I still do not know the proper way of doing things.
If I have methods which I can use on a lot of projects should I put them on a Unit, Form or DataModule?
I have not used a unit (in itself), New-> Unit. Should I put my utility methods there? If so, is there an example I can look at, a tutorial or whatever.
I've used DataModules in the past, though it gives me the impression that it should only be used when I'm dealing with databases and such.
Another thing, I'm customizing some forms (for instance a form with some TEdits that do specific things).
To use this, first I add this to the uses in the .dpr
CustomizedForm in '\CForm\CustomizedForm.pas' ;
then I add CustomizedForm to the uses in my mainform (where I'll be using it).
Is this the correct way to do it? I'm was just guessing, it seems to work though I'm not particularly confident that it's the proper way.
I put all mine in a unit called utils.pas. It works for me.
If you have different segmentations of utilities that some programs use but not others, you may want to create separate units for them.
Look at: Anatomy of a Delphi Unit
It is part of the excellent Beginner's Guide to Delphi Programming by Zarko Gajic that is very worthwhile to go through.
For the best "visual" introduction, see Nick Hodges' Thirty Camtasia Demos in Thirty Days. It is for Turbo Delphi which no longer is offered, but is still very similar to full Delphi and lets you visually get a feel for how to do things in Delphi.
Where you put things depends on what they do. The unit associated with a form should really only contain code that's directly related to the user interface that the form presents. Putting business logic directly into a form unit is considered bad practice for a number of reasons. If your utility methods aren't part of a specific form, it's best to put them in a Unit.
As for Data Modules, they're containers for holding non-visual controls. As the name implies, they were created for database access, but they can hold all sorts of other things. For example, at work we have a handful of data modules that contain TImageList controls, which hold lists of icons that are used in various places throughout the app. If you have any non-visual controls that you need to share with several different forms, a Data Module is the logical place to put them.
And yeah, it looks like you're doing the customized form right. If you have a second form that the first form needs access to, (to make it show up when you hit a button or menu item, for example,) then the first form's unit will need the second form's unit in its uses clause. (There are ways around this involving class registration techniques, but that's an advanced topic.)
You might want to avoid using the global form variable that Delphi likes to set up in a form unit, though. It makes your program start up more slowly, and using globals is another thing that's considered a bad practice. A form is an object like any other Delphi object, and you can create it with its constructor, call Show or ShowModal to make it appear, and then call Release or Free on it (read up on TForm.Release in the helpfile to know when you need to use it) when you're done with it.
For starters, create a few different units based on categories - StringUtils.pas, MathUtils.pas, DateTimeUtils.pas, etc - put your functions into those units according to category and be sure to include all the prototypes in your interface section so they'll be visible to other units (but don't get too caught up in how to categorize things...) and keep all your util units in a separate, dedicated directory. Then, point your Delphi or Project library paths to that directory and you'll be able to use the functions in all your utility units. Eventually, you may want to make the units into classes with class functions or persistent structures etc. I myself generally create a project group that includes a package called MyProjectUtils.bpl and I put all my utility units and classes into that package. I never actually deploy it as a package, but since they are wrapped up together I can always check that they all compile properly and they are all available immediately for browsing in the IDE, etc.

How to share variables among libraries in Delphi 2009?

I'm trying to divide my monolithic, Delphi-Win32 app in libraries, so I get some questions around how to share global variables and object among my libraries using Delphi 2009. For example, I have 3 global objects (derived from TObject): for user info, for current session info, and for storing the active database connection and managing operations with this database. My libraries require to work with these objects. Moreover certain libraries would give an object derived from TForm to be hosted for another parent control into the main form. Every object derived from TForm passed to main form has its own methods and properties, that is, their classes are different each other.
I'm thinking to put the global objects into a separate library but I guess that it would make things more difficult, but consider it, please.
How to get to work this situation?
One question more, which is better to use: static or dynamic loading for libraries?
Can you recommend some books or sites to learn more about this?
Thanks in advance.
What we have done in the past to share variables between modules (we used BPLs) was to pass them through a shared TStringList. Generally speaking it is best to have a global shared object with all your shared variables in it.
Anything that is going to be referenced between more then one library must be in its own library. Mason's advice was sound.
Go with static loading, unless you really need dynamic for some specific reason (which it doesn't sound like). Let the windows memory manager swap out unneeded libraries from memory.
One tip from someone who managed a large application split into multiple libraries. We had our components in packages, the VCL, some application common routines, and then a library for each "screen" or segment of the application. For changes to the screens, it was possible to just release that one updated library, but for changes to any of the other types of libraries, we found we usually had to redeploy everything. So it was rare we enjoyed an advantage from the configuration.
It seems that by "libraries" you mean BPL Packages, so here are the guidelines:
Each BPL, when it gets loaded, loads all the units in it. No unit can be loaded more than once. That means that if more than one package needs access to one of the globals, then it has to either be in one package that the other(s) have in their Requires list, or in a separate package that all the others Require.
As for static vs. dynamic loading, if your program absolutely needs it, make it statically linked. Dynamic loading is for optional features, such as plug-ins. (If you want to go that route, take a look at JVPlugin in the JVCL. It's a very useful system.)
I do NOT understand why is people mentioning the Delphi version for a simple question like this, the answer is yes it is better to put shared variables in a separate unit before the implementation keyword.
Every object(form, class, control) is derived from TObject, even if you define a class like
type TMyClass = class
// no inheritance ?
end;
the above class is still derived from TObject(read Delphi help).
Your global variables could be declared of type TObject or Pointer and when you access them use hard cast TForm(MyPointerVariable).Method, i.e.
var MyPointerVariable: Pointer; // I presume it is already initialized and is a pointer to a TForm descendant
...
begin
TForm(MyPointerVariable).Caption := 'Stack Overflow';
end;
For more information read Delphi tutorial on my blog it should be very simple to understand.

Creating a custom form designer

I'd like to create a custom "datamodule" in Delphi, a TDataModule like (maybe inherited) class which would have a custom grid based design interface (one component per line, some properties as columns). Is this possible? Where should I start?
I'm currently using Delphi 2007.
Maybe it is possible. An example of a XML Frame Designer can be found on the page New IDE Building Blocks. Well this example is for Delphi 5, but it might be a good starting point.
As Nick Hodges pointer out here:
Drawing on a DataModule in Delphi
it would be difficult to paint on the TDataModule descendant. Not impossible probably, but not worth the trouble for sure.
I would consider designing a completely new TDataModule from scratch, so you would have complete control over it. Sure a lot of work probably, but in the end it would pay off.
You can find TDataModule class in the Classes.pas unit. But this is just the runtime part of the code. Other parts are IDE related. You can find units related to ToolsAPI in "c:\Program Files\Borland\BDS\4.0\source\ToolsAPI\" for BDS 2006 for instance. You can also derive you own data module from TDataModule and register it with RegisterCustomModule (DesignIntf.pas). I don't know much more on this subject, maybe others do. As I said it would not be easy to do something like that. But maybe with this initial information you can find what you want.
It's not possible exactly as you describe it. You can't place visual components like a grid on a data module. You need a form or frame for that.
If I were to do try to something like you're describing, I'd use a list box to hold a list of individual components, a couple buttons and a selection dialog box for adding and deleting components from the list, and the TJvInspector component from the JVCL for modifying properties. That would be a lot easier than trying to make a one-size-fits-all grid to handle the situation.

Interposer class

Do I need to put my Interposer class in
all the form that will the particular class ?
Say I want to re-implement TPanel, I redeclare
it as TPanel = class(ExtCtrls.TPanel) in the unit.
Do I need to do this in all the unit that uses
TPanel ?
Thanks in advance !
You yourself have acknowledged that this is a hack. It's not meant to scale well. It's meant for one-time cases where it's not worth the trouble to "do it right" by writing a bona fide custom control.
You can try putting your new class declaration in a separate unit. Make sure that unit appears on uses clauses after the VCL unit that declares the "real" version of the class. If that doesn't work, then yes, you need to make new declarations in every unit that uses the hack.
Since you're doing this to turn TLabel into TStaticText, you'd probably be better off simply changing your TLabel controls into real TStaticText controls on your forms. (That was the answer the last time you asked about this.) That way, the program you ship will be the same program you tested. Otherwise, you're testing a program with one kind of control and shipping one with another.
If you want to design a new component, you'll have to give it a unique name. Otherwise the form designer and the serialization code won't be able to tell them apart. Call it TRoderickPanel or something. Then just replace all your TPanel objects with TRoderickPanel objects on every form that uses them. (GExperts adds a right-click option that makes this much easier.)
Depending on the functionality you are trying to add, you could consider using a class helper. If what you need cannot be done that way, I'd just bite the bullet and create a new class like Mason said. Replacing it right through your code is not that hard really, given that form files are also stored as text.
If you also have Visual Studio installed, that actually has a "Replace in files" command. On top of that I'm sure Google will be able to help you out with stand-alone tools. And I haven't used GExperts in a while, but I'm almost certain that had a "Replace component" command.
This is a far better solution for the long term. If you can use a class helper for what you need, that may be quicker, simpler and less work.
I would instead use the GExperts wizard to replace components to get the behavior you are wanting. Doing what you are suggesting would require re-registration of the components so that the DFM loading mechanism created the proper components, and if I'm not mistaken, the component registry doesn't allow duplicates so would generate an exception. What your suggesting works well with classes, but not components used on a form.
You can put your interposer class into a Unit and add that unit on the uses clause of all units where your interposer needs to act. Pay attention to add this unit AFTER the unit ExtCtrls on the uses clause, otherwise, it will not work

Resources