What is an interface in delphi. Abstract: Use of open interfaces of Delphi programming environment. Standard interface elements

One and the most strengths environments Delphi programming is its open architecture, thanks to which Delphi allows a kind of metaprogramming, allowing you to "program the programming environment". This approach brings Delphi to a qualitatively new level of application development systems and allows you to embed additional tools 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. File Interface (FileIntf.pas module) allows you to redefine the working file IDE system, which makes it possible to choose own way file storage (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 response 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 slightly complicate the functional load of the Expert Advisor: when its menu item is activated, it will issue a certificate about the name of the project opened in this moment in the environment: In this example, the central place is occupied by the AddIDEMenuItem function, which adds a menu item to the main menu of the Delphi IDE. As parameters, it receives the text of the new menu item, its identifier, the identifier of the item before which the new item is inserted, character representation key, which together with the Ctrl key can be used to quickly access a new item, and an event handler corresponding to the selection of a 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 when projects are closed/opened 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 is used to feedback with an expert (method TAddInNotifier.FileNotification). 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 issues messages about each act of saving a project file (for brevity, the implementation of the methods we already know is not given): 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 the expert menu item is selected, 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.

Object-oriented programming (OOP), in addition to the concept of a class, also provides for the fundamental concept of an interface.

What is an interface and what are the features of working with it in the Delphi programming language?

An interface is a semantic and syntactic construct in program code used to specify the services provided by a class or component (Wikipedia).

In fact, an interface defines a list of properties and methods that should be used when working with a class that implements this interface, as well as their signature (name, data type, accepted parameters (for procedures and functions), etc.). Thus, a class that implements an interface must necessarily implement all of its components. Moreover, in strict accordance with the way they are described in it.

Very often, interfaces are compared with abstract classes, but for all the similarities, this comparison is not entirely correct. In abstract classes, at a minimum, control over the visibility of members is available. At the same time, scopes are not defined for interfaces.

Interfaces allow you to make the architecture more flexible, as they unify access to one or another functionality, and also allow you to avoid a number of problems associated with class inheritance (interfaces can also be inherited from one another).

Delphi uses the interface keyword to declare an interface. This is the same keyword that defines a module section that can be accessed from outside (between keywords interface and implementation). However, when declaring an interface, a different syntax is used, similar to declaring classes.

Delphi/Pascal

IMyNewInterface = interface procedure InterfaceProc; end;

IMyNewInterface =interface

procedure InterfaceProc ;

end ;

Thus, the interface declaration syntax itself has no fundamental differences from other programming languages ​​(the syntax features based on Pascal do not count). At the same time, the implementation of interfaces has a number of characteristic features.

The fact is that Delphi interfaces were originally introduced to support COM technology. Therefore, the IInterface interface, which in Delphi is the ancestor of all other interfaces (a kind of analogue of TObject), already contains three basic methods for working with this technology: QueryInterface, _AddRef, _Release. As a result, if a class implements any interface, then it must implement those methods as well. Even if this class is not designed to work with COM.

Due to this feature of the IInterface interface, in Delphi usage interfaces, in most cases, leads to the addition of obviously unused features to the class.

There is a library class TInterfaceObject, which already contains the implementation of these methods and, when inheriting from it, there is no need to implement them yourself. But since Delphi does not support multiple class inheritance, its use often only causes additional complexity in the design and implementation of already required functionality.

All this led to the fact that, despite all the possibilities provided by interfaces, their practical use in Delphi almost did not go beyond working with COM.

Being optimized to work mainly with this technology, the interfaces, or rather the functionality and architectural restrictions that they add without fail, do not justify themselves when solving other problems.

Therefore, many Delphi programmers are still, in fact, deprived of a powerful and flexible tool for developing application architecture.

Creation interface the user is reduced to selecting from the palette of components the Delphi components necessary for the operation of the program, which serve interface management, as well as interface displaying information, and transferring them to the Form with subsequent layout.

The user interface you create should use standard, user-familiar elements and provide maximum convenience. All this is ultimately determined by such a criterion as the effectiveness of the interface - the maximum result with minimal effort.
The principles of creating a user-friendly interface are known. as the most general principles When creating user interfaces, three main points can be considered:

  1. The program should help accomplish the task, not become the task.
  2. When working with the program, the user should not feel like a fool.
  3. The program should work in such a way that the user does not consider the computer a fool.
First principle- this is the so-called "transparency" of the interface. The user interface should be intuitive, easy to learn, and not create problems for the user that he will have to overcome in the process. Use standard, unadorned components, use the usual controls used by similar programs, and you will achieve the performance criteria first principle.

Second principle lies in the neglect of the intellectual abilities of users. From my own experience, I know that often users not only do not know how to work at a computer, but are simply afraid to do anything on their own. Therefore, the user interface should be as friendly as possible.
Moreover, the fears of users are often justified, because the cost of the program, and the computer itself, cannot be compared with the cost, for example, of a database created by many years of effort. That is why the programmer, when creating a user interface, must always build in the program "fool protection" - from wrong actions and user input of incorrect data. But some programmers get too carried away with such protection, make it too intrusive, and as a result, the program's operation resembles the famous "step left, step right is considered an escape"! And what a programmer creates as a solution to a problem, itself begins to create problems.
To comply second principle there is no need to allow the program to "correct" the user's actions and indicate what exactly to act for him, driving him into a narrow framework. Also, one should not get too carried away with the display of informational hint messages, especially dialog ones, as this distracts the user from work. And it is better to provide for the possibility of disabling prompts altogether.

Third principle is to create a program with the greatest possible "mental" abilities. Despite the rapid development computer technology, even widespread programs can only very conditionally be called having artificial intelligence. They interfere with the user experience by displaying dialog boxes with stupid questions that cause bewilderment even in the simplest situations. As a result, users in their hearts exclaim: "Well, this car is stupid!"
Personally, I am annoyed by the constant questions of almost everyone. text editors about whether to save the changed text, although the original and current text do not differ by a single character. Yes, I typed something, but then I returned everything back, is it really impossible to figure it out! I have to check to see if I messed something up.

Try to adhere to the following rules:

Standard interface elements
Use standard components for this interface element. Having met your program, the user will not waste time getting to know each other, but will immediately start working - this is one of the signs of a professionally made program.
Small palette of tools
Try not to use too many different components. And of course, using one standard component somewhere in one place, in a similar case also use it.
Equal spacing between controls
Arrange interface elements at the same distance from each other. The randomly scattered components create the feeling of an unprofessional product. And vice versa, carefully calibrated placement on the Form of buttons, switches, checkboxes and other components that make up the interface is a sign of quality work.
tab order. "correct" order
TabOrder is the order in which the screen cursor moves over the controls when a key is pressed Tab. In a correctly written program, the cursor moves, following the logic of the user's work with the program. When creating a program, the programmer often changes components, removes some, adds others as needed. As a result, in finished program the cursor randomly jumps over the Form. After completing the program, do not forget to set TabOrder.
Font selection
Just leave fonts alone. Delphi's own default fonts will work for any system your program might run on. Use bold font only to highlight important elements. Application cursive and especially underlining, which the user may mistake for a hyperlink - bad form.
Choice of colors
As for the colors of the interface elements, just as in the case of fonts, it is better to leave them standard, by default. Delphi uses the Windows system palette, and by changing it, the user can easily customize the colors for themselves.
Alternative management
A professionally made program should be able to be controlled not only with the mouse, but also with the keyboard. There should be no functions available for execution only with the mouse (drawing in graphic editors doesn't count!). For the most used functions, "hot keys" should be provided for their quick access.
Interface building blocks
With regard to specific elements of the user interface, the quality of user interaction with the program depends on:
  • compliance of the control element with its task;
  • the rules by which the control operates.
    This page discusses the rules for creating some interface elements.
And now I want to show what tools Delphi offers for managing components on the Form, their relative position and cursor behavior when a key is pressed. Tab.

In order to arrange the components relative to each other in the correct order, first need to highlight them. You can simply drag the mouse over the area on the Form that contains the selected components. Or by holding Shift", specify with the same mouse each component to be selected. Repeated mouse click on the selected component (while pressing " Shift") deselects it.

Selected components can be managed as a single whole - moved around the Form, assigned values ​​to the same properties, copied (for installation, for example, on another Form), even deleted.

Now click right click one of the components, and from the "pop-up" menu, select Position -> Align... A dialog box will appear allowing you to adjust the position of the components in the group horizontally and vertically. For example, we need to align our four buttons to the left and make sure they have the same vertical spacing between them. To do this, select the radio buttons Horizontal: left sides And Vertical: Space equally.

Selecting an item Center, we will arrange the components so that their centers will be located on the same line horizontally or vertically, and the point Center in window moves components to the center of the window, either horizontally or vertically.

In the same menu, the line Tab O order... causes the appearance of a dialog box that controls the movement of the cursor through the interface elements when a key is pressed Tab. When the Form appears on the screen, the cursor will naturally be on the component located on the first line of the dialog box. And then it will move down the list. On the dialog box, two blue arrows "up" and "down" control the position of the selected component. Select the desired component, use the arrows to move to the desired line in the list, and so on.

When selecting a menu item Control -> A submenu appears with two items:

  • Bring to Front
  • send to back
These are component methods that are also available programmatically. Button1.SendToBack moves the button to the "background", and Button1.BringToFront- bring to Front". That is, if one component is placed above another, these methods swap them. The cases in which this can apply are fairly obvious. 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, to varying degrees, have already been touched upon more than once in this blog, 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.