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:
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:
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
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:
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
firstname.lastname@example.org Jason Parsley
Technical Support Engineer