Hey Designer!

The last article was about the structure and functionality of the plugin interface. In this article, I would like to explain this in more detail with the help of an example.


Introduction

Design forms can be opened in the designer via the Open dialog. Sometimes, however, it would be advantageous to have a wizard that permanently displays a list of existing dialogs that can then be opened simply by double-clicking without having to interrupt work in the designer (analogous to the procedure wizard). This article shows how this can be realized with a plugin application.

The plugin application is supposed to be developed in conzept 16 (see figure below). A preview of the dialog is displayed next to the list (shown in the illustration on the right). The dialog can be opened in the designer by double-clicking on an entry. The same happens by clicking on the Open button. You can open a dialog with a few mouse clicks via the designer, but with the help of the plugin application and the plugin functionality you only need one mouse click.

As our plugin application runs in the same database as the designer, the list with the dialogs can be implemented using the StoList object. We do not need the plugin functionality for this yet. The plugin functions only come into play when the user double-clicks on the list, as the corresponding dialog should then be opened in the designer. Conversely, when a dialog is activated in the designer, the corresponding entry should be selected in the StoList.

Die Abbildung zeigt die fertige Plugin-Anwendung.

Creating the instance and logging in

To receive designer events or send commands, we need to establish a connection between the designer and the plugin application.

The plugin instance and authentication are prerequisites for communication between the designer and the plugin application.
DThe Plugin.Core:InstanceNew() function creates a new plugin instance.

// Create plugin instance
gPluginInstanceID # Plugin.Core:InstanceNew(sPluginPort,sPluginTimeout,gPluginWinFrame);

The plugin application must authenticate itself with the designer on the designer’s port and the correct password so that communication can take place.

The application first waits for authentication of the designer page, which is sent to the plugin application immediately after the connection is established. In the source code, this is done by command Plugin.Converter:ReceiveAuth(). It receives the previously created instance number as an argument. If the authentication was received successfully, the plugin application responds with command Plugin.Converter:ReplyAuth() and sends the password to the designer. If the authentication was successful, command _ErrOK returns the password. This completes the initialisation of the plugin application.

if (gPluginInstanceID > 0)
{
  // Plugin password for authentication
  tPassword # sPluginPassword;

  // Transfer the name of the plugin application to the application log
  tPluginName # 'Dialog-Manager - ' + mIntToAlphaDec(gPluginInstanceID);

  // Authentication
  tResult # Plugin.Converter:ReceiveAuth(_ReceiverByInstanceID,gPluginInstanceID,var tSerial,var tUser,sPluginTimeout);
  if (tResult = _ErrOK)
    tResult # Plugin.Converter:ReplyAuth(gPluginInstanceID,tSerial,tPluginName,var tPassword,sPluginTimeout);

  if (tResult = _ErrOK)
    gPluginWinFrame->wpCaption # tPluginName;
  else
  {
    Plugin.Core:InstanceClose(gPluginInstanceID);
    gPluginInstanceID # 0;

    WinDialogBox(0,aCaption,'Anmeldung fehlgeschlagen.' + StrChar(13) + StrChar(10) +
                     'Fehler ' + mIntToAlphaDec(tResult) + '.',_WinIcoError,_WinDialogOk,1);
  }
//...
}

We close the plugin instance when the user closes the plugin application with the Plugin.Core:InstanceClose() function.

// Close plugin instance
Plugin.Core:InstanceClose(gPluginInstanceID);

Opening a dialog

The following source code excerpt shows how a dialog is opened by the plugin application in the designer when the user double-clicks on an entry.

// Create plugin command
tPluginCmd # Plugin.Converter:CreateCmd(sPluginCmdKindCmd, 'Designer.Forms.Open');
if (tPluginCmd > 0)
{
  // Transfer name and type of dialog
  tPluginCmd->Plugin.Converter:AddArgStr('Name', aValue, sPluginArgStrC16);
  tPluginCmd->Plugin.Converter:AddArgInt('Type', 0);

  // Send command to the designer
  Plugin.Converter:SendCmd(gPluginInstanceID, tPluginCmd);

  // Delete handle of the plugin command
  tPluginCmd->Plugin.Converter:DeleteCmd();
}

Command Designer.Forms.Open is used to open a form object in the designer. A plugin command is created for this with command Plugin.Converter:CreateCmd().

Each command has arguments that must be passed. In this case, the arguments are of type alpha and int. They are set with the functions Plugin.Converter:AddArgStr() and Plugin.Converter:AddArgInt().

aValue contains the name of the form object to be opened.

The type of the form object is defined in function Plugin.Converter:AddArgInt(). As we want to open a dialog, the type must be set with a 0 (frame).

The plugin command is then sent to the designer using the Plugin.Converter:SendCmd() function.

Plugin.Converter:DeleteCmd() löscht das Kommando, um den Speicherplatz wieder freizugeben, welcher mit Plugin.Converter:CreateCmd() belegt wurde.

Selecting the active dialog

When the user performs certain actions in the designer, this sends events to the plugin application. For example, event Designer.Forms.ActivateDone informs the user that they have activated a design form. The plugin application receives the notification via event EvtJob, as the frame handle of the plugin application was specified by Plugin.Core:InstanceNew() when the instance was created. The source code snippet shows the event processing.

sub EvtJob
(
  aEvt                  : event;        // Event
  aJobCtrlHdl           : handle;       // Job control object
)
: logic;

  local
  {
    tInstanceID         : int;
    tPluginCmd          : handle;
    tResult             : int;
    tDialogName         : alpha;
  }

{
  // Create plugin command
  tPluginCmd # Plugin.Converter:CreateCmd();
  // Receive plugin event
  tResult # Plugin.Converter:ReceiveCmd(_ReceiverByJobControl,aJobCtrlHdl,tPluginCmd,var tInstanceID);

  if (tResult = _ErrPluginCoreThreadTerm)
    TermExample();
  else if (tResult = _ErrOK and Plugin.Converter:IsCmdKindEvt(tPluginCmd))
  {
    if (tPluginCmd->Plugin.Converter:IsCmdName('Designer.Forms.ActivateDone'))
    {
      // Determine the name of the activated dialog
      tPluginCmd->Plugin.Converter:GetArgStr('Name',var tDialogName);
      gPluginStoList->wpCurrent # tDialogName;
    }
  }
  return(true);
}

First, a plugin command (Plugin.Converter:CreateCmd()) is created again. Function Plugin.Converter:ReceiveCmd() then receives the plugin event.
If function _ErrPluginCoreThreadTerm returns, the connection to the designer has been terminated. In this case, we terminate the plugin application.

If the plugin command was received successfully, the function returns _ErrOK. In this case, we check whether the received message is event Designer.Forms.ActivateDone. This takes place in two stages. First, the call to Plugin.Converter:IsCmdKindEvt() checks whether the message is an event. If this is the case, we use Plugin.Converter:IsCmdName() to check whether it is Designer.Forms.ActivateDone.

The name of the activated dialog can then be determined with Plugin.Converter:GetArgStr(). To select the entry in the list, only the property wpCurrent of the StoList object needs to be set.

You can find the complete example in database CodeLibrary under the name Plugin.Example.

Klicken Sie hier, um die Nutzungsbedingungen für unseren Blog zu lesen.

Leave a Reply

Your email address will not be published. Required fields are marked *

Leave the field below empty!

Requests, questions or feedback are welcome:

Terms of use of the comment function in the blog

1. General information

Vectorsoft AG (‘Provider’) provides a public blog for Internet users (‘Users’) on the vectorsoft.de website. The public blog is intended for the exchange of information and ideas. Users who participate with contributions and comments undertake to comply with the blog terms of use and are responsible for the accuracy, appropriateness and freedom from legal infringements of their contributions. By using the comment function in our blog, you accept these terms of use.

2. Netiquette

We ask you to refrain from personal attacks and provocations based on other opinions. Please argue objectively and maintain a constructive discussion culture. Your comment should always be related to the topic in question in order to avoid digressions into other topics. Posting the same comment or several similar comments more than once is not permitted.

3. Prohibition of illegal content

By submitting your comment, you confirm that you are not violating any copyrights or other rights of third parties. Inciting, racist statements, instructions for criminal offences and their glorification, depictions of violence, pornographic content and statements that violate personal rights are prohibited.

4. No advertising

The use of the comment function is not permitted for commercial or party-political purposes. Advertising contributions of any kind will be deleted immediately.

5. Details of the name

When entering your name, pay attention to the principles mentioned above.

6. Source references

If you intend to publish quotes or contributions from third parties, please indicate the respective sources and explain how they relate to the blog post.

7. Violation of the terms of use

Posts that violate this policy will be deleted immediately. If you notice any violations yourself, please send us the link to the comment in question by e-mail to . We expressly point out that we will exclude individual users in the event of repeated or serious violations of these terms of use.

As of: Sept. 2024

Get your Trial Version now!

Test yeet free of charge

IHRE EVALUIERUNGSLIZENZ - JETZT ANFORDERN!

TESTEN SIE DIE CONZEPT 16 VOLLVERSION - UNVERBINDLICH und KOSTENFREI

Subscribe to our newsletter

[cleverreach_signup]
WordPress Cookie Notice by Real Cookie Banner