MiniM. Saving time.


| About | Download | Tools | Knowledge Base | How to Buy |

MiniM Overview

Getting Started

Download

Documentation

Tools

Cache Tools

GT.M Tools

Knowledge Base

FAQ

Contacts

Copyrights

MiniM Knowledge Base | Nov 1, 2016

How to call MiniMSCX ActiveX from Xojo

Xojo is an integrating development tool to develop applications using Basic language and Basic dialect looks very closely to Visial Basic. See Xojo website.

To call MiniM Server Connect ActiveX component from Xojo application first of all we need that this component properly installed on this computer and on each computer where application should be run. See an article for developers How to install ActiveX for MiniM Server Connect.

Run Xojo IDE and click menu Insert | ActiveX Component... and select page References. In this list find type library of MiniMSCX.

This adds to your Xojo application information about classes, types and interfaces implemented by MiniMSCX library. After adding references you can use this component. See available in MiniMSCX library components and interfaces they supports.

There are two classes - ServerConnect and ServerString. ServerConnect object implements network protocol and this object should be created for each connection to MiniM Database Server. ServerString implements independent of development tool and language data transfer objects. All data to send to and receive from the MiniM marshals in this objects. Note that ServerString and MiniM Database Server does not support unicode data encoding.

To illustrate using MiniMSCX we use simple window with one text area to display text elements and one push button to make event handler. Controls have default names PushButton1 and TextArea1.

Right click on the push button and add event handler for event Action. This is handler of mouse click. In event handlers add code to create component MiniMSCX:

Dim Connect As new MiniMSCXLib.ServerConnect(True)
Dim ret as Integer = Connect.CreateConnect("localhost",5000,"user")
AddHandler Connect.EventTriggered, AddressOf EventFired
ret = Connect.Open
ret = Connect.ExecuteOutputStr("f i=1:1:5 w i,!")
ret = Connect.Close

And add method with name "EventFired", with parameters "Sender As MiniMSCXLib.ServerConnect, nameOfEvent As String, parameters() As Variant" and return type "Variant":

And add code body for this method:

if nameOfEvent = "OnTerminalOutput" then
  TerminalOutputHandler(Sender,parameters(1))
End
return ""

Add one more method with name "TerminalOutputHandler", with parameters "sender As MiniMSCXLib.ServerConnect, Value_Param As String" and add code body for this method:

TextArea1.Text=TextArea1.Text+Value

After running application click push button. Of course, you should check connection parameters for MiniM Database Server. This example suppose using default parameters - local instance, default connection port 5000 and database of server job "USER". If all made correctly, your small application can appear like this:

And now we will describe each step. MiniMSCX component have all 4 methods to transfer data from server application:

  • Reading value of expression. Simple Read function.
  • Catching writing data to principal device. Event OnTerminalOutput with text data.
  • Writing portions of data in fast stream mode. Event OnGroupRead with binary data.
  • Calling back client side with saving stack levels. Event OnCallback with binary data from ther server and place for binary data for answer to server.

On example shown above we illustrated catching writing data to current device. All data are available in event OnTerminalOutput. Bytes are sent from server can be splitted to portions with undefined length. Internal protocol uses convention about zero byte as a terminator, so this method is useful for traditional MUMPS applications which made reports as text.

To read value of evaluated expression component MiniMSCX can be created in any form - with or without event support. For example:

Dim Connect As new MiniMSCXLib.ServerConnect
Dim ret as Integer = Connect.CreateConnect("localhost",5000,"user")
ret = Connect.Open
TextArea1.Text = Connect.ReadStr("$zv")
ret = Connect.Close

Other data transfer method requires creation of component MiniMSCX with mandatory event support:

Dim Connect As new MiniMSCXLib.ServerConnect(True)

When events fired, Xojo virtual machine fires event EventTriggered only and we must assign only one real event handler with prototype

Public Function EventFired(Sender As MiniMSCXLib.ServerConnect, 
  nameOfEvent As String, parameters() As Variant) as Variant
  ...
  return ""
End Function

Event has ths prototype:

Event EventTriggered(nameOfEvent As String, parameters() As Variant) As Variant

And event handler receives additional first parameter with type of component

Sender As MiniMSCXLib.ServerConnect

To do assignment event handler to method, use AddHandler command:

AddHandler Connect.EventTriggered, AddressOf EventFired

Inside of this common event handler we must check name of real event by comparing value of nameOfEvent:

  if nameOfEvent = "OnTerminalOutput" then
    TerminalOutputHandler(Sender,parameters(1))
  End

Or, the best way, using all set of possible alternatives:

  select case nameOfEvent
  case "OnTerminalOutput"
    TerminalOutputHandler(Sender,parameters(1))
  case "OnGroupRead"
    GroupReadHandler(Sender,parameters(1))
  case "OnCallback"
    CallbackHandler(Sender,parameters(2),parameters(1))
  End Select

Here we use other two methods:

Public Sub GroupReadHandler(sender As MiniMSCXLib.ServerConnect, 
  Value_Param As Variant)
  ...
End Sub

and

Public Sub CallbackHandler(sender As MiniMSCXLib.ServerConnect, 
  Command_Param As Variant, Answer_Param As Variant)
  ...
End Sub

Inside of EventFired method we pass parameters as Variants. In Xojo like in VB Variant can contain pointer to automation object. All access to real ServerString objects we will do inside of methods GroupReadHandler and CallbackHandler.

First of all we executed code

Connect.ExecuteOutputStr("f i=1:1:5 w i,!")

This functions (ExecuteOutput and ExecuteOutputStr) raises event OnTerminalOutput when got any writing from the server. Other two functions (Execute and ExecuteStr) does not, but fire events OnGroupRead and OnCallback when server side calls wo^%srv and $$cb^%srv respectively.

So we change executed code in the Action handler to this:

  Dim Connect As new MiniMSCXLib.ServerConnect(True)
  Dim ret as Integer = Connect.CreateConnect("localhost",5000,"user")
  AddHandler Connect.EventTriggered, AddressOf EventFired
  ret = Connect.Open
  
  ret = Connect.ExecuteStr(
    "s i="""" f  s i=$o(^ROUTINE(i)) q:i=""""  d 
wo^%srv($lb(i,$zd($g(^ROUTINE(i,0)),3)))")
  
  ret = Connect.Close

This code order by all available routines (INTermediate source code), creates structure $lb() and pass to wo^%srv subroutine to fire OnGroupRead event on the client side.

Inside of OnGroupReadHandler we write unpacking code to accept data:

  rem OLEObject requires to access COM objects passed as Variant
  Dim Value As New OLEObject(COM.IDispatch(Value_Param))
  rem here Value is a $lb structure, unpack it
  
  rem we should unpack into separate variables Name and Date
  Dim Name as New MiniMSCXLib.ServerString
  Dim Date as New MiniMSCXLib.ServerString
  
  rem we should read error code returned by get functions
  Dim errcode as Int32
  
  rem we cannot pass OLEObject into ListGet function, 
  rem so transfer data into temporary ServerString object
  Dim v As New MiniMSCXLib.ServerString
  v.Value=Value.Value
  
  rem unpack first and second items of the $lb structure sent from the server
  errcode = sender.ListGet(v,1,Name)
  errcode = sender.ListGet(v,2,Date)
  
  rem add line to report
  TextArea1.AppendText("Routine name: "+Name.Value+
    ", date change: "+Date.Value+EndOfLine)

After running this form and pressing button TextArea control displays list of available routines with date last modified.

And last event, most complex, OnCallback event handler. Here we call on the server subroutine with return:

$$cb^%srv(param)

Here value of param expression must be passed to client side, and inside of event must be two ServerString objects - with value passed from the server to the client and for value to return from the client to the server as an answer. This answer server code return by the QUIT command from subroutine $$cb^%srv.

So, we execute the following code:

  
Dim str As String = Connect.ReadStr("$zd($h,2)_$$cb^%srv(""get string"")")
TextArea1.AppendText("Server return: " + str + EndOfLine)

We can call any access method including Execute, Read or Write, where is side effect with calling "$$cb^%srv".

On execution this code fires event OnCallback and we access parameters and can call server back if need. This callback functionality works while stacks on the server and client are available and side who calls waits answer. To unpack parameters we use casting to OLEObject:

Public Sub CallbackHandler(sender As MiniMSCXLib.ServerConnect, 
    Command_Param As Variant, Answer_Param As Variant)

  Dim Command As New OLEObject(COM.IDispatch(Command_Param))
  Dim Answer As New OLEObject(COM.IDispatch(Answer_Param))
  
  TextArea1.AppendText(
    "OnCallback event handler receives the command:"+Command.Value+EndOfLine)
  TextArea1.AppendText(
    "Inside of OnCallback handler we read back the server."+EndOfLine)
  
  Dim s as String = sender.ReadStr("$zt($p($h,"","",2))")
  
  rem we return concatenation of Command and time formatted on the server
  Answer.Value = " Client on command " + Command.Value+" return " + s
  
End Sub

And, after execution, we see in TextArea control full report with execution tracing.

This article uses technical information about MiniM Database Server and Xojo integrated development environment and compiler, so you can call two tech support in depending on the problem. While this article was being written, Jason Parsley provided invaluable support.

Eugene Karataev
support@minimdb.com

Jason Parsley
Technical Support Engineer
Xojo, Inc.
hello@xojo.com
Twitter: @xojo
Facebook: https://www.facebook.com/goxojo


Copyright (C) 2017 Eugene Karataev
Emails: Info Tech Support