Tips   >   Externals   >   Externals (All Contents)

External Components

Trying to find documentation on the external components provided with Omnis Studio can sometimes be a challenge.

This section is an attempt to document and demonstrate the external components provided by Omnis Studio.

If you have information or demos, please email them to
doug@vencor.ca

Instantiating an External Component

To use an external component you need to instantiate it with a variable.

  1. Create an object type variable.
  2. Click the variable subtype and in the treelist select the External Objects node.
  3. Open the node and select the external object of your choosing from the child nodes.
If the external object does not appear in the child nodes you may need to load the component.

Loading External Components

If an external component is not in the External Objects node of the object variable subtype, you need to set Omnis Studio to pre-load it using the External Components window.

  1. F2 Browser > select your library in the treelist > click External Components. This opens the External Components window.
  2. Open the External Components root node of the treelist.
  3. Select the child node external component you are looking for.
  4. In the Pre-Load Status group box, click either the Starting Omnis or Opening 'YourLibName' radio button.
  5. Click the OK button when you are done.
  6. Quit and reopen Omnis Studio. Omnis Studio will load the external component.

External Components Browser

The function sys(4019) opens an External Components Browser window.

Click the Run Demo button in the StudioTips Browser to open the External Components Browser.

Scroll through the list of external compenents. When you click on a component, the properties, events, and functions supported by the component are listed. When you click on a property, a description of the property is displayed in the bottom of the browser.

Blowfish Object

The blowfish external can be use to encrypt/decrypt passwords.

It is best to store all passwords in an encrypted form so that nobody, not even the system administrator, can see actual passwords. If a user forgets their password it is better practice to reset the password, than to view their existing password.

To use the blowfish external you need to instantiate it with an object type variable.

  1. Create an object type variable.
  2. Set the variable subtype to point to External Objects > Blowfish.

Encrypt a String

  1. Send the blowfish external an initial key using the $initkey method. You must remember this key in order to decrypt the message.
  2. Ask the blowfish external to encrypt a string by sending it a $encrypt(pStringValue) message.
  3. The blowfish external returns a binary value which is the encrypted string value.
  4. You can then store the encrypted string in your database as a blob or in a file.

Calculate cInitialKey as 'mykey'
Do oBlowfish.$initkey(cInitialKey)

Prompt for input Enter a password to encrypt Returns MyPassword
Do oBlowfish.$encrypt(MyPassword) Returns cBinaryVariable
OK message (Icon) {Your password has been encrypted to a binary value using the key '[cInitialKey]'////The 'Decrypt a String' demo will decrypt the string.}

Decrypt a String

  1. Send the blowfish external an initial key using the $initkey method. It must be the key that was used to encrypt the message.
  2. Ask the blowfish external to decrypt the binary value by sending it a $encrypt(pBinaryValue) message.
  3. The blowfish external returns the decrypted string value.

Do oBlowfish.$initkey(cInitialKey)
Do oBlowfish.$decrypt(cBinaryVariable) Returns DecryptedString
OK message (Icon) {The decrypted password is: '[DecryptedString]'}

Implementing Blowfish

I am a newbie to encryption so the following comments are just some of my initial thoughts on implementing blowfish.

Where do we store the key?

  1. You could hard code the $initkey somewhere in the application. The risk is that any developer who views the code can see the initial key and then use the blowfish external to decrypt any encrypted text. That may or may not be a problem depending on the application.
  2. For storing passwords you could use the user's password for the $initkey. I tested this and the only way to decrypt the binary variable was to use the correct password.

    Would using the password as the initial key for their password be a problem? I'm not sure. You wouldn't want to use the user password as the initial key to anything other than their own password!

Calculate cInitialKey as 'mykey'
Prompt for input Enter a password to encrypt Returns MyPassword
Do oBlowfish.$initkey(MyPassword)

Do oBlowfish.$encrypt(MyPassword) Returns cBinaryVariable
OK message (Icon) {Your password has been encrypted to a binary value.}

Prompt for input Enter your password Returns RenterPassword
Do oBlowfish.$initkey(RenterPassword)
Do oBlowfish.$decrypt(cBinaryVariable) Returns DecryptedString
OK message (Icon) {The decrypted password is: '[DecryptedString]'}

Include Header

The Omnis Studio F1 Help discusses an optional header parameter as follows:

The bIncludeHeader parameter is a boolean to indicate whether or not a header should be appended to the data. The encrypted data is always the same length as the decrypted data except for an additional 8 byte header (if required).

I tested encrypting a message with bIncludeHeader set to true, and then decrypting with bIncludeHeader set to false. (Just to see what would happen.) This exercise succeeded in crashing Omnis Studio v4.0. Needless to say I didn't bother testing any further.

HTMLControl

Documentation on the HTML Control is available in the F1 Help by searching for Document Viewer. (not HTML Control as I discovered.) Some of the information in this section is copied directly from the F1 Help.

The Document Viewer is an external component for viewing HTML files in a window class. The Document Viewer is used extensively in Omnis, specifically in the Welcome application to display the Omnis help and tutorial HTML files.

When placed on a window you can change the properties of the HTML component under the Custom tab in the Property Manager. The component does not have a $dataname property, instead you specify the path to an HTML text file in the $filename property. You can set the $filename in design mode or set it dynamically at runtime.

The HTML control can display HTML files stored locally. Unfortunately, the HTML control can not display files or images on the internet.

Tip

Use the openURL object class available in the downloads section of the studiotips.net to open the client's default web to a URL which you specify.

The section explains the special properties and methods for the HTML control.

Click the Run Demo button in the StudioTips Browser to test the various properties and methods of an HTML Control component.

The first time you run this demo, you must click the Set an HTML File button and point the control to a valid HTML file on your computer.

$event

The HTML component reports many different events and you can write event handlers in the object's $event method to handle them. When you create the HTML component from the Component Store a template $event method is inserted to handle the basic events in the object at runtime. Note all the events for the HTML component return the $ident of the field as the first event parameter.

The HTML component receives the following event messages:

The sample code below was pasted from the $event method of the HTML Control in the Component Store.

On evAnimateScrollEnd
;

On evSetTitle
Calculate $cwind.$title as pTitle

On evHyperlink
If pos(".lbs",pHRef)
   Calculate lOmnisLibPath as pHRef
   Do $cobj.$pathtoapi(lOmnisLibPath)
   Open library (Do not close others) {[lOmnisLibPath]}
Else
   Do method $setUrl (pHRef)
End If

On evEventTag
; deal with custom html events

On evExecTag
; deal with the following html tags (pTagValues contains list of propertie names and values)
; <BGSOUND loop=value src=url>

On evImagePluginCreate
Switch pType
   Case 'JPEG'
      Set reference lObjRef to $cinst.$objs.$add(kComponent,"JPEG Library","JPEG Control",-100,-100,10,10,kFalse,kFalse)
   Case 'GIF'
      Set reference lObjRef to $cinst.$objs.$add(kComponent,"Gif Library","Gif Control",-200,-200,10,10,kFalse,kFalse)
   Case 'PCX'
      Set reference lObjRef to $cinst.$objs.$add(kComponent,"PCX Library","PCX Control",-200,-200,10,10,kFalse,kFalse)
End Switch
Do lObjRef.$visible.$assign(kFalse)
Do method AssignProperties (lObjRef,pProperties)
Calculate as eval('pWindowRef.$assign(lObjRef.$framehwnd)')
If not(pWidthRef)
   Calculate as eval('pWidthRef.$assign(lObjRef.$imagewidth)')
End If
If not(pHeightRef)
   Calculate as eval('pHeightRef.$assign(lObjRef.$imageheight)')
End If
Do __HtmlCtrlObjsList.$add(pCtrlIdent,lObjRef.$ident)

On evXCompPluginCreate
If pComponentLib="internal"
   Set reference lObjRef to $cinst.$objs.$add(eval(pComponentCtrl),-pWidthRef,-pHeightRef,pWidthRef,pHeightRef,kFalse,kFalse)
Else
   Set reference lObjRef to $cinst.$objs.$add(kComponent,pComponentLib,pComponentCtrl,-pWidthRef,-pHeightRef,pWidthRef,pHeightRef,kFalse,kFalse)
   If pComponentCtrl=$cobj.$componentctrl
      Calculate lObjRef.$eventhwnd as $cobj.$framehwnd
   End If
End If
Do method AssignProperties (lObjRef,pProperties)
Calculate as eval('pWindowRef.$assign(lObjRef.$framehwnd)')
Do __HtmlCtrlObjsList.$add(pCtrlIdent,lObjRef.$ident)

On evPluginDestroy
Do __HtmlCtrlObjsList.$search(__HtmlCtrlident=pCtrlIdent,kTrue,kFalse,kTrue,kTrue)
Do __HtmlCtrlObjsList.$first(kTrue,kTrue) Returns lSearchRef
While len(lSearchRef)
   Do __HtmlCtrlObjsList.$loadcols()
   Set reference lObjRef to $cinst.$objs.$findident(__HtmlCtrlObjIdent) ;; get reference to plugin object
   Do $cinst.$objs.$remove(lObjRef) ;; remove plugin object from window
   Do __HtmlCtrlObjsList.$remove(__HtmlCtrlObjsList) ;; remove object from list
   Do __HtmlCtrlObjsList.$first(kTrue,kTrue) Returns lSearchRef
End While

$filename

The HTML control will display the HTML file specified in the $filename property.

The file made be a valid HTML file on the local machine or local network.

Do HTMLControlRef.$filename.$assign(FilePath)

$fontsizeadj

A numeric adjustment between -3 and 3 to apply to the font size

; Increase font size
If HTMLControlRef.$fontsizeadj<3
   Do HTMLControlRef.$fontsizeadj.$assign(HTMLControlRef.$fontsizeadj+1)
End If

; Decrease font size
If HTMLControlRef.$fontsizeadj>-3
   Do HTMLControlRef.$fontsizeadj.$assign(HTMLControlRef.$fontsizeadj-1)
End If

$getselectedtext

Do HTMLControlRef.$getselectedtext(cText)

Sets cText to the text which is currently selected in the document.

Text that is selected by $searchwords is ignored by this method.

$pathtoapi

Converts cPath from the HTML syntax to the syntax for the current platform, and sets cPath to the result.

Do HTMLControlRef.$pathtoapi(cPath)

I haven't figured out where or how I would use this method.

$pathtohtml

Converts cPath from the syntax for the current platform to the HTML syntax, and sets cPath to the result.

Do HTMLControlRef.$pathtothml(cPath)

I haven't figured out where or how I would use this method.

$printdocument

Prints the document

Do HTMLControlRef.$printdocument()

$searchwords

A space separated list of up to five words which will be highlighted in the displayed document when the document is opened.

The $searchwords property must be set before setting the $filename property, so after you set the $seachwords property you will need to reset the $filename property.

Do HTMLControlRef.$searchwords.$assign(cSearchString)
Do HTMLControlRef.$filename.$assign(irHTMLCtrl.$filename)

$startanimatescroll

Starts scrolling the document once every iInterval milliseconds by the specified units

Do HTMLControlRef.$startanimatescroll(iHorzScrollUnits,iVertScrollUnits,iInterval)

Do HTMLControlRef.$startanimatescroll(0,1,100)

$stopanimatescroll

Stops automatic scrolling of the document

Do HTMLControlRef.$stopanimatescroll()

Lining up Hyperlinks

If you want to overlay a multi-line entry field with an hmtl view of the same thing with hyperlinks added you run into a problem with the margins shifting. While that xcomp doesn't have any margin control properties, you can compensate in the HTML itself, adding to the opening body tag:

<body topmargin=-10 leftmargin=-1>

You will need to adjust the values for the font and size you use in order to shift the text to align with the scrolling entry field behind the html overlay. Once added you can make the hyperlinks come and go without any shifty glitches.

This tip has been provided by Kelly Burgess and Michael Monschau.

Timer Object

The first time I tried to use the timer object it took a while to find because it wasn't loaded. Review the topic on Loading External Components if the Timer object doesn't show up in your external components treelist.

To use the timer object you first create an object class which has the timer object as its superclass.

  1. Create a new object class. e.g. oCustomTimer
  2. With the object class selected, press F6 to open the Property Manager.
  3. Click the $superclass property droplist button.
  4. Scroll down the treelist to the External Objects node and select the Timer child node.

Once the timer object class is created, you can instantiate it using an object data type variable. Depending on the purpose you can use a task variable, class variable, or instance variable to instantiate your object class which has the timer object as its superclass.

  1. Go to the variables pane in the method editor of the class where you wish to instantiate the timer object subclass.
  2. Add a new variable. eg. instance variable ioTimerObj
  3. Set the Type to Object.
  4. Click the droplist of the variable's Subtype.
  5. Navigate to the timer object class which you created in your library.

Your Timer object class will have several properties and methods which are reviewed below.

Click the Run Demo button to open a window which demonstrates an oTimerDemo object class and a technique for adding an observer to a timer object. The observer is notified each time a $timer message is received by the timer object.

$autoreset

The timer object $autoreset property can be set to kTrue or kFalse.

If set to kFalse the timer object will send a $timer message once and then stop. If set to kTrue the timer object will continue to send $timer messages at the interval specified by the $timervalue and $useseconds properties until it is sent a $stoptimer message.

$reentrant

The timer object $reentrant property can be set to kTrue or kFalse.

If set to kTrue the timer sends a $timer message and immediately restarts the timer without waiting for the $timer method to execute.

If set to kFalse the timer sends a $timer message and waits for the $timer method to complete before restarting the timer.

$resettimer

Sending a $resettimer message to the timer object stops and then restarts the timer using the current value of $timervalue.

$starttimer

Sending a $starttimer message to the timer object starts the timer using the current value of $timervalue.

$stoptimer

Sending a $starttimer message to the timer object stops the timer.

$timer

When the timer counts down to zero a $timer message to the timer object. The pEventCode is evTimer. You override the $timer method of your timer object subclass and enter the code you want executed when the timer counts down to zero.

$timervalue

The timer object $timervalue property can be set to any integer value. The unit of measure will either be seconds or milliseconds depending on the $useseconds property setting.

$useseconds

The timer object $useseconds property can be set to kTrue or kFalse.

If set to kTrue the unit of measure for $timervalue will be seconds. If set to kFalse the unit of measure will be milliseconds.

Timer Crashes Omnis

Some Omnis developers have reported that a timer object initiated method will crash Omnis Studio if the timer object initiated method kicks in when another Omnis Studio method is executing.

To prevent this from happening you can use the sys(90) function to check the number of methods in the method stack and abort running the timer object method if other methods are running at the same time.

Place the following code at the start of your $timer method:

; Check the number of methods currently in the method stack.
Calculate MethodStackLineCount as sys(90)
If MethodStackLineCount<>1
   
   ; A method other than this one is currently running.
   ; Restart the timer object if it is not $reentrant.
   If $cinst.$reentrant=kFalse
      Do $cinst.$starttimer()
   End If
   Calculate FlagOK as kTrue
   
Else
   
   ; No other methods are in the method stack.
   ; Run the timer object method initiated code.
   Breakpoint
   
End If
Quit method FlagOK

Note

The sys(9) function does not work for web client requests running in a thread of the multi-threaded server.