Delphi what interfaces are for. Abstract: Use of open interfaces of Delphi programming environment. Everything is always visible

This article is based on questions on the forums: "How do I return a string from a DLL?", "How do I pass and return an array of records?", "How do I pass a form to a DLL?".

So that you do not spend half your life figuring it out - in this article I will bring everything on a silver platter.

The topics of this article have been touched upon more than once in this blog to varying degrees, but in this article they are collected in a heap, justifications are given. In short, a link to this article can be thrown at those who develop the DLL.

Important note: article must be read successively. Code examples are provided only as examples, at each step (point) of the article, the code of examples is added with new details. For example, at the very beginning of the article there is no error handling, "classic" methods are indicated (such as using GetLastError , sdtcall conventions, etc.), which are replaced by more adequate ones in the course of the article. This is done for the reason that "new" ("unusual") designs do not raise questions. Otherwise, with each example, one would have to insert a note of the form: "this is discussed in that paragraph below, but that - in this one here." In any case, at the end of the article there is a link to a ready-made code written taking into account everything said in the article. You can just take it and use it. And the article explains why and why. If you are not interested in "why and why" - scroll to the end to the conclusion and a link to download the example.

One of the greatest strengths of the Delphi programming environment is its open architecture, which allows Delphi to allow a kind of metaprogramming, allowing you to "program the programming environment." This approach takes Delphi to a qualitatively new level of application development systems and allows you to embed additional tools in this product that support almost all stages of creating application systems. Such a wide range of possibilities opens up thanks to the concept of so-called open interfaces implemented in Delphi, which are the link between the IDE (Integrated Development Environment) and external tools.

This article focuses on Delphi's open interfaces and provides an overview of the features they provide. Delphi defines six public interfaces: Tool Interface, Design Interface, Expert Interface, File Interface, Edit Interface, and Version Control Interface. It is unlikely that within the framework of this article we would be able to cover in detail and illustrate the possibilities of each of them. The source texts of Delphi will help you to understand the issues under consideration more thoroughly, since the developers have provided them with detailed comments. Class declarations that represent public interfaces are contained in the corresponding modules in the ...\Delphi\Source\ToolsAPI directory. The Design Interface (module DsgnIntf.pas) provides the means to create property editors and component editors.

Property and component editors are a topic worthy of a separate discussion, so we only recall that the property editor controls the behavior of the Object Inspector when you try to change the value of the corresponding property, and the component editor is activated when you double-click the left mouse button on the image of the component placed on the form. The Version Control Interface (VCSIntf.pas module) is designed to create version control systems. Starting with version 2.0, Delphi supports the Intersolv PVCS integrated version control system, so in most cases it is not necessary to develop your own system. For this reason, we will also omit consideration of the Version Control Interface. The File Interface (FileIntf.pas module) allows you to redefine the IDE's working file system, which makes it possible to choose your own way of storing files (in Memo fields on the database server, for example). The Edit Interface (module EditIntf.pas) provides access to the source text buffer, which allows you to analyze and generate code, determine and change the cursor position in the code editor window, and control source text syntax highlighting.

Special classes provide interfaces to the components placed on the form (defining the type of component, getting references to parent and child components, accessing properties, passing focus, deleting, etc.), to the form itself, and to the project's resource file. The Edit Interface also allows you to identify the so-called module notifiers that determine the reaction to events such as changing the source code of the module, modifying the form, renaming the component, saving, renaming or deleting the module, changing the project resource file, etc. Tool Interface (module ToolIntf. pas) provides developers with a means to get general information about the state of the IDE and perform actions such as opening, saving and closing projects and individual files, creating a module, getting information about the current project (number of modules and forms, their names, etc.) , registration file system, organization of interfaces to individual modules, etc. In addition to module notifiers, the Tool Interface defines add-in notifiers that notify about events such as opening/closing files and projects, loading and saving a project desktop file, adding/excluding project modules, installing/uninstalling packages, compiling a project, and in Unlike modular notifiers, add-in notifiers allow you to cancel the execution of some events.

In addition, the Tool Interface provides a means of accessing the main menu of the Delphi IDE, allowing you to embed additional items in it. Expert Interface (module ExptIntf.pas) is the basis for creating experts - software modules that are built into the IDE in order to expand its functionality. An example of an expert is the Delphi Database Form Wizard, which generates a form for viewing and modifying the contents of a database table. Having defined the expert class, we need to make sure that Delphi “learns” about our expert. To do this, it must be registered by calling the RegisterLibraryExpert procedure, passing it an instance of the expert class as a parameter. As an illustration, let's create a simple expert in the esStandard style, which, when the corresponding Delphi menu item is selected, displays a message that it is running. As you can see from the table above, the esStandard style requires six methods to be overridden:

In order for the expert to be “activated”, you must select the menu item Component/Install Component ... , select the module containing the expert (in our case exmpl_01.pas) in the Browse dialog, click OK, and after compiling the dclusr30.dpk package in the Delphi main menu in the Help section, the Simple Expert 1 item should appear, when selected, the informational message “Standard Expert started!” appears. Why Delphi puts the expert menu item in the Help section remains a mystery. If you don't like the fact that the menu item appears anywhere in Delphi, and not where you want, the following option is possible: create an add-in style expert, which eliminates automatic creation menu item, and add the menu item “manually” using the Tool Interface. This will allow you to set the location of the new item in the main menu in an arbitrary way.

To add a menu item, the TIToolServices class is used - the basis of the Tool Interface - and the TIMainMenuIntf, TIMenuItemIntf classes that implement interfaces to the IDE main menu and its items. The ToolServices instance of the TIToolServices class is created by the IDE itself when it is initialized. Note that it is the developer's responsibility to release the interfaces to the Delphi main menu and its items. Along the way, let's complicate the functionality of the Expert Advisor a little: when its menu item is activated, it will issue information about the name of the project currently open in the environment: As parameters, it is passed the text of the new menu item, its identifier, the identifier of the item before which the new item is inserted, the symbolic representation of the key that, together with the Ctrl key, can be used to quickly access the new item, and the event handler corresponding to the selection of the new item. We've added a new menu item to the View section before the Watches item.

Now let's get acquainted with notifiers. Let's define an add-in notifier that tracks the moments of closing/opening projects and adjusts the field that stores the name of the active project accordingly (we omit the implementation of methods that have not changed compared to the previous example for brevity): To implement the notifier, we defined the TAddInNotifier class, which is a descendant of TIAddInNotifier and override the FileNotification. The IDE will call this method every time an event occurs that the add-in notifier can respond to (each such event is denoted by the corresponding TFileNotification type constant). The Expert field in the TAddInNotifier class serves for feedback with an expert (the TAddInNotifier.FileNotification method). In the expert's destructor, the registration of the notifier is unregistered and the notifier is destroyed. Now let's illustrate the use of modular notifiers. Let's create an add-in expert that generates messages about each act of saving a project file (for brevity, we do not provide the implementation of the methods already familiar to us): In this example, the add-in expert monitors events corresponding to the opening/closing of projects.

Each time a project is opened, a module notifier corresponding to the project file is registered. In terms of implementation, modular notifiers are similar to add-in notifiers: we define a TModuleNotifier class that is a descendant of TIModuleNotifier and override its Notify and ComponentRenamed methods. The IDE calls the Notify method when certain events related to this module occur; inside this method, the reaction to a particular event is determined. The ComponentRenamed method is called when the name of the component that is on the module form changes. Please note that we do not use this method, but we must override it, otherwise, when the name of the component changes, the abstract method of the base class will be called, which leads to unpredictable consequences.

Registering a module notifier is somewhat more complicated than registering a notifier add-in: first we get the module interface (TIModuleInterface) and then register the notifier using the module interface. When the project is closed, the module notifier is unregistered (again using TIModuleInterface) and the notifier is destroyed. In conclusion, we will show how you can determine the position of the cursor in the code editor window. Let's create an Expert Advisor that, when the corresponding menu item is selected, would display a message containing the name of the active file and the position of the cursor in it (the implementation of only those essential for this example methods): To determine the cursor position, we must obtain the following sequence of interfaces: module interface (TIModuleInterface); code editor interface (TIEditorInterface); module view interface in the editor window (TIEditView).

If the active file with the source text (*.pas) is active when selecting the expert menu item, then a message is displayed containing the name of the active file and the current position of the cursor in it. If the active file is not a pas file, no message is issued. The GetCurrentFile method of the TIToolServices class is used to get the name of the active file. This concludes our discussion of ways to use public interfaces. The CD-ROM contains the source code for all the examples given. The CD-ROM also contains a more complex and extended example containing an add-in expert that allows the user to bookmark the source code of Delphi modules. A quick guide to installing and using the Bookmark Expert is contained in the bkmrks97.htm file. So, in this article, public interfaces are discussed in general terms and examples of their use are given. Once again, thanks to the availability of source codes of open interfaces, you can easily understand the details that interest you. We hope that the variety of possibilities provided by open interfaces will give you more than one bold and useful idea.

just for results

strict adherence to deadlines

Transparency

project implementation

technical support as a gift

Programming, improvements, consultations on 1C

How we are working

1. We discuss the problem by phone. If you have remote access - show on your computer screen.

2. We evaluate the work in rubles if the project is large, if not - the approximate number of hours.

3. We get the job done.

4. You accept work in your program, if there are shortcomings, we correct them.

5. We issue an invoice, you pay.

Cost of work

1. All works are divided into 3 categories: consultation, updating a typical configuration, developing or programming a new report, processing, buttons, etc.

3. For work over 10 hours, a technical task is prepared in advance with a description and cost of the work. Work begins after the approval of the TOR with you.

Technical support

1. If you find any errors in previously accepted works, within 3 months, we correct them for free.

2. For regular customers, we fix any shortcomings in our work free of charge within a year.

Programs for managing your business.

Buy 1C:Enterprise

We are the official dealer of 1C, you can purchase from us various software products and licenses. In addition to buying a "box", we will help you set up the program, consult and make basic settings.

  • Accounting
  • Store automation
  • Wholesale
  • Help with installation and initial setup is included in the package!
  • Fine-tuning configurations to the needs of the customer, development of new modules in the absence of the necessary functions in the standard configuration.
1c accounting 1C: Trade management 1C: Retail 1C: Payroll and Human Resources Management
From 3300 rub. From 6700 rub. From 3300 rub. From 7400 rub.

Providing a server.

Instant setup server + 1C.

No server? It doesn't matter, we will select and quickly set up a server in the "cloud". Behind a small fee you get a very reliable solution.

  • Availability 24\7
  • No need to keep your own system administrator (the savings will cover the cost of your server).
  • Quick setup and installation of 1C on the server, in 3 days you will already have a fully working system.
  • At any time you can move to local server if the solution is not satisfactory.

SMS from your 1C

Do you want customers to learn about promotions and discounts in time? Clients not returning? Set up SMS sending directly from 1C!

Our company will be able to quickly set up sending SMS to your customers directly from 1C. Examples of events that can be automated:

  • Gratitude for the purchase and accrual of bonuses immediately after the next purchase.
  • Accrual of bonuses to the card as a gift for a birthday/another important or holiday day.
  • Warehouse notification.
  • Gift voucher expiration.
  • Notification of receipt of prepayment and reservation of goods.
  • Address with directions to the store/office, phone numbers.
  • Etc.

Setting in 1C can be done by our specialists or our employees. You can get acquainted with the tariffs on the SMS-tariffs page.

  • SMS delivery guarantee, money is withdrawn only for delivered SMS.
  • Separate billing for each SMS.
  • Replenishment of the balance in various ways.
  • View the history of all sent SMS at any time.
  • The sender's name instead of the numeric number on the recipient's phone.

The article was written based on the results of analyzes of programs written by young developers of our group.

Correctly arrange the switching sequence of components

Many users, especially those who have previously worked in DOS, have a habit of switching between input fields not with the mouse, but using the keyboard with the Tab key. In addition, it is much faster than selecting each field with the mouse. Therefore, the switching order of the components must be set correctly. This applies both to components inside all container components (panels, GroupBoxes, and the like), and to the container components themselves, if there are several of them on the form.

The switching order of components inside the container is set by the TabOrder property. The first component to become active is the one with TabOrder equal to 0, the second one with 1, and so on, until all components have been iterated over. In addition, the component has a TabStop property, which indicates whether the component will receive focus when switching with the Tab key. If you need to disable switching to any component, set TabStop = false for it. In this case, it will be possible to switch to this component only with the help of the mouse.

There are times when users who are accustomed to switching a certain key in one program, out of habit, continue to use it in others. This often happens with 1C users, where the Enter key can be used to navigate through the input fields. Well, let's give them that opportunity in our programs if they ask for it. Set the form's KeyPreview property to true and write the OnKeyPress event handler:

Procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if ord(key)=vk_Return then
Form1.SelectNext(PriemForm.ActiveControl, true, true);
end;

Such a handler provides a transition through the form elements when the Enter key is pressed. It should be noted that this method will not work with buttons, because pressing Enter on a button causes it to be pressed, while pressing Tab transfers input focus to the next component in the switching sequence.

Default buttons

All the same users quickly get used to the fact that in application dialog boxes, as a rule, you can confirm your choice with the Enter key, and cancel with the Esc key. Let's not disappoint them in our programs, especially since it's very easy to do. For the Enter button, set the Default property to true. For a button that responds to Esc, set the Cancel property to true. And that's all.

Yes or no

Everything dialog boxes, requesting user actions, must have at least two buttons: confirmation of action and refusal of action (Yes / No, Save / Cancel, etc.). The action can be canceled by closing the window with the [X] button in the window title. It is invalid if there is only one button for confirming the action, and for refusal it is supposed to close the window with the button [X] in the title, or there is no possibility of refusal at all. This confuses the user, causing a logical question: how to refuse?

Also, do not forget about what was said above in the paragraph "Default buttons".

All dialog boxes should open in the center of the screen

Centered instead of where they were created in design mode. Firstly, it is more visual, and secondly, it automatically eliminates the problem of different screen resolutions for different users.

An exception is made if the dialog box is not modal, and as a result of the user's work in this window, changes immediately occur in the main window (for example, filtering a data set, redrawing graphs, etc.).

Window sizes should not exceed screen sizes.

In no case. It's a disgrace when part of the window crawls out of the screen. This requirement does not depend on the user's screen resolution, i.e. excuses like "Let them put a higher resolution" do not work.

Correct resizing of window elements

Window elements must correctly resize or move when the window is resized, when the window is maximized, and when the window is restored after being maximized.

Everything is always visible

Reducing the size of the window should not lead to the disappearance of window elements and preferably should not lead to the appearance of scrollbars (scrollers) of the window itself. You can limit the minimum size of the window so that all elements are visible and accessible. If it is not possible to place the components so that everyone is visible in the window, you can use tabs (of the PageControl type) to divide the components into groups. Excuses about screen resolution are also not missed.

Hints everywhere, hints always

For buttons, especially on toolbars (such as ToolBar), hints should be given so that it is always clear why this or that button is needed.

Color spectrum

It is not necessary to paint the components on the form in all the colors of the rainbow. This tires the eyes and scatters the user's attention. It doesn't look "cool". Highlighting is used when it is necessary to draw the user's attention to a particular element or a particular part of the window. For example, you can color the entries with errors in light red color or, on the contrary, light green color of the entries, the verification of which was successful.

Conclusion

There is a very good method that allows you to find the shortcomings of the program in general and the interface in particular. It is simple: imagine yourself in the place of the user and for half an hour try to work the way he works. It's even better if your user is within reach (e.g. works in the same organization). In this case, sit next to him, or rather instead of him, and try to do his job. Enter data, change them, display reports, etc. If you don't know how to do it right, ask your user. Do not one or two operations of the same type, as in debug mode, but 20-30 or even more different operations, in a different order. Forget to enter something or enter it incorrectly and see how the program reacts to it. You will quickly see the weak points of your program.

The author of the article automated the work of the admission committee at the university, and in the first year of the program implementation, he spent 3-4 hours a day at the admission committee, registering applicants, filling in their personal data and giving them exam reports. And in the remaining working time, corrected errors and shortcomings. Believe me, the next year there are practically no problems left. It was the same with the introduction of the personnel module.

Thus, keep the user experience in mind. Let it be easy and pleasant for them to work with your programs.

Share with friends or save for yourself:

Loading...