Difference between revisions of "Scripting"

From DXLog.net
Jump to navigation Jump to search
(C# Script Structure)
Line 24: Line 24:
 
<br>
 
<br>
 
<code>Main</code> - is called each time the script is called with a defined shortcut or from a macro message.<br>
 
<code>Main</code> - is called each time the script is called with a defined shortcut or from a macro message.<br>
[[File:DXLog_script_references.PNG|200px|thumb|right|Required references in Visual Studio's Solution Explorer]]
 
 
<br>
 
<br>
 
To access DXLog.net internal objects and methods from the script, three main objects are available:<br>
 
To access DXLog.net internal objects and methods from the script, three main objects are available:<br>
 
<br>
 
<br>
<code>FrmMain</code> - Refers to the main Window - from this you can access any other public object in main code and you can access public properties, methods, hook on events etc. This object has access to everything within in the main DXLog.net code.<br>
+
<code>FrmMain</code> - Refers to the main Window - from this you can access any other public object in main code and you can access public properties, methods, hook on events etc.<br>
 +
This object has access to everything within in the main DXLog.net code.<br>
 
<br>
 
<br>
 
<code>ContestData</code> - Contains all the properties and methods related to the currently open log.<br>
 
<code>ContestData</code> - Contains all the properties and methods related to the currently open log.<br>
 
<br>
 
<br>
<code>COMMain</code> - The main communications object which is used to access everything that is configured in the "Configure interfaces" window. Via this you can e.g. access the radio(s) or any other enabled serial or parallel port object.<br>
+
<code>COMMain</code> - The main communications object which is used to access everything that is configured in the "Configure interfaces" window. <br>
 +
Via this you can e.g. access the radio(s) or any other enabled serial or parallel port object.<br>
 
<br>
 
<br>
An extremely valuable feature of Visual Studio is the "Intellisense" mechanic which allows interactive searching for available objects and methods. By adding references to the DXLog.net binaries in Visual Studio's Solution Explorer, Intellisense will be able to automatically list available options for objects as you type, and you will also be able to search for objects and methods by name using the top search bar in Solution Explorer or by using the Object Browser.<br>
+
[[File:DXLog_script_references.PNG|200px|thumb|left|Required references in Visual Studio's Solution Explorer]]
 +
An extremely useful feature of Visual Studio is the "Intellisense" mechanic which allows not only as-you-type syntax checking but also interactive searching for available objects and methods.<br>
 +
By adding references to the DXLog.net binaries in Visual Studio's Solution Explorer, Intellisense will be able to automatically list available options <br>
 +
for objects as you type, and you will also be able to search for objects and methods by name using the top search bar in Solution Explorer or by using the Object Browser.<br>
 
<br>
 
<br>
You add references to the binaries by right-clicking on "References", select "Add Reference" and in the bottom of the Reference Manager panel use the "Browse" button. The DXLog.net binaries are typically located in <code>C:\Program Files (x86)\DXLog.net</code> on 64-bit Windows or <code>C:\Program Files\DXLog.net</code> on 32-bit Windows.<br>
+
You add references to the binaries by right-clicking on "References", select "Add Reference" and in the bottom of the Reference Manager panel use the "Browse" button.<br>
 +
The DXLog.net binaries are typically located in <code>C:\Program Files (x86)\DXLog.net</code> on 64-bit Windows or <code>C:\Program Files\DXLog.net</code> on 32-bit Windows.<br>
 
<br>
 
<br>
 
Important: the custom C# code script must be included as source code, DO NOT COMPILE.<br>
 
Important: the custom C# code script must be included as source code, DO NOT COMPILE.<br>

Revision as of 05:16, 12 May 2019

Introduction to C#

DXLog.net has been written in such a way that bespoke C# scripts can be written by the end user and will be compiled into DXLog.net at runtime.

This makes DXLog.net very versatile and with a little C# knowledge a very powerful contest logging tool.

To learn the basics about C# there are lots of free on-line help like http://www.homeandlearn.co.uk/csharp/csharp.html

Microsoft have a free fully functional version of Visual Studio called Community, available from https://visualstudio.microsoft.com/vs/community

C# Script Structure

Scripts must start with references to the relevant objects:

  //INCLUDE_ASSEMBLY System.dll
  //INCLUDE_ASSEMBLY System.Windows.Forms.dll
  //INCLUDE_ASSEMBLY CWKeyer.dll


Each script needs to implement three methods, as shown in the examples below:

Initialize - is called when the script is compiled and the object created. This is used to hook on events or initialize additional properties etc.

Deinitialize - is called when the object is going to be closed, for example when we exit DXLog.net.

Main - is called each time the script is called with a defined shortcut or from a macro message.

To access DXLog.net internal objects and methods from the script, three main objects are available:

FrmMain - Refers to the main Window - from this you can access any other public object in main code and you can access public properties, methods, hook on events etc.
This object has access to everything within in the main DXLog.net code.

ContestData - Contains all the properties and methods related to the currently open log.

COMMain - The main communications object which is used to access everything that is configured in the "Configure interfaces" window.
Via this you can e.g. access the radio(s) or any other enabled serial or parallel port object.

Required references in Visual Studio's Solution Explorer

An extremely useful feature of Visual Studio is the "Intellisense" mechanic which allows not only as-you-type syntax checking but also interactive searching for available objects and methods.
By adding references to the DXLog.net binaries in Visual Studio's Solution Explorer, Intellisense will be able to automatically list available options
for objects as you type, and you will also be able to search for objects and methods by name using the top search bar in Solution Explorer or by using the Object Browser.

You add references to the binaries by right-clicking on "References", select "Add Reference" and in the bottom of the Reference Manager panel use the "Browse" button.
The DXLog.net binaries are typically located in C:\Program Files (x86)\DXLog.net on 64-bit Windows or C:\Program Files\DXLog.net on 32-bit Windows.

Important: the custom C# code script must be included as source code, DO NOT COMPILE.
Scripts can be located anywhere on your hard drive but must always be added using the scripts manager (Tools->Scripts Manager) in DXLog.net.

Example Scripts

Example scripts are available in the download directory http://dxlog.net/sw/#files%2Fdownload%2Fscript_examples

The following script is an example of a C# script which keeps the Elecraft K3 keyer speed in sync with the CW speed set in DXLog.net

 //INCLUDE_ASSEMBLY System.dll
 //INCLUDE_ASSEMBLY System.Windows.Forms.dll
 //INCLUDE_ASSEMBLY CWKeyer.dll
 
 using System;
 using System.Windows.Forms;
 using CWKeyer;
 
 namespace DXLog.net
 {
      public class Script : ScriptClass
      {
          FrmMain mainForm;
 
          public void Initialize(FrmMain main)
          {
              mainForm = main;
              if (mainForm._cwKeyer != null)
                  mainForm._cwKeyer.CWSpeedChange += new CWKey.CWSpeedChangeDelegate(handleCWSpeedChange);
          }
  
          public void Deinitialize()
          {
              // Unclear if this is required 
              if (mainForm._cwKeyer != null)
                  mainForm._cwKeyer.CWSpeedChange -= handleCWSpeedChange;
          }
 
          public void Main(FrmMain main, ContestData cdata, COMMain comMain)
          {
          }
 
           private void handleCWSpeedChange(int radioNumber, int newSpeed)
           {
               CATCommon radioObject = mainForm.COMMainProvider.RadioObject(radioNumber);
               if (radioObject == null)
               {
                   mainForm.SetMainStatusText(String.Format("CAT object for radio {0} isn't available!", radioNumber));
                   return;
               }
               radioObject.SendCustomCommand(String.Format("ks0{0};", newSpeed));
               mainForm.SetMainStatusText(String.Format("Radio {0} CW speed changed to {1} wpm!", radioNumber, newSpeed));
           }
      }
 }

The following script triggers the built-in digital voice keyer on ICOM 7000-series radios.

 //INCLUDE_ASSEMBLY System.dll
 //INCLUDE_ASSEMBLY System.Windows.Forms.dll
  
 using System;
 using IOComm;
  
 namespace DXLog.net
 {
     public class IcomRunDVK1 : ScriptClass
     {
         const byte DVK = 1;
       
         // Bare CI-V Command to trigger DVK. 
         // Method SendCustomCommand() adds preamble, address, etc.
         readonly byte[] IcomDVKCommand = new byte[] { 0x28, 0x00, DVK }; 
  
         public void Initialize(FrmMain main) { }
  
         public void Deinitialize() { }
  
         public void Main(FrmMain main, ContestData cdata, COMMain comMain)
         {
             CATCommon radioObject;
             bool modeIsSO2V = (cdata.OPTechnique == 4);
  
             if (modeIsSO2V) // if SO2V send command to radio 1 regardless if VFO A or B are focused
                 radioObject = comMain.RadioObject(1);
             else
                 radioObject = comMain.RadioObject(cdata.FocusedRadio);
  
             if (radioObject == null)
             {
                 main.SetMainStatusText(String.Format("IcomRunDVK1: Radio {0} is not available.", 
                     cdata.FocusedRadio));
                 return;
             }
             radioObject.SendCustomCommand(IcomDVKCommand);
         }
     }
 }

The following script uses the FocusedRadioChange event to switch VFO knob focus and Dual Watch in SO2V on ICOM radios with dual receivers.

 //INCLUDE_ASSEMBLY System.dll
 //INCLUDE_ASSEMBLY System.Windows.Forms.dll
  
 using System;
 using IOComm;
  
 namespace DXLog.net
 {
     public class IcomSO2V : ScriptClass
     {
         ContestData cdata;
         FrmMain mainForm;
  
         readonly byte[] IcomDualWatchOn = { 0x07, 0xC1 };
         readonly byte[] IcomDualWatchOff = { 0x07, 0xC0 };
         readonly byte[] IcomSelectMain = { 0x07, 0xD0 };
         readonly byte[] IcomSelectSub = { 0x07, 0xD1 };
         readonly byte[] IcomSplitOff = { 0x0F, 0x00 };
         static byte[] IcomSetSpeed = new byte[4] { 0x14, 0x0C, 0x00, 0x00 };
  
         bool tempStereoAudio;
 
         // Executes at DXLog.net start 
         public void Initialize(FrmMain main)
         {
             CATCommon radio1 = main.COMMainProvider.RadioObject(1);
             cdata = main.ContestDataProvider;
             mainForm = main;
                
             // Initialize temporary stereo mode to DXLog's stereo mode to support temporary toggle
             tempStereoAudio = (mainForm.ListenStatusMode != 0); 
  
             // Only subscribe to event and initialize if radio is ICOM
             if (radio1 != null)
                 if (radio1.IsICOM()) { // nesting if since method only valid if radio1 is != null
                     cdata.FocusedRadioChanged += new ContestData.FocusedRadioChange(HandleFocusChange);
  
                     // Initialize radio to DW off, Split off and Main VFO focused
                     radio1.SendCustomCommand(IcomDualWatchOff); 
                     radio1.SendCustomCommand(IcomSelectMain);
                     radio1.SendCustomCommand(IcomSplitOff);
                 }
         }
         
  
         public void Deinitialize() { } // Do nothing at DXLog.net close down
  
         // Toggle dual watch, execution of Main is mapped to a key, 
         // typically in upper left corner of keyboard
         public void Main(FrmMain main, ContestData cdata, COMMain comMain)
         {
             int focusedRadio = cdata.FocusedRadio;
             CATCommon radio1 = comMain.RadioObject(focusedRadio);
             bool radio1Present = (radio1 != null);
  
             if ((focusedRadio == 1) && cdata.OPTechnique == 4) // Only active in SO2V
                if (tempStereoAudio)
                 {
                     if (radio1Present)
                         radio1.SendCustomCommand(IcomDualWatchOff);
                 }
                 else
                 {
                     if (radio1Present)
                         radio1.SendCustomCommand(IcomDualWatchOn);
                 }
             tempStereoAudio = !tempStereoAudio;
         }
  
         // Event handler invoked when switching between radios (SO2R) or VFO (SO2V) in DXLog.net
         private void HandleFocusChange()
         {
             CATCommon radio1 = mainForm.COMMainProvider.RadioObject(1);
             int focusedRadio = mainForm.ContestDataProvider.FocusedRadio;
             // ListenStatusMode: 0=Radio 1, 1=Radio 2 toggle, 2=Radio 2, 3=Both
             int listenMode = mainForm.ListenStatusMode;
             bool stereoAudio = (listenMode != 0);
             bool modeIsSo2V = (mainForm.ContestDataProvider.OPTechnique == 4);
             int ICOMspeed;
  
             if (radio1 == null)
             {
                 mainForm.SetMainStatusText("IcomSO2V: Radio 1 is not available.");
                 return;
             }
  
             if (modeIsSo2V) // Only active in SO2V and with ICOM
             {
                 // Set temporary stereo mode to DXLog's stereo mode to support temporary toggle
                 tempStereoAudio = stereoAudio; 
  
                 if (focusedRadio == 1)
                     radio1.SendCustomCommand(IcomSelectMain);
                 else
                     radio1.SendCustomCommand(IcomSelectSub);
    
                 if (stereoAudio || (focusedRadio == 2))
                     radio1.SendCustomCommand(IcomDualWatchOn);
                 else
                     radio1.SendCustomCommand(IcomDualWatchOff);
             }
         }
     }
 }

Custom Forms

DXLog.net offers a unique customization ability in that you can design your own "subwindows" also referred to as Forms. A Form can contain information, data or metrics that you do not get from one of the standard DXLog.net windows. A sample file can be found at http://dxlog.net/sw/files/development/csharp_DXLCusForm1.rar

A custom form is installed as a DLL file in a subfolder to DXLog.net's installation folder. Contrary to DXLog.net script files, this means you have to compile your code into an executable binary.

Some advice for designing custom Forms in DXLog.net:

  • To write, modify and compile custom Forms you need to install Visual Studio. The "Community" version is free for personal use.
  • The example code should be opened through its solutions file (.sln)
  • If you can not see the code, right click on the Form and select "view code"
  • Just as with the scripts, you need to add proper references to relevant parts of the DXLog.net binaries such as DXLog.net.exe, DXLogDAL.dll etc. Without this, Visual Studio Intellisense will complain about e.g. variable names not being available and you will not be able to build.
  • Make sure Visual Studio is set up to build for x86. (Click on the selection arrow where it says "any CPU" and change to "x86")
  • The shortcut key to building the binary is Shift-Ctrl-B.
  • If it does not already exist, create a folder called "CustomForms" in the DXLog.net data folder, typically C:\Users\YOURUSERNAME\AppData\Roaming\DXLog.net\CustomForms. This folder is easily accessible from the File->Open configuration directory drop down menu option.
  • Copy the created DLL file (located in ...DXLCusFrm1\bin\x86\Debug or similar, depending on your settings.) to the CustomForms folder.
  • Start DXLog.net and find a new drop-down menu called "Custom" between "Windows" and "Help". Use it to activate your new custom Form.

You can contain as many custom Forms as you like in a single DLL but they must

  • Have different names (of the KForm)
  • Have different FormsID (change both in the CusFormID method for the class and in the Form's property)