ObjectViRCScript Documentation (for ViRC '96 0.82a and above) - Revision 2a =========================================================================== Introduction ============ What is ObjectViRCScript? ObjectViRCScript is a set of object-based extensions to the main ViRCScript language, adding a class/property/event model to ViRCScript, much as C++ adds a similar model to C. Anyone who has programmed in Delphi before will feel instantly familiar with OVS - it uses Delphi's class library!! This was facilitated by Delphi's very comprehensive RTTI system which allows sufficient data to be extracted from classes and so forth at runtime to make programming the ObjectViRCScript interpreter relatively simple - OVS adds only about 1200 lines of code to the main ViRCScript interpreter. What does ObjectViRCScript add? ------------------------------- OVS adds New and Destroy to create and destroy class objects, a new @p statement to set properties, and a $prop function to get properties. Also added is the ability to call object methods, either as statements or as functions to return values. New MAPOBJECT function and UNMAPOBJECT statement added to enable customization of ViRC '96's GUI (server windows, channel windows etc.). Adds WITH/ENDWITH for making setting multiple properties of an object easier. ADDTOSETPROP and REMOVEFROMSETPROP commands for dealing with objects' set properties. What's new in this release of ObjectViRCScript? ----------------------------------------------- New in 0.82: support for enumerated and set properties, many object methods, many new classes supported (including the TSockets class for writing sockets applications in ViRCScript, and TTimer for making timers), and MAPOBJECT/UNMAPOBJECT for customizing V96's built-in windows. New WITH/ENDWITH statements. ADDTOSETPROP/REMOVEFROMSETPROP statements. New in 0.82a: a few more implemented methods documented, corrected many documentation inaccuracies (esp. in TSockets documentation). What's currently wrong with ObjectViRCScript? --------------------------------------------- This is a difficult one ... not all methods of all Delphi objects are currently supported, although support will improve greatly in future versions. ObjectViRCScript extension details ================================== NEW function ------------ Usage: $new(class [ownedby object]) Creates a new object of type class, and returns an instance handle. Class can be any of the Delphi VCL classes, for example, TForm, TEdit, TButton, and so forth. If the optional ownedby object parameter is specified, the object's owner is set to that parameter. If you're creating a TForm, which has no owner (actually ViRC '96 itself is the owner), you must leave this parameter off - forms owning other forms does not make sense. Note: all objects are created invisible. To show them, you need to change their Visible property (see the @P statement below). Examples: The following code makes a new TForm object and assigns its instance handle to the $form variable. Notice that @ $form = $new(TForm) Once the form has been created and assigned to $form, the following code adds a button to the form: @ $button = $new(TButton ownedby $form) DESTROY command --------------- Usage: Destroy object Destroys object, along with all the objects it owns, freeing all the memory associated with the objects. You should always use DESTROY to destroy any object you have created to conserve memory. Note that, if you have a TForm which owns a number of other controls, you only have to call DESTROY once for the form object, as all the controls it owns will be automatically destroyed as well. Example: To destroy the form object $form and all controls that it owns: Destroy $form DESTROY does _NOT_ deallocate the variable specified, only the object itself. Therefore, unless you're storing the object handle in a local variable, you should deallocate the variable after using the DESTROY command (e.g. -@ $form). Note that Delete is synonymous with Destroy - you can use either. @P command ---------- Usage: @p $object.Property = Value Assigns Value to $object's Property property. For example, to show the form object $form, change its caption, and make it visible, you could do: @p $form.Caption = This is a test!! @p $form.Visible = True Please note that only a subset of Delphi's types are currently supported for properties. They are: integers, strings, booleans (use 1 and 0 for True and False respectively), enums, sets, and objects. Floats and variants are currently NOT supported, although this will probably change in future versions of OVS. For example, to set the active control on the form object $form to the button object $button, use: @p $form.ActiveControl = $button You can set enum properties either by name, or by index. You will probably prefer to set them by name!! For example, the 2 lines below are equivalent, causing the $edit object to align itself with the bottom of its parent form. @p $edit.Align = 2 @p $edit.Align = alBottom Of course, the latter is far more self-explanatory. You can also retrieve set properties. Set properties are similar to enums, except that multiple elements within the set can be set at once. A very common set property (possibly the only one you will ever use) is TForm.BorderIcons. This controls what icons are present in a form's border. The BorderIcons set may contain any combination of biSystemMenu, biMinimize, and biMaximize. Set properties MUST be included in []'s (even if there is only one member (or even no members) in the set) and multiple elements must be separated by , (a comma). Examples: // Makes the form's border contain only a system menu icon @p $form.BorderIcons = [biSystemMenu] // Show all the icons in a form's border @p $form.BorderIcons = [biSystemMenu,biMinimize,biMaximize] // Show no icons in the form's border @p $form.BorderIcons = [] You can also add or remove specific values from a set. See the ADDTOSETPROP and REMOVEFROMSETPROP commands below for more information. In addition, OBJECT EVENTS may be set with @p. This can be illustrated with some very simple examples: @p $button.OnClick = MessageBox You clicked me!! @p $form.OnClose = Beep If you want to execute more than one command in response to an object event, define an alias and call that, for example: @p $closebutton.OnClick = CLOSEBUTTON_CLICK Alias CLOSEBUTTON_CLICK MessageBox I'll now close the form!! Destroy $form EndAlias In addition, with some events, ViRC '96 will pass in extra information in the form of local variables. In fact, V96 always passes in $Sender, which is the object that caused the event. Thus you can create one alias which handles events from a number of objects of different types. The following events are supported: Mouse events ------------ Event names: OnMouseUp, OnMouseDown Variables passed in: $Button - button pressed. Can be mbLeft, mbRight or mbMiddle. $X - X coordinate of where the mouse is. $Y - Y coordinate of where the mouse is. Mouse move events ----------------- Event names: OnMouseMove Variables passed in: $X - X coordinate of where the mouse is. $Y - Y coordinate of where the mouse is. Key events ---------- Event names: OnKeyUp, OnKeyDown Variables passed in: $Key - The scan code for the key pressed. You can modify this value in your OnKeyUp/OnKeyDown events to simulate as if a different key were pressed. For example, if you wish to nullify a key press, set $Key to 0 in your code. Key press events ---------------- Event names: OnKeyPress Variables passed in: $Key - The key pressed (e.g. A, 0, & etc). You can change this value in your OnKeyUp/OnKeyDown events to simulate as if a different key were pressed. Drag-and-drop events are also supported, although their usage is rather complicated, and I will refrain from documenting them until they work well. ADDTOSETPROP command -------------------- Usage: AddToSetProp object.property set Combines set with the set property object.property. This is used to add values to a set. For example, this code will display the minimize icon on a form's border by adding the item biMinimize to the BorderIcons set: AddToSetProp $form.BorderIcons [biMinimize] Note that if biMinimize is already present in the set, the second addition will have no effect, in other words, ADDTOSETPROP will only add an item to a set if it isn't already in the set. You can add multiple items to a set as well. Example: AddToSetProp $form.BorderIcons [biMaximize,biMinimize] ADDTOSETPROP is an efficient wrapper around the standard VS ADDTOSET function. For example: AddToSetProp $form.BorderIcons [biMaximize,biMinimize] Is equivalent to this: @p $form.BorderIcons = $AddToSet($prop($form.BorderIcons) [biMaximize,biMinimize]) REMOVEFROMSETPROP command ------------------------- Usage: AddToSetProp object.property set Removes any elements from object.property that are also present in set. For example, the following code will remove the minimize icon from a form's border by removing the biMinimize element from the set: RemoveFromSetProp $form.BorderIcons [biMinimize] You can remove multiple items from a set at once (see above). Attempting to remove an item from a set which isn't in the set will have no effect. REMOVEFROMSETPROP is an efficient wrapper around the standard VS REMOVEFROMSET function. For example: RemoveFromSetProp $form.BorderIcons [biMaximize,biMinimize] Is equivalent to this: @p $form.BorderIcons = $RemoveFromSet($prop($form.BorderIcons) [biMaximize,biMinimize]) WITH/ENDWITH statement ---------------------- (should this be in VSCRIPT.TXT instead? Or as well?) Usage: With command ... EndWith This very useful statement makes setting multiple object properties (for example) very easy. Basically, command is prepended to every line in the WITH/ENDWITH block before execution. Example (from WEBSERV.VSC): @ $webform = $new(TTabbedForm) With @p $webform. Left = 20 Top = 20 Width = 300 Height = 300 FormStyle = fsStayOnTop Caption = ObjectViRCScript Web Server Example TabCaption = Web server Visible = True EndWith This would be equivalent to: @ $webform = $new(TTabbedForm) @p $webform.Left = 20 @p $webform.Top = 20 etc. As can be seen, WITH makes setting multiple object properties very simple. Although this is the use WITH was designed for, it's possible to use it without objects. For example, you can use this to make outputting multiple lines of text to a query window very simple: With TextOut > TextQuery clBlue $null Hello!! This is a very good way ... ... to add lots of lines of text at once ... ... to a window. EndWith The $null is required to ensure that the space after clBlue is not removed by the parser. PROP function ------------- Usage: $prop($object.Property) Returns the property Property of $object. For example, to retrieve the contents of a TEdit control, you could use: @ $x = $prop($edit.Text) The PROP function can currently return integer, string, boolean, enum, and object properties. Other Delphi property types aren't supported yet, but they should be in future versions of OVS. OVSVER variable --------------- Usage: $ovsver This variable contains the ObjectViRCScript version number. V96 0.82 and above return an ObjectViRCScript version number of 2. The presence of this variable is useful, as it allows you to test in your script whether the user is running an ObjectViRCScript-capable version of ViRC '96 or not, for example: if !($ovsver) MessageBox This script requires ViRC '96 0.80 or higher with ObjectViRCScript to function. Halt endif MAPOBJECT function ------------------ Usage: $mapobject(window[:control]) This is possibly THE most powerful function in ObjectViRCScript. What it does is to return an ObjectViRCScript object handle for any built-in ViRC '96 window. You can then add controls to it or change properties as if it were an object which you have created yourself. This function is designed primarily to be used in the event, which is fired whenever a new channel window or server window is created. Two parameters are passed to the event: $0 is the class of the window created (TServerForm or TChannelForm), and $1 is the standard name of the window. So, server windows always have a name of . (period), channel windows have names of #channel, and so forth. For example, this very simple example changes the colour of the text entry area of server windows to a random colour whenever a new one is opened. Note that, with server windows, $1 is always . (period), so you could replace $mapobject($1:tbServerText) with $mapobject(.:tbServerText). Event "TServerForm" @ $servertext = $mapobject($1:tbServerText) @p $servertext.Color = $rand($FFFFFF) UnmapObject $servertext EndEvent Another example: to make text entry areas in channel windows appear at the top of the window rather than the bottom, you could use: Event "TChannelForm" @ $chanentry = $mapobject($1:EntryPanel) @p $chanentry.Align = alTop UnmapObject $chanentry EndEvent Really, knowledge of all the names of the controls on server and channel windows is needed, so I might release the source .DFM files for those forms so anyone with Delphi can find the names themselves. However, this should get you started: Server window only ------------------ tbServCommand - TEdit entry box where the user types commands tbServerText - TRichEdit where server text appears Channel window only ------------------- NamesPanel - TPanel containing lvNames tbChannelText - TRichEdit where channel text appears lvNames - TListView where the channel nick list is *** NOTE *** TListView is not fully supported by OVS yet. However, you can read/write a TListView's ItemText and ItemIndex properties to fetch the currently-selected nick in a channel nicks list, for example (or you could use the regular ViRCScript function $selectednick() for this, which is probably a LOT simpler!! :) Both windows ------------ MainPanel - TPanel containing text output box EntryPanel - TPanel containing entry box WholePanel - TPanel containing MainPanel and EntryPanel ToolbarPanel - TPanel containing toolbar The MAPOBJECT function can also be used to return an internal ViRC '96 form, for example, the client setup form. The list of supported forms is as follows: !AboutBox !Aliases !ChannelBox !ChannelList !EditXDCCPack !EventManager !FingerClientDialog !TipForm !IRCServers !UserSetup !ListFilter !LoadingScript !Main !MenuEditor !PortScanner !ResumeDlg !Links !VSWizard !WHOIS !WhoList You can thus add controls to any of these forms. For example: @ $aliasform = $mapobject(!Aliases) @ $button = $new(TButton ownedby $aliasform) In addition, the !UserSetup form's page control is called SetupPages. Thus you can add your own tab to ViRC '96's client setup dialog!! For example, this code will add a new tab sheet to the client setup dialog which contains one button: @ $SetupPages = $mapobject(!UserSetup:SetupPages) @ $NewTabSheet = $new(TTabSheet ownedby $SetupPages) With @p $NewTabSheet. PageControl = $SetupPages Caption = Test tab EndWith @ $NewButton = $new(TButton ownedby $NewTabSheet) With @p $NewButton. Left = 20 Top = 36 Width = 73 Height = 65 Caption = &Beep!! OnClick = Beep EndWith $SetupPages.RefreshTabs UnmapObject $SetupPages If you do add pages to V96's client setup dialog, you must call the RefreshTabs method to ensure that the pages are refreshed properly, otherwise you will experience visual problems. You only need to call RefreshTabs on V96's client setup dialog, never on your own tab controls. UNMAPOBJECT command ------------------- Usage: UnmapObject object The MAPOBJECT function creates a ViRCScript object handle representing a built-in V96 object. You must use the UNMAPOBJECT command to remove the object handle when you have finished using it, otherwise, the object handle will be left in memory (each object handle only takes 4 bytes, but these can add up). UNMAPOBJECT, unlike DESTROY, does not harm the underlying object, but merely removes its ObjectViRCScript handle. Special objects =============== On startup, ViRC '96 creates the special object handle 0 which represents the main ViRC '96 window. This is useful if you wish to manipulate the main V96 window, for example, the following code will hide ViRC '96: @p 0.Visible = False Or you can add your own controls to ViRC '96's main window by setting their owner to 0, for example, the following code will add a button to the main V96 window which quits V96 when you click on it: @ $mainbtn = $new(TButton ownedby 0) With @p $mainbtn. Left = 30 Top = 60 Width = 150 Height = 25 Caption = &Exit OnClick = Exit EndWith Visual controls =============== The following major visual controls are currently supported fully: TForm, TTabbedForm, TButton, TBitBtn, TListBox, TComboBox, TEdit, TMemo, TRichEdit, TCheckBox, TRadioButton, TGroupBox, TPanel, TBevel, TShape, TTrackBar, TProgressBar, TTabControl. Here I'll try to document some of the features of each object. All objects ----------- The following properties are shared by all visual objects: Left - X position of object Top - Y position of object Width - Width of object Height - Height of object Visible - (True or False) Controls whether object is visible Enabled - (True or False) Controls whether object is enabled Color - The background colour of the object Font.Color - The object's font colour Font.Name - The object's font name Font.Size - The object's font size Font.Style - (set) fsBold, fsItalic, fsUnderline, fsStrikeout Hint - The tooltip that appears if the user holds the mouse over the control for a while without clicking ShowHint - (True or False) Controls whether the tooltip is displayed or not Align - Causes the control to "stick" to one edge of its parent, or to fill the whole client area. alNone, alTop, alBottom, alLeft, alRight, alClient Handle - Returns the control's window handle (hWnd) The following events are shared by all visual objects: OnClick - Fired when object is clicked OnMouseMove - Fired when mouse moved over object OnMouseDown - Fired when mouse button pressed over object OnMouseUp - Fired when mouse button released over object OnActivate - Fired when the object gets the focus Supported by most visual objects (where appropriate): OnChange - Fired when object's selection (item, check mark, tab page, etc.) is changed Methods: Repaint - Causes the object, and all the objects it owns, to redraw themselves SetFocus - Sets focus to the object BringToFront - Brings the object to the front of the screen Objects that introduce no additional properties or events will not be documented further - their usage should be self-explanatory!! In addition, most objects have a standard BorderStyle property (except for the TForm), which can be bsNone for no border or bsSingle for a single black line border. TForm ----- Properties: ActiveControl - The control that has the focus when the form appears BorderStyle - bsSingle, bsDialog, bsNone, bsSizeable FormStyle - fsNormal, fsMDIForm, fsMDIChild, fsStayOnTop Position - poDefault, poScreenCenter WindowState - wsNormal, wsMaximized, wsMinimized Caption - The form's caption BorderIcons - (set) biSystemMenu, biMaximize, biMinimize OnClose - Fired when the form is closed (it's a good idea to DESTROY the form here, otherwise it will stay in memory!!) Events: OnResize - Fired when the form's size is adjusted TTabbedForm ----------- Exactly as above, except that a window tab (in the main V96 window) is made for the form. Adds one new property: TabCaption - The caption of the window's tab TButton ------- Properties: Caption - The button's caption Note that the Font.Style property is ignored on a TButton. Use a TBitBtn instead if you wish to change the Font.Style property. TBitBtn ------- As above, only Font.Style can be set, for example: @p $bitbtn.Font.Style = [fsBold,fsUnderline] Button bitmaps are supported by TBitBtn but not by ObjectViRCScript (go figure). Bitmaps should be supported shortly. TListBox and TComboBox ---------------------- Properties: Items - A TStringList object containing all the items ItemText - The text of the currently-selected item (or empty if no item selected) ItemIndex - The index of the currently-selected item (or -1 if no item selected) See later in this file under "Non-visual controls" for information on how to manipulate a TStringList object. TEdit, TMemo, TRichEdit ----------------------- Properties: Text - Contains the text in the edit control SelStart - The start of the text selection SelLength - The length of the text selection (0 if nothing selected) SelText - The selected text ReadOnly - (True or False) Controls whether the text control is read-only (not modifiable by the user) WordWrap - (TMemo and TRichEdit only) Controls whether words are wrapped on multiple lines Lines - (TMemo and TRichEdit only) TStringList object that contains the lines of text in the control (see the "Non-visual controls" section below for information on TStringList) In general, you should use TEdit for single lines of text and TRichEdit for multiple lines (in colour if necessary). You should never have to use TMemo, which is the same as TRichEdit except you cannot output text with TextOut > %$object (see VSCRIPT.TXT under TEXTOUT for more information on this). TCheckBox, TRadioButton ----------------------- Properties: Checked - Whether or not the control is checked Caption - The caption on the check box or radio button TGroupBox --------- Properties: Caption - The group box's caption TPanel ------ Properties: Caption - The text within the panel Alignment - Text alignment. taCenter, taLeft, taRight BevelInner - The inner bevel. bvNone, bvLowered, bvRaised BevelOuter - The inner bevel. bvNone, bvLowered, bvRaised BevelWidth - The width of the bevel TBevel ------ Properties: Style - The bevel's style. bsLowered, bsRaised Shape - The bevel's shape. bsBox, bsFrame, bsTopLine, bsBottomLine, bsLeftLine, bsRightLine TTrackBar --------- Properties: Min - The minimum value of the track bar Max - The maximum value of the track bar Position - The track bar's position Orientation - trHorizontal, trVertical TProgressBar ------------ Properties: Min - The minimum value of the progress bar Max - The maximum value of the progress bar Position - The progress bar's position TTabControl (tabbed notebook) ----------------------------- Properties: Tabs - TStringList containing all the tabs in the tabbed notebook TabIndex - The number of the currently selected tab. -1 means no tab selected, 0 means the first tab is selected, 1 the second, etc. For information on how to use the TStringList object, see the "Non-visual controls" section. Non-visual controls =================== TStringList (string list object) -------------------------------- The TStringList is a very powerful object. It can store a list of strings, which can be saved to and from disk, sorted, and manipulated in a powerful manner, rather like a sophisticated string array. TStringList objects are used internally by TListBox, TComboBox, TTabControl etc. to maintain their list of items. Strings start at index 0. TStringList objects grow and shrink automatically to store all the strings. Properties: Count - The number of strings in the list Methods: GetString(i) - Gets the string at index i SetString i text - Sets the string at index i to text Add(text) - Adds a string, returns the index Delete i - Deletes the string at index i, moves the others up by one Clear - Clears the string list Exchange i j - Exchanges the string at position i with the string at position j SaveToFile file - Saves the string list to file LoadFromFile file - Loads the string list from file SaveToSet() - Converts the string list to a set (e.g. [one,two,three]) and returns the set LoadFromSet set - Clears the string list and adds each element in the set to the string list Sort - Alphabetically sorts the strings in the string list TSockets (Winsock socket control) --------------------------------- ViRC '96 0.82 and above support a TSockets class, whose interface is similar to the freeware Sockv3 Delphi control. Anyone who has used this will feel instantly familiar!! Nothing has been changed in TSockets in 0.82a, however, MANY documentation inaccuracies in this section have been fixed, so please read through this again, even if you thought you understood it for 0.82!! Note that, unlike every other non-visual object, TSockets _REQUIRES_ an owner. You cannot use a TSockets without a TForm to own it. If you wish to use a TSockets without an accompanying form you can either set the TSockets's owner to 0, i.e. $new(TSockets ownedby 0) to make ViRC '96 itself own the TSockets, or you can create an invisible TForm to own the socket. Properties: IPAddr - The host name or IP address of where to connect to Port - The port to connect to or listen on Methods: SConnect - Connects to IPAddr:Port SListen - Listens for connections on Port SAccept - Accepts an incoming connection SCancelListen - Cancels a previous SListen command Send text - Sends text to the remote end SendCRLF text - Sends text plus a CRLF to the remote end Events: OnSessionConnected - Called after SConnect when session connects OnSessionAvailable - Called after SListen when an incoming connection arrives OnSessionClosed - Called when the remote end closes the connection OnDataAvailable - Called when data, sent by the remote end, is available for reception OnErrorOccurred - Called when a socket error occurs Connecting somewhere -------------------- To connect somewhere, first create the socket, ownedby a form (this is VERY important, the socket WILL NOT WORK if it is not owned by anything). Then set the IPAddr property to the name or IP of the host you wish to connect to, and set Port to the port. Then call the SConnect method. Example: @ $socketform = $new(TForm) @ $socket = $new(TSockets ownedby $socketform) @p $socket.IPAddr = post.demon.co.uk @p $socket.Port = 25 $socket.SConnect Listening for connections ------------------------- Virtually identical to the above, except that IPAddr isn't specified and you call SListen instead of SPort. For example, to listen for incoming connections on port 1234, do: @ $socketform = $new(TForm) @ $socket = $new(TSockets ownedby $socketform) @p $socket.Port = 1234 $socket.SListen Accepting incoming connections ------------------------------ When you are listening and an incoming connection comes in, the OnSessionAvailable event is fired. You can then use the SAccept method to accept the connection. Example: @p $socket.OnSessionAvailable = SOCKET_INCOMING Alias SOCKET_INCOMING $socket.SAccept EndAlias When the remote end connects ---------------------------- After you have issued the SConnect call, V96 tries to connect with the remote host. When a connection is established, the OnSessionConnected event is fired. You must not send data to the socket before this event is fired!! Example: @p $socket.OnSessionConnected = SOCKET_CONNECTED Alias SOCKET_CONNECTED TextOut > . clBlue *** We're connected!! EndAlias Socket errors ------------- If the socket fails, either while attempting to connect or during data transfer and so forth, the OnErrorOccurred event is fired: @p $socket.OnErrorOccurred = SOCKET_ERROR Alias SOCKET_ERROR TextOut > . clRed *** Error occurred while using socket!! EndAlias Note that "Connection reset by peer" (which occurs when a client closes a connection with a server) is treated as an error. By default, all errors will shut V96 down (I will endeavour to change this behaviour in future releases). Therefore it is STRONGLY recommended you have the following statement in: @p $socket.OnErrorOccurred = Nop NOP simply does nothing - this ensures that your application will continue whenever a socket error occurs. Sending data ------------ Data is sent with the SEND or SENDCRLF methods, which are identical except for that fact that SENDCRLF sends a CRLF at the end of the line, whereas SEND does not. Usually, you will use SENDCRLF. Example, which sends the string "Hello!!" after connecting to the host: @p $socket.OnSessionConnected = SOCKET_CONNECTED Alias SOCKET_CONNECTED $socket.SendCRLF Hello!! EndAlias Receiving data -------------- When data is received on the socket, the OnDataAvailable event is fired. You can receive the data by reading the socket's Text property. Note that reading the Text property REMOVES THE DATA FROM THE SOCKET'S QUEUE. RETRIEVING ITS VALUE AGAIN WILL CAUSE AN ERROR!! Therefore assign the value of the Text property to a variable at the beginning of the event code, and only reference that variable. Example, which sends "Good morning!!" back whenever "Hello!!" is received: @p $socket.OnDataAvailable = SOCKET_DATA Alias SOCKET_DATA @ $data = $prop($socket.Text) if ([$data] == [Good morning!!]) $socket.SendCRLF Hello!! endif EndAlias Closing the connection ---------------------- The socket connection can be closed with the SClose method, for example, this closes the connection when QUIT is received: @p $socket.OnDataAvailable = SOCKET_DATA Alias SOCKET_DATA @ $data = $prop($socket.Text) if ([$data] == [QUIT]) $socket.SClose endif EndAlias When the REMOTE END closes the connection, the OnSessionClosed event is fired. You must close the local end of the socket with SClose when this event is fired. You could do something like this: @p $socket.OnSessionClosed = $socket.SClose Cancelling listening -------------------- If you're listening on a port and wish to cancel listening, call the SCancelListen method. This listens on port 1234 and cancels listening when an incoming connection appears: @p $socket.Port = 1234 @p $socket.OnSessionAvailable = SOCKET_AVAILABLE $socket.SListen Alias SOCKET_AVAILABLE $socket.SAccept TextOut > . clBlue *** We're connected!! $socket.SCancelListen EndAlias TTimer ------ Timer creation is very simple, just use a TTimer object. First create the object, set the Interval property for the time interval, set the OnTimer event to the code you want executed every Interval milliseconds, and set Enabled to True to turn the timer on. Properties: Enabled - (True or False) Controls whether the timer is enabled or not Interval - The interval in milliseconds between the firing of the OnTimer event Events: OnTimer - This event is fired when the timer goes off (every Interval milliseconds) Example: @ $timer = $new(TTimer) @p $timer.Interval = 1000 @p $timer.OnTimer = BEEP @p $timer.Enabled = True This will beep every second. How unspeakably annoying!!