Using UI Toolkit with .NET
You can use UI Toolkit code with the Microsoft .NET Framework in three ways:
- Use the Toolkit .NET routines to embed .NET forms in Toolkit windows. With this method, you compile the application with the traditional Synergy compiler and then run the application with the traditional Synergy runtime. See .NET Routines for information.
- Include Toolkit code in Synergy routines called from xfNetLink .NET. For information, see Creating Synergy .NET Assemblies and UI Toolkit routines.
- Build and run the Toolkit application as a Synergy .NET application with a cell-based appearance. This is an unsupported option. See Building and running a UI Toolkit application as a cell-based Synergy .NET application below.
Building and running a UI Toolkit application as a cell-based Synergy .NET application
In .NET, most Toolkit routines and Script commands are available, though they result in applications with cell-based rather than Windows-like appearance and functionality. For example, the mouse won’t work in most instances. Note the following:
- Toolkit routines generally function as they do on Unix (non-.NET), e.g., %U_SAVESETTINGS always returns false. But there are exceptions. Some of these are listed below; others are documented with the routines they apply to.
- Code with calls to the following routines won’t compile: %AX_TKCALL, AX_TKGET, %AX_GETINT, AX_TKSET, %TB_BUTTON, %TB_INFO, %TB_TOOLBAR, and the Script compiler routines (%SCR_ routines).
- Native .NET status bars are used for the information line and footer. (.NET Framework and .NET 6.0 Windows and higher only)
- Native .NET controls are used for menus, but automatic menu drop-down is not supported, the input string passed to M_PROCESS is not used, and the only alignment settings supported for %M_POPUP are D_POPUP_LEFT and D_POPUP_RIGHT. (.NET Framework only)
- Arguments with the “any” type cannot take objects. For example, you cannot pass an object as one of the method data arguments for C_PROCESS.
- Bounds checking is automatically provided by the Synergy .NET compiler, but for more complete bounds checking, you can use g_dtkbounds (or DTK_BOUNDS) and DTK_BOUNDS_LOG. See Bounds checking.
- By default, Toolkit uses cell-based-style message boxes for U_MESSAGE, %U_MSGBOX, and U_WAIT.
- There are some restrictions on the ways you can use global fields in tkctl.def and tools.def. See Restrictions for global fields below.
The following is a summary of the process you’ll follow to use Toolkit code with .NET. See Debugging Synergy Programs.
1. | Create a Synergy project in Visual Studio. |
2. | Add a reference to Synergex.SynergyDE.tklib in your project. For .NET Framework projects, this is a .dll installed in a CLR directory under Program Files\Common Files\Synergex. For .NET 6 and higher, you should add a reference to the Synergex.SynergyDE.tklib NuGet package. |
3. | Use supported Synergy DBL and Toolkit routines to create the program. You can also define your Toolkit windows in windows script files and then compile the script files with Proto or Script. (See step 1 through step 3 of Getting started with UI Toolkit.) Script and Proto run only in traditional Synergy, but the libraries they create are compatible with Toolkit applications for .NET. |
4. | Build your application in Visual Studio. This creates an .exe or a .dll assembly. |
Restrictions for global fields
When using Toolkit code with .NET, there are some limitations to the ways you can use global fields defined in tools.def and tkctl.def. The following are not supported:
- Ranging when assigning a value—for example, “g_entnam(7:4) = number”. Instead, you can assign the value of the global field to a temporary field and then use ranging with that field.
- Assigning a value from a different type (implicit conversion). Instead, use explicit conversion.
- Assigning a value and then using the result of the assignment in the same statement, for example, “if (g_select = value)”. Instead, separate the assignment and the use of the assignment into two statements:
g_select=1 if(g_select)...
- Modifying through a cast—for example, “clear ^i(g_entnam)”. Instead, use a temporary field:
clear ^i(temp_var) g_entnam=temp_var
- Accessing groups or record names.
- Passing global fields as modifiable parameters to subroutines, functions, or methods. Instead, you can pass a temporary field and then assign its value to a global field.