Welcome to Programming Guide

Welcome to the Programming Guide.


Introduction to Programming in Origin

Origin includes two programming languages each with different characteristics. Origin C is a high level full featured compiled language closely based on the ANSI C programming syntax and includes some elements of C++ and C#. LabTalk is a C like scripting language with commands and built-in objects having methods and properties. This section introduces the general topic of programming in Origin, compares Origin C and LabTalk, highlights several ways to get programming related help, and lists OriginPro programming features.


Advantages to Programming in Origin

Origin is designed to meet the graphing and data analysis needs of scientists and engineers in diverse areas of academics and industry. To accomplish this, Origin provides a broad range of tools for importing, analyzing, graphing, presenting, and exporting data. As you gain familiarity with Origin, you may want to customize Origin to meet your specific graphing and analysis needs. Common customization needs include:

  • Adding functionality to Origin by creating new importing, analysis, graphing, and exporting routines.

  • Automating the work that you do in Origin.

  • Performing numerical computation and simulations in Origin.

These types of customizations can be achieved using Origin's programming language, Origin C and/or Origin’s scripting language, LabTalk.

The primary objective of the this guide is to help you learn more about how you can tailor Origin to meet any custom graphing or analysis need you might have. In addition to this guide, you might also find it helpful to review the many sample Origin projects and associated programming source files that are installed in the \Samples\Programming subfolder of Origin.


LabTalk vs Origin C

 | Origin C | LabTalk
Compiled? | Yes Programs can also be saved to disk in a pre-compiled form for faster recall. | No
Speed | A compiled language, so it is much faster (up to 20 times) than LabTalk. Especially well suited to computationally intensive operations and it is ideal for user-defined curve fitting functions. | An interpreted language. Relatively slow, especially in the case of loops requiring many iterations.
Access to internal Origin objects | Yes Access is object-oriented. At present, it provides access to most internal objects. | Yes
Case sensitive? (commands and variables) | Yes Origin C is case sensitive. Function names are also case sensitive. | No
Functions | Yes Standard rules of C language apply for calling functions. This is much more convenient than calling script file sections in LabTalk. | No LabTalk has the ability to call sections in script files having .OGS extensions. This allows the passing of simple text arguments.
Mode of execution | Origin C code is organized in functions. Functions can be called from other Origin C functions in the standard way by passing arguments of different types. Functions accepting strings, doubles, and vectors (datasets) of strings and doubles and can be called from the Script window, from LabTalk scripts, from menu commands and toolbars buttons, as well as from buttons on various Origin windows (graphs, worksheets, etc.). | LabTalk scripts are usually organized by sections in .OGS script files. They can be called using the run.section() command from either Script window or from another LabTalk script. Also, LabTalk scripts can be typed directly to the Script window and executed from there. They can be associated with menu commands or toolbar buttons, or with buttons on various Origin windows (graphs, worksheets, etc.). LabTalk scripts can also be executed from Origin C.
Variable types | Yes All standard C types are supported, as are pointers. Object-oriented access to Origin objects is supported.In addition, Tree and XML objects are also supported.All variables must be declared before being used. | Yes Only numeric (double precision) and string variables are supported. Variables representing internal Origin objects are not supported. It is possible to refer to various global objects, such as the active window, layer, etc.
Local variables | Yes Local variables in functions must be declared before being used, (as is standard in the C language). | No
Global variables | Yes All global variables must be declared outside functions before being used. | Yes All variables are global variables. These global variables are either numeric or string. Variables do not have to be declared before use - they are defined and space in memory is reserved for them on first use.
Multidimensional objects | Yes Origin C supports vector and matrix classes (and the associated classes Dataset and Matrix which provide access to Origin’s internal datasets and matrices). | No
Collections | Yes Origin C supports various collections of internal Origin objects, such as the collection of all windows in a project, all columns in a worksheet, all data plots in a graph layer, etc. Collections allow for easy enumeration and access to the items being held in the collection. | No
Control structures | It supports all C-style control structures (if-else, switch, for, while, do-while, goto). It also supports foreach loops which provide a simple way to enumerate all members of a collection. | LabTalk supports C-like if-else and switch statements. It also supports C-like for-loop, as well as LabTalk-specific repeat and loop looping control structures.
Writing user-defined fitting functions | Yes Compiled Origin C functions greatly increase curve fitting speed. | Yes
Calling external functions (functions written in external DLLs) | Yes A function implemented in an external DLL (the function must be exported from the DLL in a standard way) can be called from Origin C. This enables use of proprietary routines written in standard Windows DLLs, to be used inside of Origin. This is no more difficult than calling another Origin C function. | No

LabTalk vs Origin C

Origin's newest programming language is called Origin C. Origin C supports a nearly complete ANSI C language syntax as well as a subset of C++ features (including built-in, user-defined, and DLL-extended classes) and a few C# features (including Collections and the using and foreach commands). In addition, Origin C is "Origin aware." This means that Origin objects such as worksheets and graphs are mapped to classes in Origin C allowing direct manipulation of these objects and their properties from Origin C.

LabTalk is Origin’s original programming language. LabTalk is a scripting language and, as such, is well suited to cobbling together many of the graphing and analysis operations that you might perform as standalone actions (e.g. FFT, graphing, graphic export, etc.) through the Origin user interface. LabTalk provides access to many internal Origin objects such as graphs, worksheets, data plots and their properties, menus, etc.

For many years users have successfully automated their Origin routines using LabTalk and we will continue to support LabTalk for the foreseeable future. However, LabTalk is not well suited to tasks where speed is crucial – importing large data files, curve fitting where large data sets or complex functions are involved, operations which require a large number of program loops to complete, etc. For this and other reasons, Origin C was developed.

Origin C is a compiled language and is much better suited to computationally intensive operations than LabTalk. Like LabTalk, it provides access to many internal Origin objects. Origin C control of Origin is still developing and some internal object properties are only accessible from LabTalk. However, Origin C is evolving rapidly so that the gap is rapidly being closed. In many ways Origin C surpasses LabTalk with regard to access to internal Origin objects. In addition, Origin C excels with regard to speed and access to powerful programming features in general.

If you are upgrading from a previous version of Origin and you have written LabTalk scripts to perform operations, you should consider upgrading your scripts to Origin C – particularly if you are performing numerical computational loops. In some cases, Origin C code is 20 times faster than LabTalk script.

In addition, Origin C functions that accept string, double, or vectors of string and double are accessible from the Origin interface just like any other LabTalk command is accessible. This enables you to expand the scripting language of Origin by creating custom commands that are based on your custom Origin C functions.

The following table contrasts Origin C versus LabTalk.


Getting Help

Origin provides a number of resources to help you program in LabTalk and Origin C. Chief among those resources is the Programming Help file accessed by the Origin and Code Builder Help:Programming menu items. The Programming Help file contains the following books:

Code Builder User’s Guide: The Code Builder User’s Guide contains detailed explanations of how to use Code Builder. Code Builder is an Integrated Development Environment (IDE) inside Origin that is used to code and debug programs written in Origin’s two programming languages LabTalk and Origin C.

Programming Guide: The Programming Guide describes many of the most important Origin programming topics including programming in Origin C, user interface development in both standard and professional versions of Origin, COM programming, and how to distribute your custom applications once completed. Descriptions include many small and easily understood examples with brief explanations. Source files containing most example code are provided and can be found in the \Samples\Programming subfolder of Origin.

Origin C Language Reference: The Origin C Language Reference provides detailed reference information on every Origin C class member function and global function. Reference information includes the function prototype, remarks, a summary of parameters and return values, example code, the name of the header file containing the prototype, and links to related functions.

Origin Automation Server Reference: The Origin Automation Server Reference provides detailed reference information on Origin Automation Server methods and properties. Reference information for methods includes the function prototype, remarks, a summary of parameters and return values, VB example code, and links to related properties and functions. Reference information for properties includes the property type and name, remarks, VB example code, and links to related properties and functions.

LabTalk Language Reference: The LabTalk Language Reference contains information on the LabTalk commands, objects, functions, and macros.

Additional Resources:

  • Programming Tutorials are available by selecting the Origin and Code Builder Help:Tutorials menu items. There are several programming tutorials in the Programming book of the Tutorials Help file.

  • Sample Origin projects containing embedded Origin C source files are included in the \Samples\Programming subfolder of Origin. Additionally, source files illustrating basic Origin C operations are included in the \Samples\Programming\Origin C Files subfolder of Origin.

The following resources are also available on the OriginLab web site (www.OriginLab.com):

  • Origin and Origin C user forums are available to share ideas and ask questions of other Origin users.

  • OriginLab's programming resources web page provides sample code, frequently asked questions, and access to the OriginLab knowledge database.

  • Technical Support is available for resolving problems using Code Builder, discussing general programming strategies, and for troubleshooting small sections of code. Additional more detailed support is available through Consulting.


OriginPro Features

OriginPro includes all the features found in Origin plus additional tools for building custom applications. After development, these custom applications can be run on standard Origin or on OriginPro. The OriginPro development tools include – but are not limited to - the following:

  • COM Client Programming. Create Origin C programs which use Component Object Model (COM) to interact with other software applications (e.g. Microsoft® Word, Microsoft® Excel, or Seagate® Crystal Reports). Import and export data from a Microsoft® XML document. Read data from a database (e.g. Microsoft® Access or Microsoft® SQL Server).

  • Automation Server Programming with Multiple Clients. Communicate with OriginPro from other applications, such as Microsoft® Excel, that support COM programming. Supports multiple client access using a reservation and polling mechanism (multi-threading is not supported).

  • Dialog Builder. Create sophisticated custom interfaces for your graphing and analysis routines utilizing industry standard controls. Create dialog boxes, tabbed dialogs, and wizards. Access object properties and methods of controls and dialogs from Origin C. Integrates with industry standard development software for creating graphical user interfaces. Save Wizard procedures as Origin toolbar buttons for later re-use.

  • ActiveX. Include ActiveX® controls in Dialog Builder dialogs and wizards. Build Data Acquisition Systems using ActiveX controls for real-time display as well as instrument controls.

  • Source Code Protection with Encryption. Protect proprietary source code with encryption. Origin Standard and OriginPro users can run your Origin C code but not see source files.


Introduction to Programming in Origin C

Origin C is a full featured high level programming language closely based on the ANSI C programming language syntax. In addition, Origin C supports a number of C++ features (including mid-stream variable declarations, overloaded functions, built-in and user-defined classes, references to variables, and default function arguments) and a few C# features (including collections of objects, and the foreach and using statements). Origin C programs are developed in Origin’s Integrated Development Environment (IDE) named Code Builder. Code Builder includes an editor, a workspace window, a debugger with a variables and watch window, a call stack, an output window, a command console, and a compiler and a linker. Origin C functions are compiled into object code, loaded, and then run inside of Origin. Using Origin C, developers can take full advantage of Origin’s many data import, data handling, graphing, analysis, and image export capabilities. Combined with numerous user interface controls included in Standard Origin (label buttons, toolbar buttons, menu items, and simple dialogs) and/or OriginPro’s ability to make more advanced dialogs and wizards, developers can make powerful tools and add-on modules of their own.

The following sections of this help file describe several of Origin C’s most useful features. Topics covered include supported data types, control structures, input and output, built-in Origin C classes, accessing internal Origin objects, collections of objects, trees and XML, accessing global and NAG functions, LabTalk access from Origin C, extending Origin C via external DLLs and user-defined classes, compiling, linking, and loading Origin C functions, and calling Origin C functions from Origin. The descriptions include many small and easily understood examples with brief explanations. The source code for most example functions can be found in the \Samples\Programming subfolder of Origin. A few example source files can also be found in the \Tutorial subfolder of Origin. Most users will find it helpful to open source files in Code Builder and run them in debug mode while reading the help file. For more information on debugging in Code Builder see the debugging tutorial by selecting the Help:Tutorials menu item in Origin or Code Builder. For more complete information on Origin C global functions and built-in classes see the Origin C Language Reference.

The remainder of this section covers ANSI C, C++, and C# supported features in more detail. In addition, a brief discussion on the organization of Origin C files and a “Hello World!” tutorial is included.


ANSI C Support

With some exceptions (e.g. the main function is not used in Origin C), Origin C supports a nearly complete ANSI C language syntax, including support of ANSI C elements, program structure, declarations and types, expressions and assignments, statements, functions, and syntax.

ANSI C features not supported by Origin C:

  • Origin C only supports one-dimensional arrays. Thus, the following declaration is not supported:

int aa[5][6];

Instead, you can declare a matrix object for support of dynamic two-dimensional arrays:

matrix<int> aa(5, 6);

  • Origin C does not support the use of the extern storage class specifier on functions (but does support extern variables).

Also, Origin C differs from ANSI C in that Origin C treats ^ as an exponentiate operator. Thus, x^y is equivalent to pow(x, y).

To treat ^ as the ANSI C bit wise exclusive OR operator in your Origin C function, you can use the xor pragma:

#pragma xor(push, FALSE)


C++ Support

void DeclareVariablesAnywhere()

{

vector<double> v1;

v1.SetSize(10);

for(int ii = 0; ii < 10; ii++)

{

v1[ii] = rnd(ii);

}

double val = v1[0];

printf("%f\n", val);

}

// Overloaded Functions

double Max(double, double);

int Max(int, int);

void OverloadedFunctions()

{

int ii = Max( 20, 5 );

double dd = Max( 15.5, 30.0 );

printf("The Max int is %d\n", ii);

printf("The Max double is %.1f\n", dd);

}

// Max of doubles

double Max(double d1, double d2)

{

return ( d1 > d2 ) ? d1 : d2;

}

// Max of ints

int Max(int i1, int i2)

{

return ( i1 > i2 ) ? i1 : i2;

}

// Pass by reference

void ChangeVals(int in1, int& in2)

{

in1 = in1 + 100;

in2 = in2 + 100;

printf("in1 =%3d and in2 =%3d\n", in1, in2);

}

void PassByReference()

{

int val1 = 5, val2 = 10;

printf("val1=%3d and val2=%3d\n", val1, val2);

ChangeVals(val1, val2);

printf("val1=%3d and val2=%3d\n", val1, val2);

}

// Default Arguments

int GetVolume(int length, int width = 2, int height = 3);

void DefaultArguments()

{

int x = 10, y = 4, z = 5;

out_int("Volume (10*4*5)=", GetVolume(x, y, z));

out_int("Volume (10*4*3)=", GetVolume(x, y));

out_int("Volume (10*2*3)=", GetVolume(x));

}

int GetVolume(int length, int width, int height)

{

return length * width * height;

}

C++ Support

In addition to ANSI C support, Origin C supports a number of C++ features including the following bulleted items. All example code for this page is contained in the OriginCSupportsEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.

  • Variable declarations that are not restricted to the beginning of a block.

The following example code illustrates this:

  • Overloaded function names.

The following example code defines the max function twice, with different formal parameters and return values. The correct function is called based on the arguments in the calling function.

Important! Overloaded functions cannot be called from LabTalk; they can only be called from other Origin C functions.

  • Support for built-in and user-defined classes.

Origin C provides a number of useful built-in classes and allows users to create their own classes. See the sections Built-in Origin C Classes and Extending Origin C via User-Defined Classes for more information. Built-in Origin C classes are used to provide programmatic access to external applications, to composite data types, to internal Origin objects, to system objects, and to user interface controls (see the section Accessing Internal Origin Objects for more information on using Origin C classes to access internal Origin objects). User-defined classes allow users to create their own object types with user-defined properties and methods in Origin C.

  • Passing arguments to functions by reference.

The following example code illustrates how you can pass a variable (in this case in2) by reference to a function. Note that upon return from the function ChangeVals the variable val1 is the same but the variable val2 has been changed.

  • Default argument values.

Origin C supports functions with default arguments as illustrated in the following example code:


C# Support

// Print column names

void PrintColNames()

{

Worksheet wks("Data1");

if( wks.IsValid() )

{

// wks.Columns is collection of columns

foreach( Column col in wks.Columns )

{

printf("%s\n", col.GetName());

}

}

}

// Using keyword

void UsingKeywordEx()

{

Worksheet wks;

// wpg is "shorthand" for wks.GetPage:

using wpg = wks.GetPage();

if(wks.Attach("Data1"))

out_str(wpg.GetName());

if(wks.Attach("Data2"))

out_str(wpg.GetName());

}

C# Support

Origin C also supports a subset of C# features, including the following bulleted items. All example code for this page is contained in the OriginCSupportsEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.

  • Support of Collections.

Origin C provides Collections for efficient looping through objects of the same type using the foreach statement. For example, the Project class provides Collections for all child windows in a project, and for all the worksheet, graph, note, matrix, and layout windows in a project. Other classes also provide Collections. For example, the Page class provides a collection of all the layers on a page.

  • Support of the foreach statement.

Origin C provides a foreach statement to loop through elements in a Collection. The following example code illustrates the use of the foreach statement.

  • Support of the using statement.

You can use the using statement to create a shorthand notation for calling member functions from a base class. For example, in the following code, the using statement assigns wks.GetPage() to wpg. The example assumes that the Data1 and Data2 worksheets exist in the open project file.


Organization of Origin C Files

During the Origin installation, the following Origin C related subfolders are created:

  • \OriginC: This is the default location for saving source (*.C and *.CPP), header files (*.H), and workspace (*.OCW) files.

  • \OriginC\OriginLab: This folder contains source, header, and workspace files that are used by built-in Origin tools.

  • \OriginC\system: This is the standard include directory for Origin C. The Origin C header files available for general use are installed to this folder, except for the NAG header files, which are installed into the \OriginC\system\NAG subfolder. This folder also contains several source (*.C) files which contain function definitions used by built-in Origin tools. These functions are also available for general use.

  • \Samples\Programming: This folder contains a number of Origin project files (*.OPJ) which contain embedded Origin C files that demonstrate various programming topics. It also contains several subfolders including \Origin C Files and \User Interface Development. The \Origin C Files subfolder contains a number of Origin C sample files many of which are used in the Programming Guide and the \User Interface Development subfolder contains a mix of file types (including *.OPJ, *.OGS, *.INI, *.CNF, *.C) implementing user interface related examples.

  • \NAG PDFs: This folder contains the NAG PDF documents for the NAG libraries included in Origin. It is only available if you selected this option during installation. If you did not install the PDFs, they remain accessible on your installation CD. Furthermore, you can install them at a later date by running the Origin "Add or Remove Files" program.


"Hello World!" Tutorial

    1. Click the Code Builder button [image] on Origin's Standard toolbar.

    2. Click the New button [image] on Code Builder's Standard toolbar.

    3. Select C File from the list box.

    4. Type Tutorial in the File Name text box.

    5. Click OK to close the dialog box and open the new file in Code Builder's Multiple Document Interface (MDI).

    6. Copy or type the following Origin C code beneath the line that reads // Start your functions here.

void test()

{

printf("Hello World!\n");

}

    7. Click the Build button [image] on Code Builder's Standard toolbar to compile and link the Tutorial.C source file. The Output window should display:

compiling...

Tutorial.c

Linking...

Done!

    8. To test this function in Code Builder, click in the upper pane of the LabTalk Console located in the bottom right corner of Code Builder. (This is the default location after installing Origin. If the LabTalk Console isn't open, select the View:LabTalk Console menu item in Code Builder to open it.)

    9. Type the following LabTalk function call in the LabTalk Console and then press ENTER:

test

"Hello World!" displays in the lower pane of the LabTalk Console.

In the next series of steps, you'll modify the Custom.OGS script file so that you can call your "Hello World!" function from the Origin interface.

    1. Click the Open button [image] on Code Builder's Standard toolbar.

    2. From the Files of Type drop-down list, select 'LabTalk Script File (*.OGS)'.

    3. In your Origin folder, select the file Custom.OGS and click Open. The Custom.OGS script file opens in the Code Builder MDI.

    4. Comment the line that currently reads:

type -b $General.Userbutton;

so that it reads:

//type -b $General.Userbutton;

    5. Beneath this line, copy or type the following code:

if(run.LoadOC("Tutorial.c")!=0)

type -b "Cannot load Origin C file.";

else

test();

Important: The run.LoadOC LabTalk method loads, compiles, and links the specified Origin C source file. You don't need to use this method if your source file is already compiled and linked (as in this example). However, if you will be calling the function in a future Origin session, or if you are developing a GUI interface or if you will be distributing your custom application, you must execute this method before calling your function. For a general discussion on compiling strategies, see Four Methods of Building the Code Builder Workspace.

    6. Click the Save button [image] on Code Builder's Standard toolbar.

    7. Make Origin the active application.

    8. Open the Script window if it is not already open (select the Origin Window:Script Window menu item).

    9. Click the Custom Routine button [image] on Origin's Standard toolbar.

"Hello World!" displays in the Script window.

"Hello World!" Tutorial

This tutorial introduces you to Origin C and Code Builder by having you write a simple Origin C program. You will then link your program to a toolbar button and execute the program by clicking the button.

While the program itself may be trivial, we hope it inspires you to think about ways in which you might use Origin C to develop your own custom graphing and analysis routines.

Programming and Calling Your Origin C Function

Calling Your Function from the Custom Routine Button


Supported Basic and Derived Data Types

Origin C supports integer, floating point, void, and character basic types. The following topics summarize the supported basic types.


Integer Data Types

Data Type | Values | Memory
int ---- synonyms include LONG, long, BOOL | -2,147,483,648 to 2,147,483,647 BOOL (TRUE or FALSE) | 4 bytes
unsigned int or uint ---- synonyms include size_t, UINT, DWORD | 0 to 4,294,967,295 | 4 bytes
short ---- synonyms include short int, signed short int | -32,768 to 32,767 | 2 bytes
unsigned short or ushort ---- synonyms include unsigned short int, WORD | 0 to 65,535 | 2 bytes
bool | true or false | 1 byte
byte ---- BYTE | 8-bit integer that is not signed. | 8-bit


Floating Point Data Types

Data Types | Values | Memory
double | 1.7E +/- 308 (15 digits) | 8 bytes
float | 3.4E +/- 38 (7 digits) | 4 bytes


Character(s) Data Types

Data Type | Values | Memory
char | one ASCII character enclosed in single quotation marks | 1 byte


Other Data Types

The void type can be used when the type is unknown or for functions that do not return a value. Pointers to voids are supported in Origin C.

Origin C also supports the ANSI C supported derived types including one-dimensional arrays of variables or objects, pointers to variables or objects of a specific type, references to objects (address of an object), _VARIANTs, structures, enumerations, and pointers to functions.

Exceptions to the standard ANSI C support are the following:

  • Origin C does not support multi-dimensional arrays. However, you can declare a matrix object for support of dynamic two-dimensional arrays:

matrix<int> m(5, 6);

Origin C also provides support for a number of C++ class objects. Origin C provides several built-in classes for creating program objects to access and perform operations on composite data types such as strings, complex variables, trees, vectors, etc. and on internal Origin objects such as worksheets, columns, data sets, graphs, layers, etc. See the topics Built-in Origin C Classes and Accessing Internal Origin Objects for more information on built-in classes. In addition, Origin C supports user-defined classes. See the topics Extending Origin C via External DLLs and Extending Origin C via User-Defined Classes for more information on user-defined classes.


Control Structures

Origin C supports all ANSI C control structures including Statements and Blocks as well as the if, if-else, switch, for, while, do-while, goto, and break and continue statements. In addition, Origin C supports the C# foreach loop for collection objects. See the following topics for syntax, examples, and descriptions.


Statements and Blocks

An Origin C statement is an expression terminated by a semicolon such as the following examples.

int ii = 5;

dZ = fabs(dZ);

printf(“Now is the time for all good men to come to the aid of their country.”);

A block is a collection of statements grouped together by the curly braces { and }. A block of statements is considered to be syntactically equivalent to and can be substituted for a statement, wherever statements are allowed. Thus, wherever you see statement; specified as part of a syntax, you can substitute a block of statements. Variables declared within a block are local in scope to the block and do not exist outside the block. The following statements are grouped together in a block.

{

int ii = 5;

dZ = fabs(dZ);

printf(“Now is the time for all good men to come to the aid of their country.”);

}


if and if-else

if(condition)

statement;

For example,

if( a == 5 )

{

b = 6;

}

other statements;

Here, a == 5 is the condition.

If this condition is true (the value of a is 5), the statement

b = 6;

executes, followed by the execution of

other statements;

If the condition is false, then

b = 6;

does not execute, and only the following executes:

other statements;

if(condition)

statement;

else

statement;

For example,

if( a == 5 )

{

b = 6;

}

else

{

b = 8;

}

other statements;

Here again, a == 5 is the condition.

If this condition is true (the value of a is 5), the statement

b = 6;

executes (the statement b = 8 does not execute), followed by the execution of:

other statements;

If this condition is false, the statement b = 6 does not execute, but instead

b = 8;

executes, followed by the execution of:

other statements;

The if-else control structure can be chained together to form a multi-conditional branch as follows:

if(condition)

statement;

else if(condition)

statement;

else if(condition)

statement;

else

statement;

if and if-else

if and if-else are used for conditional branching of program execution.

The if control structure has the following syntax:

The if-else control structure has the following syntax:


switch

switch(n)

{

case 1:

b = 3;

break;

case 2:

b = n + 6; // Fall through to case 3

case 3:

b = 2 * n + b;

break;

default:

b = 10;

}

other statements;

switch

The switch statement has the following syntax:

switch(expression)

{

case constant-expression:

statements;

case constant-expression:

statements;

case constant-expression:

statements;

default:

statements;

}

For example:

The execution branches depending upon the value of the variable n.

If the value of n is 1, then the statement

b = 3;

is executed, after which break causes the execution to break out of the switch statement and execute

other statements;

If the value of n is 2, then the statement

b = n + 6;

is executed, after which execution falls through into case 3 since there is no break to break out of the switch statement. If execution falls through from case 2 or if the value of n is 3, then the statement

b = 2 * n + b;

is executed, after which break causes the execution to break out of the switch statement and execute

other statements;

If the value of n is neither 1, 2, or 3, the default statement

b = 10;

is executed after which the following is executed:

other statements;

Note: If you do not put break (or return) at the end of the statements for one case, the execution will fall through to the next case instead of breaking out of the switch statement.


for

The for loop has the following syntax:

for( expression; condition; expression )

statement;

For example,

for( ii = 0; ii < n; ii++ )

{

k + ii;

}

other statements;

The parentheses following the word for contain three separate expressions separated by semicolons. When the loop executes, the first of those three expressions

ii = 0;

is executed first. After that the following condition (i.e. expression) is evaluated:

ii < n;

If the condition is false, the execution of the for-loop ends and the following statements are executed:

other statements;

If the condition is true, the body of the loop (in this example, only a single statement) executes:

k = k + ii;

Subsequently, the third expression in the parentheses executes (the value of ii is incremented):

ii++

Once again, the condition is evaluated:

ii < n;

If the condition is false, the execution of the for loop ends;

Otherwise, the body of the loop is executed once more, the third expression in parentheses executes once more, etc., until the condition evaluates to false.


while

The while loop has the following syntax:

while( condition )

statement;

For example,

while( nn < kk )

{

bb += nn++;

}

other statements;

The parentheses following the word while contain the condition of the loop (in this case it is nn < kk). When the while loop executes, the condition is evaluated first.

If the condition is false, the execution of the loop ends and the following is executed:

other statements;

If the condition is true, the body of the loop (in this case the body is comprised of only one statement) executes:

bb += nn++;

Subsequently, the condition is re-evaluated. The looping continues until the condition evaluates to false.


do-while

The do-while loop has the following syntax:

do

statement;

while(condition);

For example,

do

{

bb += nn++;

} while( nn < kk );

other statements;

The parentheses following the word while contain the condition of the loop (in this case, nn < kk). When the do-while loop executes, the body of the loop (in this case, it is the single statement bb += nn++) executes once. Then the condition is evaluated.

If it is false, the execution of the loop ends, and the statements following the loop (other statements;) are executed.

If it is true, the body is executed again, and the condition is re-evaluated. The looping continues until the condition evaluates to false.

The primary difference between a do-while loop and a while loop is that the body of a do-while loop will always execute at least once even if the condition is initially false whereas the body of a while loop will not execute at all if the condition is initially false.


foreach

The foreach loop is used to loop through all the elements in a collection and has the following syntax:

foreach( elementType elementObject in collection )

statement;

The following example illustrates the use of the foreach statement.

// Declare and attach to Worksheet object Data1

Worksheet wks("Data1");

// wks.Columns is the collection of Columns in the worksheet Data1

foreach( Column col in wks.Columns )

{

cols.SetDigitMode(DIGITS_SIGNIFICANT);

cols.SetDigits(10);

}

In this example, the foreach loop loops once for each column in the Origin worksheet Data1. The Origin C Worksheet object wks contains a collection of columns in the worksheet Data1 named Columns. For each iteration of the loop, a column object named col is attached to the next column in the Data1 worksheet. The body of the loop then uses the Column object col to access the properties of each column in the worksheet.


goto

The goto command is not commonly used and is sometimes frowned upon in structured programming but is supported (as in ANSI C). The goto command has the following syntax:

goto Label;

statement(s);

Label: statement;

The following example illustrates the use of the goto command.

if( dd < 0 )

goto End;

dd = sqrt(dd);

End: return dd;

In this example, if the variable dd is less than 0 then control is transferred to the return dd; statement identified by the label “End.”


break and continue

for( ii = n1; ii < n2; ii++ )

{

if( ii == 0 )

continue;

dSum = dd / ii;

if( dSum < 0 )

break;

dd = sqrt(dSum);

}

other statements;

In the above for loop, if ii is 0 then the continue statement is executed causing the current iteration of the loop to end without computing dSum or updating dd. The next iteration of the loop begins immediately. If dSum is less than 0 then the break statement is executed, the for loop is exited, and program control is passed on to other statements.

break and continue

Any Origin C loop or the switch statement can be prematurely exited by using the break statement. Remaining statements in the body of an Origin C loop can be skipped and the next iteration of the loop immediately started by using the continue statement. When encountered inside nested loops the break and continue statements always break or continue the inner most loop.

The following example illustrates the use of the break and continue statements.


Input/Output

// Sample function to show different output methods

void BasicIOEx()

{

int ii = 6;

out_int("\nint ii = ", ii); // Basic I/O global method

double dd = -3.5;

out_double("\ndouble dd = ", dd); // Basic I/O global method

printf("\n");

string str = "This is a test.";

out_str(str); // Basic I/O global method

// Options WRITE_SCRIPT_WINDOW, WRITE_STATUS_BAR, WRITE_OUTPUT_LOG,

// WRITE_MESSAGE_BOX, WRITE_COMPILER_OUTPUT

str.Write(WRITE_SCRIPT_WINDOW); // string class method

str.WriteLine(WRITE_SCRIPT_WINDOW); // string class method

printf("\nint ii = %d,\tdouble dd = %g,\tstring str = %s\n", ii, dd, str);

complex cc(3.2, -4.9);

out_complex("\ncomplex cc = ", cc); // Basic I/O global method

Tree tr;

tr.Branch1.Node1.nVal = 6;

tr.Branch1.Node1.ID = 101;

tr.Branch1.Node1.Enable = 1;

tr.Branch1.Node1.Show = 0;

tr.Branch1.Node2.nVal = 7;

tr.Branch1.Node2.ID = 102;

tr.Branch1.Node2.Enable = 0;

tr.Branch2.Node1.nVal = 16;

tr.Branch2.Node1.ID = 201;

printf("\nout_tree:\n");

out_tree(tr); // Basic I/O global method

// Options WRITE_SCRIPT_WINDOW, WRITE_STATUS_BAR, WRITE_OUTPUT_LOG,

// WRITE_MESSAGE_BOX, WRITE_COMPILER_OUTPUT

tree_dump(tr, "\ntree_dump:", WRITE_SCRIPT_WINDOW); // Basic I/O global method

}

Input/Output

Origin C contains a number of built-in functions for outputting various types of variables and objects. Reference information for most of these functions is in the Basic I/O section of the Global Functions chapter of the Origin C Language Reference. Reference information for other output functions, including two string class methods, can be found in the Composite Data Types section of the Classes chapter of the Origin C Language Reference. The following table summarizes these functions and the data types which they output.

Function Prototype | In System Header File | Data Type Output
int out_complex(LPCSTR lpcstr, complex z); | Complex.h | complex
int out_double(LPCSTR lpcstr, double dbValue); | Stdio.h | double
int out_int(LPCSTR lpcstr, int nValue); | Stdio.h | int
int out_str(LPCSTR lpcstr); | Stdio.h | string
string::void Write( int iDestination );* | String.h | string
string::void WriteLine( int iDestination );* | String.h | string
bool out_tree(TreeNode& tr); | Tree_Utils.h | Tree
bool tree_dump(const TreeNode& tr,LPCSTR lpcstr , int iDestination);* | Tree_Utils.h | Tree
int printf(LPCSTR lpcszFormat, ...); | Stdio.h | <various>

* Where iDestination can be any of the enumerated values WRITE_SCRIPT_WINDOW, WRITE_STATUS_BAR, WRITE_OUTPUT_LOG, WRITE_MESSAGE_BOX, or WRITE_COMPILER_OUTPUT.

The following example code demonstrates the usage of each of these output functions. The example code can also be found in the sample file BasicIOEX.c in the \Samples\Programming\Origin C Files subfolder of Origin.

Several other Origin C functions exist which convey information to and/or solicit input from a user. See the section File Dialogs, Message Boxes, and Input Boxes for information on opening several variations of message boxes and see the section Creating Simple Dialogs: The GetN Dialog Box for information on how to easily create a multi-control GetN dialog box. For information on user interface development in general, see the User Interface Development and User Interface Development with OriginPro chapters.


Built-in Origin C Classes

In addition to most standard ANSI C features, the Origin C programming language supports a number of C++ features. One C++ feature supported in Origin C is classes. Origin C allows users to create their own classes (see the section Extending Origin C via User-Defined Classes for more information) and provides a number of useful built-in classes as well. Built-in Origin C classes are used to provide programmatic access to external applications, to composite data types, to internal Origin objects, to system objects, and to user interface controls. See the section Accessing Internal Origin Objects for more information on using Origin C classes to access internal Origin objects. Both user-defined and built-in Origin C classes support derivation and inheritance. In addition, Origin C classes support composition and can themselves contain complex data structures including data members constructed from other classes defined in Origin C.

For a complete listing of built-in Origin C Classes, see the following class derivation charts. See also the Classes book of the Origin C Language Reference. Please note that Origin C classes associated with internal Origin objects are generally listed with the first letter capitalized (e.g. Page, Layer, Worksheet, Dataset, etc.). Origin C classes related to objects not necessarily unique to Origin are generally listed with the first letter in lower case (e.g. string, complex, vector, matrix, etc.).

Click the links below to open a class derivation chart in a new instance of your browser.

Application Communication Classes

Composite Data Type Classes

Internal Origin Object Classes

System Classes

User Interface Control Classes


Application Communication Classes


Composite Data Type Classes


Internal Origin Object Classes


System Classes


User Interface Control Classes


Accessing Internal Origin Objects

Internal Origin objects (such as Project Explorer folders; Origin child windows (pages): graphs, worksheets, matrices, layouts, notes; layers; data plots; graphic objects; data sets; etc.) are accessed using built-in Origin C classes. To programmatically control an internal Origin object it must first be attached to an Origin C object. To attach an Origin C object to an internal Origin object you must “find” the internal object using the properties, methods, and collections of a container class. Common container classes include the Project, Folder, Page, GraphPage, Layer, GraphLayer, Worksheet, MatrixLayer, and Collection classes. Once found, an internal Origin object can easily be attached to an Origin C object of the appropriate type. The internal Origin object is then programmatically controlled by manipulating the class methods and properties of the attached Origin C object. This section demonstrates how to find particular internal Origin objects, how to attach Origin C objects to those objects, and how to access the internal Origin objects by manipulating the methods and properties of the attached Origin C objects.

Familiarity with the Origin C Project class (Project.h), the Collection class (Collection.h), and the Folder class (Folder.h), is valuable when attempting to understand how to find particular internal Origin Objects. User’s may find it helpful to preview these classes in the Classes book of the Origin C Language Reference or in the above header files located in the \OriginC\system subfolder of Origin. If you are not familiar with debugging Origin C files in Code Builder you may also find it helpful to review the Debug Tutorial before proceeding (select the Help:Tutorials menu item in Origin or Code Builder).


Accessing Worksheet Related Objects

  1. Launch a new session of Origin or click the New Project button [image] on the Standard toolbar in Origin.

  2. Click the Code Builder button [image] on the Standard toolbar to open Code Builder.

  3. Select the File:New Workspace menu item in Code Builder to open a new empty Code Builder workspace.

  4. Click the Open toolbar button [image] in Code Builder. Browse to and open the source file AccessWorksheetObjectsTutorial.c in the \Tutorial subfolder of Origin.

  5. Activate the AccessWorksheetObjectsTutorial.c window in the Code Builder workspace and press the CTRL+W keyboard keys to add the file to the current Code Builder workspace.

  6. Click the Code Builder Rebuild All toolbar button [image] to compile, load, and link the file AccessWorksheetObjectsTutorial.c.

  7. Select the Code Builder View menu as needed to open the LabTalk Console window (Command & Results) and the Local Variables window.

  8. Make sure the Debug toolbar is visible by selecting the Code Builder Tools:Customize menu item and checking the Debug checkbox on the Toolbars tab.

  9. Activate the AccessWorksheetObjectsTutorial.c window in the Code Builder workspace. Near the top of the file locate and click on the line

PageBase pb;

positioning the cursor anywhere on the line.

  10. Select the Code Builder Debug:Toggle Breakpoints menu item (alternatively press the F9 function key or click the left most Toggle Breakpoint button [image] on the Debug toolbar).

A brown circle is displayed in the gray margin to the left of the above line indicating that a Debug breakpoint has been set for that line.

  11. Activate the LabTalk Console (Command & Results window) in Code Builder and enter

AccessWorksheetObjectsTutorial

to execute the function having that name.

  12. Step through each statement in the AccessWorksheetObjectsTutorial function one line at a time by repeatedly pressing the Step Into button [image] on the Debug toolbar stopping to read the comments for each statement (as needed to understand the code). Also, periodically stop along the way (as needed) to re-size and re-position the Local Variables window and to view the current runtime value of each variable as it gets set.

In the above function, the line pb = Project.Pages(); gets the active PageBase object using the Pages collection of the Project class. The function then gets the name and checks the page type of the PageBase object pb to make sure it is a WorksheetPage. Next, the statement wp = (WorksheetPage) pb; casts the PageBase object to a WorksheetPage object. The line wks = (Worksheet) wp.Layers(0); uses the Layers collection in the WorksheetPage to get the first layer in the page by index (WorksheetPage layers are called a Worksheets). Currently, WorksheetPages can only have one layer (Origin C uses 0 based offsets so layer 0 is the first layer). The statement col = wks.Columns(iColNum); uses the Columns collection in the Worksheet (Layer) object to attach to the second column in the worksheet by index (column 1 is the second column) and the statement col = wks.Columns("A"); attaches to the first column of the worksheet by name. Finally, the line ds.Attach(wks, iColNum); uses the Worksheet object wks and the column number of column A to get the Dataset Data1_A whose size is then set to 10 elements and whose values are all set to 100.

Note that there are often many different ways to accomplish the same thing in Origin C (and coincidentally in Origin). The function above is not necessarily intended to demonstrate the best or even the most efficient way to attach to internal Origin objects. Rather, the intention of this example function is to show a number of different instances of locating and attaching to internal Origin objects. For example, the line of code and nearly all the code above the statement wks = (Worksheet) wp.Layers(0); could have been replaced with the single line wks = Project.GetActiveLayer(); with identical results. If the active child window in Origin happens to not be a worksheet then attaching the Worksheet object wks to the layer returned by the GetActiveLayer() method would fail and the object wks would be invalid. If the active window in Origin is a worksheet then attaching the wks object will succeed and the function will proceed as before.

Of particular importance is the repeated use of the IsValid method. When attaching Origin C objects to internal Origin objects you must always test the validity of the Origin C object after attaching but before accessing any of its properties or methods. When a method or property of an improperly attached object (e.g an invalid object) is accessed an Origin C run time error is generated and the function will abruptly terminate. It is generally preferable to test validity and if need be return with an error code or an error message rather than to abruptly terminate from a program. The IsValid method is inherited by all Origin C classes used to attach to internal Origin objects and returns true if the calling object is valid making it the obvious choice for testing validity.


Accessing Graph Related Objects

  1. Click the Open button [image] on the Standard toolbar in Origin. Browse to and open the Origin project file AccessGraphObjectsTutorial.opj in the \Tutorial subfolder of Origin.

  2. Click the Code Builder button [image] on the Standard toolbar to open (or activate) Code Builder.

  3. Select the File:New Workspace menu item in Code Builder to open a new empty Code Builder workspace.

  4. Click the Open toolbar button [image] in Code Builder. Browse to and open the source file AccessGraphObjectsTutorial.c in the \Tutorial subfolder of Origin.

  5. Activate the AccessGraphObjectsTutorial.c window in the Code Builder workspace and press the CTRL+W keyboard keys to add the file to the current Code Builder workspace.

  6. Click the Code Builder Rebuild All toolbar button [image] to compile, load, and link the file AccessGraphObjectsTutorial.c.

  7. Select the Code Builder View menu as needed to open the LabTalk Console window (Command & Results) and the Local Variables window.

  8. Make sure the Debug toolbar is visible by selecting the Code Builder Tools:Customize menu item and checking the Debug checkbox on the Toolbars tab.

  9. Activate the AccessGraphObjectsTutorial.c window in the Code Builder workspace. Near the top of the file locate and click on the line

GraphPage gp;

positioning the cursor anywhere on the line.

  10. Select the Code Builder Debug:Toggle Breakpoints menu item (alternatively press the F9 function key or click the left most Toggle Breakpoint button [image] on the Debug toolbar).

A brown circle is displayed in the gray margin to the left of the above line indicating that a Debug breakpoint has been set for that line.

  11. Activate the LabTalk Console (Command & Results window) in Code Builder and enter

AccessGraphObjectsTutorial

to execute the function having that name.

  12. Step through each statement in the AccessGraphObjectsTutorial function one line at a time by repeatedly pressing the Step Into button [image] on the Debug toolbar stopping to read the comments for each statement (as needed to understand code). Also, periodically stop along the way (as needed) to re-size and re-position the Local Variables window and to view the current runtime value of each variable as it gets set.

In the function AccessGraphObjectsTutorial, the line fld = Project.RootFolder; uses the RootFolder property of the Project class to get the Project Explorer root folder. Next, the statement fld = fld.Subfolders("Level 2B"); uses the Subfolders collection in the Folder class to get subfolder "Level 2B" reassigning the returned (sub)folder object to the variable fld (which previously held the root folder). The line gp = (GraphPage) fld.Pages("Graph2B"); uses the Pages collection in the Folder class to get the child window named "Graph2B" and attach it to the GraphPage object gp. The Pages collection contains a collection of all PageBase objects in the calling folder. The PageBase object returned is cast to a GraphPage object. The statement gl = gp.Layers(0); uses the Layers collection in the GraphPage class to get the layer 1 GraphLayer. The line foreach( DataPlot dp in gl.DataPlots ) uses the DataPlots collection in the GraphLayer class to loop once for each data plot in the graph layer. The statement dp.SetColor( iColor, TRUE ); uses the SetColor method of the DataPlot class to set the color of each data plot in the layer.

Again, please note that the function AccessGraphObjectsTutorial is not necessarily intended to demonstrate the best or even the most efficient way to attach to internal Origin objects. Rather, the intention of this example function is to show a number of different instances of locating and attaching to internal Origin objects. Also note the repeated use of the IsValid method. As described above, when attaching Origin C objects to internal Origin objects you must always test the validity of the Origin C object after attaching but before accessing any of its properties or methods.


Collections

The Origin C Collection class is a useful device for grouping together a collection of objects of one kind. A Collection is itself an Origin C object having a data member akin to an array of pointers to the objects it contains. A Collection object facilitates easy access (by index and name) to the objects in the collection. The following sections discuss the Collection class, list many of the collections contained in Origin C objects, and show by example how to use collections in an Origin C program. All example code used in these sections is in the sample file Collection.c and can be found in the \Samples\Programming\Origin C Files subfolder of Origin.


The Collection Class

// Lookup Origin windows in Pages collection of Project object

void PagesCollectionEx()

{

PageBase pb0, pbData, pbActive;

pb0 = Project.Pages(0); // Get the first page and output name

if( pb0.IsValid() )

printf("The first page in the project file is %s.\n", pb0.GetName());

pbData = Project.Pages("Data2"); // Get the page named "Data2" and output name

if( pbData.IsValid() )

printf("The Data2 page is in fact named %s.\n", pbData.GetName());

pbActive = Project.Pages(); // Get the active page and output name

if( pbActive.IsValid() )

printf("The active page in the project file is %s.\n", pbActive.GetName());

// Output the number of pages in the project

printf("The project %s contains %d pages.\n", Project.GetName(), Project.Pages.Count());

}

The Collection Class

The definition of the Collection class can be found in the Origin C system header file Collection.h. The Collection class provides a template for collections of various internal Origin objects such as Pages (the collection of all PageBase objects or child windows in an Origin project file). The Collection class has an implicit templatized type _TemplType which is the type of each element in the collection. For example, the templatized type of the Pages collection in the Project class (Collection<PageBase> Pages;) is PageBase. Each collection usually has a parent class which is the class whose data member is the collection. For example, the Pages collection is a data member of the Project class. The member functions of the Collection class are the same regardless of its template type and include a constructor, two methods that return a single item in the collection referenced either by name or index, and a method that returns the number of items in the collection. The only data member of the Collection class is the collection of pointers to the objects in the collection.

To run the example function PagesCollectionEx follow the steps below.

  1. Add a number of worksheet and graph windows including a worksheet named “Data2” to the Origin workspace.

  2. Click the Code Builder button [image] on Origin’s Standard toolbar to open Code Builder.

  3. Select the Code Builder File:Open menu item. Browse to and open the source file Collection.c in the \Samples\Programming\Origin C Files subfolder of Origin.

  4. Activate the Collection.c window in Code Builder and press the CTRL+W keys to add the file to the Code Builder workspace.

  5. Click the Rebuild All button [image] on Code Builder’s Standard toolbar to build all files in the workspace.

  6. Select the Origin Window:Script Window menu item to open the Script window, type the command PagesCollectionEx(), and press ENTER.

When the ENTER key is pressed the PagesCollectionEx function is executed. The Pages collection in the Project object is used to lookup and attach to several different Origin PageBase objects (child windows). The name of each Origin window is output in the Script window. The example function PagesCollectionEx is contained in the Collection.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Built-in Origin C Collections

Collection Name | Parent Class | Contains Objects of Type
Children | TreeNode | TreeNode
Columns | Worksheet | Column
Data Plots | GraphLayer | Data Plot
DatasetNames | Project | String (Names of Loose data sets)
GraphObjects | Layer | GraphObject
GraphPages | Project | GraphPage
Layers | GraphPage | GraphLayer
Layers | Page | Layer
LayoutPages | Project | LayoutPage
LooseDatasetNames | Project | string (Names of Loose data sets)
MatrixObjects | MatrixLayer | MatrixObject
MatrixPages | Project | MatrixPage
Notes | Project | Note
Objects | Selection | OriginObject
Pages | Folder | PageBase
Pages | Project | PageBase
SubFolders | Folder | Folder
StyleHolders | GraphLayer | StyleHolder
WorksheetPages | Project | WorksheetPage

Built-in Origin C Collections

Many Origin C classes contain (as data members) collections of other Origin C objects. For example, as shown in the PagesCollectionEx function in the previous section, the Project object (a built-in instance of the Project class) contains a collection of all Origin PageBase objects (child windows) in the open project file named Pages. The table below lists the names of all built-in Origin C collections (collections contained by built-in Origin C classes), the containing or parent class, and the type of object contained in the collection. See the example functions in the sections that follow for an illustration of how to use the Origin C built-in collections.

View Built-in Origin C collections


Looping through Collections using the foreach Loop

// Count the number of GraphLayers in an Origin project file

void CountGraphLayersInProjectEx()

{

// Initialize count

int nCount = 0;

// Use GraphPages collection in Project object to loop

// on all GraphPage objects in project file

foreach( GraphPage gp in Project.GraphPages )

{

// Use Layers collection in GraphPage object to loop

// on all layers in each Graph page

foreach( GraphLayer gl in gp.Layers )

{

nCount++; // Count layer

}

}

printf("Total number of GraphLayers = %d\n",nCount);

}

// Walk a Tree outputting the string values of each TreeNode

void WalkATreeEx()

{

Tree trRoot; // Declare and populate nodes of tree

trRoot.Fruits.SubNode1.strVal = "Apples";

trRoot.Fruits.SubNode2.strVal = "Pears";

trRoot.Fruits.SubNode3.strVal = "Peaches";

trRoot.Nuts.SubNode1.strVal = "Walnuts";

trRoot.Nuts.SubNode2.strVal = "Cashews";

trRoot.Nuts.SubNode3.strVal = "Peanuts";

trRoot.Vegetables.SubNode1.strVal = "Carrots";

trRoot.Vegetables.SubNode2.strVal = "Peas";

trRoot.Vegetables.SubNode3.strVal = "Potatoes";

// Declare an unattached Collection of TreeNode objects and attach

// TreeNode Collection to collection of child nodes named Children

Collection<TreeNode> tncFoods; // Declare

tncFoods = trRoot.Children; // Attach

// Loop on all TreeNodes in TreeNode Collection tncFoods

foreach( TreeNode tnParent in tncFoods )

{

string strParentName = tnParent.tagName;

// Loop on all (sub)TreeNodes in TreeNode Collection tnParent.Children

foreach( TreeNode tnSubNode in tnParent.Children )

{

printf("trRoot.%s.%s.strVal = %s\n", strParentName, tnSubNode.tagName, tnSubNode.strVal);

}

}

}

Looping through Collections using the foreach Loop

All example code for this page is contained in the Collection.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.

foreach Loop Example 1

Programmers may find it useful to loop through a collection processing each object in the collection as the loop proceeds. The following example function uses the foreach command to loop through and count all GraphLayers in all GraphPages in the open Origin project file. The total count of GraphLayers is then output.

To run the example function CountGraphLayersInProjectEx continue from step 6 in The Collection Class section.

  7. Add a number of graph windows including a few graph windows with multiple layers to the Origin workspace.

  8. Type the command CountGraphLayersInProjectEx() in the Origin Script window and press ENTER.

When the ENTER key is pressed the CountGraphLayersInProjectEx function shown below is executed. The outer foreach loop loops on all GraphPage objects in the open project file and the inner foreach loop loops on and counts all GraphLayer objects in each GraphPage. The total number of GraphLayers is then output in the Script window.

foreach Loop Example 2

The following example uses the foreach command to loop through all the nodes and subnodes of an Origin C Tree object. The TreeNode collection tncFoods is first declared and then attached to the internal TreeNode collection trRoot.Children. The second TreeNode collection tnParent.Children is used directly. The complete subnode path and string value of each TreeNode is output.

To run the example function WalkATreeEx continue from step 8 in the example above.

  9. Type the command WalkATreeEx() in the Origin Script window and press the ENTER key.

When the ENTER key is pressed the WalkATreeEx function shown below is executed. The outer foreach loop loops on all TreeNode objects in the TreeNode collection tncFoods (a reference for trRoot.Children) and the inner foreach loop loops on and outputs all (sub) TreeNode objects in the TreeNode collection tnParent.Children. The path and string value of each subnode is output in the Script window.


Trees and XML

The Origin C Tree, TreeNode, and PropertyNode classes implement a tree based data structure. Each Origin C Tree object has a root node which may contain either a set of properties or a collection of child nodes. Each child node, can, in turn, have its own set of properties or its own collection of child nodes (and so on). The nodes of an Origin C Tree provide an efficient means of storing and accessing data in an hierarchical structure. The following sections discuss how to set and get the properties of a tree node, how to find and access the nodes of a tree, how to add and remove nodes of a tree, how to clone (copy) and create references to tree nodes, how to save a tree to and load a tree from an XML file, and how to improve the scalability of an Origin C function by passing input and output arguments as nodes in a tree. All example code used in these sections is in the sample file TreeEx.c and can be found in the \Samples\Programming\Origin C Files subfolder of Origin. For more information on Origin C Trees see the Tree, TreeNode, and PropertyNode classes in the Origin C Language Reference.


Setting and Getting the Properties of a TreeNode

// Demonstrate the different values of a TreeNode

void ValuesOfATreeNodeEx()

{

Tree tr;

// Set common node properties

tr.mynode.ID = 200;

tr.mynode.Show = 1;

tr.mynode.Enable = 1;

string strLabel; // tagName is read only

strLabel.Format("\ntree_dump of Tree having TreeNode named %s", tr.mynode.tagName);

// Set node properties

tr.mynode.nVal = 6;

tree_dump(tr, strLabel);

tr.mynode.dVal = 3.5;

tree_dump(tr, strLabel);

tr.mynode.strVal = "This is a string value";

tree_dump(tr, strLabel);

tr.mynode.Text = "-8.9";

tree_dump(tr, strLabel);

// Get and print all node properties

int iID = tr.mynode.ID;

int iShow = tr.mynode.Show;

int iEnable = tr.mynode.Enable;

int nVal = tr.mynode.nVal;

double dVal = tr.mynode.dVal;

string strVal = tr.mynode.strVal;

string strText = tr.mynode.Text;

printf("\nID = %d, Show = %d, Enable = %d, nVal = %d, dVal = %g, strVal = %s, Text = %s",

iID, iShow, iEnable, nVal, dVal, strVal, strText);

}

Setting and Getting the Properties of a TreeNode

Nodes of an Origin C Tree object may contain either a set of properties or a collection of child nodes. The set of available tree node properties includes an integer value nVal, a double value dVal, and two string values strVal and Text. When you set one of these tree node properties all others update accordingly each reflecting the most recently set value cast to its property type. For example, if you set dVal = -8.9, then nVal = -8, dVal = -8.9, strVal = “-8.9”, and Text = “-8.9.” In addition to the properties already mentioned, all tree nodes (even those with child nodes) have a set of common properties including tagName (read only), ID, Enable, and Show. tagName is the name of the node, ID is the node ID, and Enable and Show are binary properties that can be used as desired by the application (for example, the GetN dialog uses them to determine whether or not a control for the node is to be enabled or shown in the GetN dialog box).

To refer to an entire tree the notation TreeName is used, to refer to a tree node the notation TreeName.NodeName...NodeName is used, and to refer to the property of a tree node the notation TreeName.NodeName…NodeName.PropertyName is used. The depth and path of the referenced node in the tree determines how many and what NodeNames are required to uniquely identify a specific node in the tree. Note the use of dots (periods) to separate the tree name, node name(s), and property name. To set or get the value of a tree node property simply use an assignment statement like the ones below.

MyTree.MyNode.Property = Value; // Set tree node property, or

Value = MyTree.MyNode.Property; // Get tree node property

The following example shows how to set and get the properties of a tree node. See also the SetAttribute and GetAttribute methods of the TreeNode class. The example code for this page is contained in the TreeEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Finding and Accessing Nodes of a Tree

// Demonstrate how to find and access nodes of a tree

void AccessNodesOfATreeEx()

{

Tree tr; // Tree declaration and definition

tr.Edge.Style.strVal = "Solid Line";

tr.Edge.Color.strVal = "Red";

tr.Edge.Thickness.strVal = "5";

// Get child node by name

TreeNode tn;

printf("\nGet node by name...\n");

tn = tr.Edge.GetNode("Color");

printf("tr.Edge.%s.strVal = %s\n", tn.tagName, tn.strVal);

// Foreach loop through all child nodes using Children collection

printf("\nForeach loop through child nodes...\n");

foreach(TreeNode tnChild in tr.Edge.Children ) // Foreach child in node...

{

printf("tr.Edge.%s.strVal = %s\n", tnChild.tagName, tnChild.strVal);

}

// Loop forward through nodes

printf("Iterate forward through nodes...\n");

tn = tr.Edge.FirstNode; // Get first node

while( tn.IsValid() ) // While nodes exist...

{

printf("tr.Edge.%s.strVal = %s\n", tn.tagName, tn.strVal);

tn = tn.NextNode; // Get next node

}

// Loop backward through nodes

printf("\nIterate backward through nodes...\n");

tn = tr.Edge.LastNode; // Get last node

while( tn.IsValid() ) // While nodes exist...

{

printf("tr.Edge.%s.strVal = %s\n", tn.tagName, tn.strVal);

tn = tn.PrevNode; // Get previous node

}

// Get parent node

printf("\nGet parent of node and number of child nodes...\n");

tn = tr.Edge.Color.Parent();

printf("tr.%s has %d child nodes\n", tn.tagName, tn.GetNodeCount());

}

Finding and Accessing Nodes of a Tree

Nodes of an Origin C Tree object may be accessed randomly by name, sequentially by looping, and relatively by juxtaposition. To access nodes of a tree by name use the GetNode method of the TreeNode class. To access nodes of a tree by looping use the control structure foreach on the Children collection of the TreeNode class (see the foreach and Collections sections for more information on the foreach command and on Collections). To access nodes of a tree by relative position use the FirstNode, NextNode, PrevNode, and LastNode properties or the Parent method of the TreeNode class. The following example shows each of these methods for accessing tree nodes. The example code for this page is contained in the TreeEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Adding and Removing Nodes of a Tree

// Add and remove nodes of a tree

void AddAndRemoveNodesOfATreeEx()

{

Tree tr;

// Add nodes by assigning values...

tr.Edge.Style.strVal = "Solid Line";

tr.Edge.Color.strVal = "Red";

tr.Edge.Thickness.strVal = "5";

tree_dump(tr, "\nTree with Edge nodes");

// Exlicitly add nodes...

tr.AddNode("Fill", 200);

tr.Fill.AddTextNode("Hashing", "Style", 201);

tr.Fill.AddNumericNode(3.3, "Density", 202);

tr.Fill.AddTextNode("Pink", "Color", 203);

tree_dump(tr, "\nTree with Fill nodes added");

// Clone tree to make backup copy...

Tree trCopy;

trCopy = tr.Clone();

// Remove specified nodes...

tr.Fill.Style.Remove(); // Remove Style node by self reference

tr.Fill.RemoveChild(202); // Remove Density node by ID

tr.Fill.RemoveChild("Color"); // Remove Color node by name

tree_dump(tr, "\nTree with Fill child nodes removed");

// Replace childless Fill node by copy of Fill node...

tr.Fill.Replace(trCopy.Fill);

tree_dump(tr, "\nTree with Fill child nodes replaced from copy");

// Remove entire Fill node...

tr.RemoveChild(tr.Fill); // Remove Fill node by node

tree_dump(tr, "\nTree with Fill node removed");

// Reset entire tree removing all nodes...

tr.Reset();

tree_dump(tr, "\nReset tree will no nodes");

}

Adding and Removing Nodes of a Tree

Nodes of an Origin C Tree object may be added, removed, and replaced using a number of different methods. The easiest way to add a node is simply to make an assignment statement. Assignment statements involving nodes of a tree both declare and initialize the node in one step. However, node names are often not known at compile time and can also be dynamically added at execution time using the AddNode, AddTextNode, or AddNumericNode methods of the TreeNode class. To delete or remove nodes of a tree use the Remove, RemoveChild, RemoveChildrenWithPrefix, RemoveAttribute, or Reset methods. To replace one node of a tree with another use the Replace method. Replacement may involve one level or optionally all levels beneath the replacing node. The following example shows several different examples of adding, removing, and replacing nodes in a tree. The example code for this page is contained in the TreeEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Cloning (Copying) a Tree and References to Trees

// Clone (copy) a tree versus reference to a tree

void TreeNodeCloneVsReferenceEx()

{

Tree tr; // Tree declaration and definition

tr.Students.nVal = 453;

tr.Teachers.nVal = 23;

tr.Administrators.nVal = 5;

tree_dump(tr, "\nOriginal tree");

TreeNode tnClone, tnReference;

tnReference = tr; // Assign address of tr

tnClone = tr.Clone(); // Assign clone (copy) of tree

tr.Students.nVal = 508; // Modify original tree

// Output original, referenced, and cloned (copied) trees

tree_dump(tr, "\nOriginal tree (modified)");

tree_dump(tnReference, "\nReference to original tree (also modified)");

tree_dump(tnClone, "\nClone (copy) of tree (not modified)");

}

Cloning (Copying) a Tree and References to Trees

When a tree node is assigned to another tree node (not tree node property) using only the equals operator “=” the value assigned to the tree node on the left side of the equation is, in essence, the address of the tree node on the right side. Tree node assignment involves references to tree node objects and not tree node objects themselves. The nodes of one tree are not copied into the nodes of the other tree. Rather, the tree nodes point to the same area in memory. To make a copy of a tree node use the Clone method of the TreeNode class along with the equals operator (see also the Replace method discussed in the section above). The Clone method allocates new memory and then fills it with (copies into it) the node structure and properties of the calling TreeNode object. The following example nicely demonstrates this difference. Note that when a property of the original tree node tr.Students.nVal is modified the corresponding property of the reference tree node trReference is also changed but the corresponding property of the cloned node trClone is not. This happens because tr and trReference refer to the same area in memory and trClone refers to a different area.

The example code for this page is contained in the TreeEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Saving Trees to and Loading Trees from XML Files

// Save a tree to an XML file and reload tree from XML file

void SaveToAndLoadFromXMLEx()

{

Tree tr; // Tree declaration and definition

tr.IntNode.ID = 200;

tr.IntNode.Show = 1;

tr.IntNode.Enable = 1;

tr.IntNode.nVal = 6;

tr.StrNode.ID = 201;

tr.StrNode.strVal = "This is a string value";

tr.DoubleNode.ID = 202;

tr.DoubleNode.dVal = -8.9;

tree_dump(tr, "\nOriginal tree");

// Print tree as XML string

printf("\nXML file as string\n%s\n",tr.XML);

// Save tree

tr.Save(GetAppPath() + "Samples\\Programming\\Origin C Files\\MyTree.XML");

// Load tree using Tree constructor

string str = GetAppPath() + "Samples\\Programming\\Origin C Files\\MyTree.XML";

Tree trConstructor(str);

tree_dump(trConstructor, "\nCopy of Original tree loaded using Tree constructor");

// Load tree using Load constructor

Tree trLoad;

trLoad.Load(GetAppPath() + "Samples\\Programming\\Origin C Files\\MyTree.XML");

tree_dump(trLoad, "\nCopy of Original tree loaded using Load method");

}

Saving Trees to and Loading Trees from XML Files

Origin C Trees are closely allied with the XML file format. So much so, in fact, that the TreeNode class contains a read only string property (named XML appropriately enough) which represents an XML version of the tree node itself. In addition, objects of type Tree (the Tree class is derived from the TreeNode class) can easily be saved to and loaded from an XML file. To save an Origin C Tree to an XML file use the Save method of the Tree class and to load an Origin C Tree from an XML file use the Load method of the Tree class. A Tree constructor that loads from an XML file is also available. Please see the following example for usage. The example code for this page is contained in the TreeEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Passing TreeNodes as Arguments to Scalable Functions

// Demonstrate scalability of functions when passing tree as argument

void ScalableFunctionEx()

{

Tree tr; // Tree declaration and definition

tr.Input.Term1.dVal = 3;

tr.Input.Term2.dVal = 4;

// tr.Input.Term3.dVal = 6; // ** 3 ** Uncomment to scale calling function

// Compute sum

OperateOnTreeArg(tr);

// ** 2 ** Uncomment code below to modify calling function to compute mean

//tr.Option.nVal = 1;

//OperateOnTreeArg(tr);

tree_dump(tr, "Results:");

}

// Scalable helper function accepting tree as argument

static bool OperateOnTreeArg(TreeNode& trArg)

{

trArg.Result.Reset();

trArg.Result.Sum.dVal = 0;

foreach(TreeNode tn in trArg.Input.Children)

trArg.Result.Sum.dVal += tn.dVal;

trArg.Result.NumTerms.dVal = (double) trArg.Input.GetNodeCount();

// ** 1 ** Uncomment code below to modify called function to compute mean

//if( trArg.Option.IsValid() )

//if( trArg.Option.nVal == 1 )

//trArg.Result.Mean.dVal = trArg.Result.Sum.dVal / trArg.Result.NumTerms.dVal;

return true;

}

Passing TreeNodes as Arguments to Scalable Functions

A welcome side effect of trees is that when passed as arguments to functions they can increase the scalability of both the calling and the called function. In many cases a cleverly designed general purpose helper function that accepts a reference to an Origin C Tree as an argument can easily be modified without affecting its prototype. More importantly, many instances of pre-existing code that call the helper function may not have to be modified when the helper function is modified. Functions that call the helper function can also be scaled if the helper function is written in such a way that allows the tree passed in as an argument to have a variable number of input nodes needing to be processed.

For example, the computation performed by a helper function can be modified causing a more or less complex calculation based on the presence or absence of an optional subnode in the tree argument. Calling functions can take advantage of the modified computation, or not, depending on the presence or absence of a passed optional subnode. Results passed back as nodes in the tree can also be added and removed as desired. All of these changes can be accomplished without affecting either the prototype or the invocation of the called function. Finally, the number of items processed can be altered by varying the number of input child nodes in the tree argument. The following example code can be modified (by uncommenting existing code) a number of different ways each demonstrating a different aspect of scalability. The example code for this page is contained in the TreeEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.

First, build and run the example functions ScalableFunctionEx and OperateOnTreeArg without modifications to compute the sum of two terms. Then, uncomment the code below the // ** 1 ** comment, rebuild, and re-run the example. Note that the helper function was modified without effecting its prototype or its invocation in the old version of the calling function…the sum of two terms is still computed because the Option node does not exist in the passed tree argument. Next, uncomment the code below the // ** 2 ** comment, rebuild, and re-run the example again. Note that the calling function was easily modified so that the example now computes both the sum and mean of two terms. Now uncomment the code left of the // ** 3 ** comment (to add another input node), rebuild, and re-run the example. This time the calling function was modified to compute the sum and mean of three terms. Finally, comment out the code below the // ** 1 ** comment, rebuild, and re-run the example one last time. Note that the helper function was modified again without effecting its prototype, its invocation, or the now modified version of the calling function. Now the sum but not the mean of three terms is computed because the Option node exists in the tree argument (and its property value is 1) but the helper function now ignores it.


Accessing Plot Properties with Trees

Many plot properties of 2D and 3D graphs can be accessed (manipulated) in Origin C. An Origin C Tree object is used to acquire, modify, and then re-assign the internal (internally stored in Origin) plot properties. The Origin C Tree object acquires the plot properties by assigning the data plot’s properties node to the Tree object. The nodes of the Origin C Tree object are then manipulated as desired. Once set, the Origin C Tree object is then re-assigned back to the data plot’s properties node resulting in the update of the internal Origin plot properties. The following examples demonstrate this technique for both a 2D (Line + Symbol) and a 3D (Contour) plot. All sample code is contained in the source file AccessPlotPropertiesEx.c located in the Code Builder Project folder of the Origin project file AccessPlotPropertiesEx.opj. The project file AccessPlotPropertiesEx.opj also contains sample data and can be found in the \Samples\Programming subfolder of Origin.

The most reliable method to identify the plot properties available to be modified is to attach an Origin C Tree object to the root node of the data plot’s properties node. The nodes of the Origin C Tree can then be observed in the Code Builder Local Variables window while in Debug mode. The examples below demonstrate this procedure in greater detail. If you are not familiar with debugging Origin C files in Code Builder you may find it helpful to review the Debug Tutorial before proceeding (select the Help:Tutorial menu item in Origin or in Code Builder).

An easier method to get an approximation of the plot properties available to be modified is to inspect them in Origin using the Save Format as Theme dialog box. To open the Save Format as Theme dialog box, right-click on the data plot in Origin and select the Save Format as Theme… menu item from the short cut menu. Then, click the push button with the yellow pencil and blue down arrows [image]. A list control containing a tree structure of folders and properties and their values is displayed. Many of the plot properties in the list control are available to be modified.


Accessing 2D Plot Properties

To access the plot properties of a two dimensional data plot you must first assign the data plot's internal properties node to an Origin C Tree object. The internal properties node of a two dimensional data plot is accessed by attaching an Origin C DataPlot object to the data plot in Origin and then assigning the Curve property of the Origin C DataPlot object to an Origin C Tree. The example code used in the following steps demonstrates this procedure.

  1. In Origin click the Open button [image] on the Standard toolbar.

  2. Browse to and open the sample project file AccessPlotPropertiesEx.opj in the \Samples\Programming\Active Origin Projects subfolder of Origin.

  3. In Origin click the Code Builder button [image] on the Standard toolbar to open Code Builder. Make sure the Code Builder Workspace and Local Variables windows are open by checking their menu items on the Code Builder View menu.

  4. Click the [+] symbol next to the Project folder in the Code Builder Workspace window to expand the file list and then double-click on the source file AccessPlotPropertiesEx.c to open it in Code Builder.

  5. Locate the function named SetLineSymbolPlotProperties in the file AccessPlotPropertiesEx.c, click anywhere on the line

Tree tr;

to position the cursor, and then press the F9 function key to place a break point on the line.

  6. Open the Script window in Origin. Execute the function PlotWksColumnsAsLineSymbol by typing PlotWksColumnsAsLineSymbol("Data1") and pressing ENTER in the Script window. The columns in the Data1 worksheet are plotted as a Line + Symbol plot with 9 point black squares connected by a black line of width 0.5 points.

  7. Be sure the break point is set (as described above in step 5) and then execute the function SetLineSymbolPlotProperties by typing SetLineSymbolPlotProperties("Graph1") and pressing ENTER in the Script window. The function executes but stops at the line where the break point was set.

  8. Step through each remaining statement in the SetLineSymbolPlotProperties function one line at a time by repeatedly pressing the Step Into button [image] on the Code Builder Debug toolbar. As needed to understand the code, stop along the way to read the comments for each statement and to view the current runtime value of each tree node in the Local Variables window as it gets set. To see the node values of the Origin C Tree object tr click the [+] symbol next to its nodes to expand the view.

After the debug session above runs to completion the Line + Symbol plot is modified and now consists of 15 point red circles connected by a red line of width 3 points.


Accessing 3D Plot Properties

To access the plot properties of a three dimensional data plot you must first assign the data plot's internal properties node to an Origin C Tree object. The internal properties node of a three dimensional data plot is accessed by attaching an Origin C DataPlot object to the data plot in Origin and then assigning the Surface property of the Origin C DataPlot object to an Origin C Tree. The example code used in the following steps demonstrates this procedure.

  9. Follow steps 1 through 4 in the previous section if not continuing from step 8 in the previous section.

  10. Locate the function named SetContourColorMapProperties in the file AccessPlotPropertiesEx.c, click anywhere on the line

Tree tr;

to position the cursor, and then press the F9 function key to place a break point on the line.

  11. If need be open the Script window in Origin. Execute the function PlotMatrixAsContour by typing PlotMatrixAsContour("Matrix1") and pressing ENTER in the Script window. The matrix Matrix1 is plotted as a Color Filled Contour plot with 8 contour levels from –1 to 1.

  12. Be sure the break point is set (as described above in step 10) and then execute the function SetContourColorMapProperties by typing SetContourColorMapProperties("Graph2") and pressing ENTER in the Script window. The function executes but stops at the line where the break point was set.

  13. Step through each remaining statement in the SetContourColorMapProperties function one line at a time by repeatedly pressing the Step Into button [image] on the Code Builder Debug toolbar. As needed to understand the code, stop along the way to read the comments for each statement and to view the current runtime value of each tree node in the Local Variables window as it gets set. To see the node values of the Origin C Tree object tr click the [+] symbol next to its nodes to expand the view.

After the debug session above runs to completion the Contour plot is modified and now consists of 9 contour levels from –0.9 to 0.9.


Calling Global Functions

Origin C includes a large number of global functions grouped together in related categories. Global functions can be called at any time as long as the header file containing the function's prototype is included in the source file. Including the system header file Origin.h includes most global function prototypes. Origin C global functions include functions implemented internally in Origin, NAG functions, and some functions implemented in Origin C itself. For a complete listing of Origin C Global Functions see the Origin C Language Reference.

The example function below CallGlobalFuncsEx calls two global functions. The global function Data_sum computes basic statistics on an Origin C Dataset object and the global function printf outputs some results. Including the system header file Origin.h includes the prototypes for both global functions. The example code can also be found in the sample file GlobalFunctionsEx.C in the \Samples\Programming\Origin C Files subfolder of Origin.

Before executing the function click the New Project button [image] on the Standard toolbar in Origin and enter some numeric data in the worksheet column Data1_A.

#include <Origin.h>

void CallGlobalFuncsEx()

{

Dataset dsDataIn("Data1_A");

BasicStats bsStat;

BOOL bErr = Data_sum(&dsDataIn, &bsStat);

printf("Min = %f\nMax = %f\nMean = %f\nSD = %f",

bsStat.min, bsStat.max, bsStat.mean, bsStat.sd);

}


Accessing NAG Functions

 | Miscellaneous
c06 | Fourier Transforms
e01 | Interpolation
e02 | Curve and Surface Fitting
F | Linear Algebra
f06 | Linear Algebra Support Functions
g01 | Simple Calculations on Statistical Data
g02 | Correlation and Regression Analysis
g03 | Multivariate Methods
g04 | Analysis of Variance
g08 | Nonparametric Statistics
g11 | Contingency Table Analysis
g12 | Survival Analysis
s | Approximations of Special Functions

Accessing NAG Functions

Origin includes a number of the NAG C function libraries. Functions in the NAG C libraries can easily be accessed in your Origin C functions. To access any NAG function in any NAG category simply include the Origin C system header file Origin.h in your source file. Now that all Origin C NAG header files are included in the pre-compiled system header file Origin.h it is recommended to include Origin.h when accessing NAG functions. The NAG libraries included with Origin are listed in the following table.


Getting Help for NAG Functions

A number of resources exist to help you get started using NAG functions in your Origin C functions. These resources include:

  • Origin C Language Reference Help File.

Reference information for all NAG functions is provided in the Global Functions book of the Origin C Language Reference. Functions are grouped in chapters.

  • Programming Tutorial - Calling NAG Functions From Origin C.

Origin includes a number of tutorials several of which are programming tutorials. To access the tutorial Calling NAG Functions From Origin C select the Help:Tutorials menu item in Origin or in Code Builder. In the Tutorials help file select the Programming Tutorials book and then select the Calling NAG Functions From Origin C tutorial. The NAG tutorial includes a sample Origin project file with worksheet data and a sample Origin C source file. An Origin C function in the source file calls a NAG function to perform a multiple linear regression.

  • Origin Sample Project Files.

Origin includes a number of sample project files containing Origin C functions that call NAG functions. Each sample project file contains sample data, sample Origin C functions, and one or more label buttons to execute the functions. To see the Origin C functions open the project file in Origin, open Code Builder, and then look in the Project folder of the Code Builder Workspace window. The NAG sample project files include NAG 2D Gridding.OPJ, NAG FFT Convolution.OPJ, NAG2DFFT.OPJ, NAG STFT.OPJ, NAG FFT Lowpass.OPJ, and NAGSummaryStats.OPJ and are located in the \Samples\Programming subfolder of Origin.

  • NAG PDF Files in the Origin Subfolder \NAG PDFs.

When you install Origin, you are given the option to install NAG supplied PDF files which thoroughly document all NAG functions included with Origin. If you clicked Yes to install these files, a \NAG PDFs folder is created with a subfolder for each library. If you did not install the PDFs, they remain accessible on your installation CD. Furthermore, you can install them at a later date by running the Origin "Add or Remove Files" program.

  • Origin Statistical Tools.

Several of the Origin statistical tools access NAG functions. To see NAG function calls implemented as part of Origin review the script files ANOVA1Way.ogs, ANOVA2Way.ogs, CoxPHM.ogs, KaplanMeier.ogs, TTestMean1Sample.ogs, and TTestMean2Sample.ogs located in your Origin folder. See also the OStat.c and SurvivalAnalysis.c source files located in the \OriginC\OriginLab subfolder of Origin.


NAG Functions and Origin Missing Values

Some NAG functions handle Origin missing values passed in as arguments without problems but others may have difficulties. It is recommended that you not pass any Origin missing values in to NAG functions to avoid all such difficulties. Depending upon the numerical consequences for a given analysis, it is good policy to remove missing values usually after requesting approval but always with notification (at least). Some types of analysis involving paired data sets may have to be terminated with a warning message when missing values are encountered.

To ensure that you are not passing missing values inside a vector or matrix to a NAG function Origin provides a number of useful functions. See the Origin C Language Reference for more information on the functions listed below.

curvebase::TrimLeft(BOOL bShiftLeft = FALSE) ;

curvebase::TrimRight(BOOL bDelExtra = FALSE) ;

Curve::Curve(curvebase &cv, int &nNumMissingInCopy, int &nSrcOffset, DWORD dwOptions = 0, int nLower = -1, int nUpper = -1) ;

vector::vector(Dataset &ds, BOOL bRemoveMissingValues = FALSE);

vectorbase::Trim();

vectorbase::TrimLeft(BOOL bShiftLeft = FALSE);

vectorbase::TrimRight(BOOL bDelExtra = FALSE);

matrixbase::RemoveEmptyRows(BOOL bOnlyRemoveEmptyRows = TRUE) ;

matrixbase::Replace(double dThresholdVal, double dReplaceVal = 0, uint wBitwiseOption = 0);


Interpreting NAG Errors

In case an error should occur, most NAG C functions return (by function argument) a pointer to a predefined NAG error structure. The predefined NAG error structure contains a number of elements including an error code and an error message. In Origin C the definition of the predefined NAG error structure is in the system header file nag_types.h and can be found in the \OriginC\system\NAG subfolder of Origin. The definition of the NAG error structure is also shown below for convenience.

typedef struct {

int code; // Out: Error Code

BOOL print; // In: print? yes/no, not used in Origin C

char message[NAG_ERROR_BUF_LEN]; // InOut: Error message

UINT handler; //Error handling function, not used from OriginC

int errnum; // May hold useful value for some errors

} NagError;

In some cases the Origin C version of NAG C functions have been slightly modified (simplified) to not return the entire NAG error structure. In these cases, the Origin C version of the NAG C function returns just the NAG error code not by argument but by the function’s return value. In many other cases, however, the Origin C version of NAG C functions return the entire NAG error structure. In all cases, the prototype of the NAG function in the Origin C Language Reference clearly indicates whether just an error code is returned or whether the entire NAG error structure is returned.

Once identified, all NAG error codes (no matter how they are returned) can be deciphered by referring to the NAG documentation for the function in the NAG PDF files. For more information on how to locate or install the NAG PDF files see the bulleted text NAG PDF Files in the Origin Subfolder \NAG PDFs in the section Getting Help for NAG Functions.


LabTalk Access

Origin C contains a number of functions and techniques that allow Origin C programmers to access LabTalk variables, commands, functions, and objects. This section describes these functions and techniques in detail. All example code in this section is also included in the Origin C source file LabTalkAccessEx.c in the \Samples\Programming\Origin C Files subfolder of Origin.

The functions and techniques that allow programmers to access LabTalk script in their Origin C functions include the following:

  • Get LabTalk variable values using the LT_get_var and LT_get_str global functions.

  • Set LabTalk variable values using the LT_set_var and LT_set_str global functions.

  • Evaluate LabTalk expressions using the LT_evaluate global function.

  • Execute LabTalk statements using the LT_execute global function and the LT_execute member functions of the Layer and Page classes.

  • Prevent a portion of your source code from compiling using the #ifdef and the #endif preprocessor directives. Include LabTalk code between these directives.

  • Include LabTalk object property and method statements in an _LT_Obj { } block inside your Origin C functions.

  • Include LabTalk object property and method statements inside your Origin C functions using the LabTalk and using keywords.


Get and Set LabTalk Variable Values

X1, X2, Y1, Y2, Z1, Z2: When a graph window is active, these variables contain the initial and final X, Y, and Z axis scale values for the active layer. Changing these values resets the X, Y, or Z scale.

X, Y, Z: These variables contain the current X, Y, and Z coordinates of the Screen Reader, Data Reader, or Data Selector tools.

i: The variable i is used to store the index number to a data set. In most cases, this is also the row number of a worksheet. (Notice that in LabTalk, the data set index starts at 1. This contrasts with Origin C, in which the index starts at 0).

SELC1, SELC2, SELR1, SELR2: These variables contain the column and row numbers that delineate the current worksheet selection range.

@A: The angular unit setting. 0 = radian, 1 = degree, 2 = gradian.

@D: The current date and time in Julian days.

@SD: Control the number of significant digits displayed when mathematical operations are performed in the Script window.

%C: The name of the current active data set.

%G: The current project name.

%H: The current active window title.

%X: The DRIVE:PATH of the current project.

%Y: The DRIVE:PATH for the ORIGIN70.INI file.

// Get the value of a numeric LabTalk object property

void GetNumericVariable( )

{

double vv; // Get Layer.ShowX property value

LT_get_var("LAYER.SHOWX", &vv);

printf("The value is: %.1f\n", vv);

}

// Get and Set the value of a LabTalk numeric variable

void GetAndSetNumericVariable()

{

double dIn, dNew;

if( LT_get_var("X1", &dIn) ) // Get X1 variable

{

dNew = dIn - 10;

LT_set_var("X1", dNew); // Set X1 variable

printf("The initial X1 scale value of %g was changed to %g\n", dIn, dNew);

}

}

// Get the value of a LabTalk string variable

void GetActiveDatasetName()

{

char szTemp[100];

LT_get_str("%C", szTemp, 100); // Get %C variable

string strC = szTemp;

printf("The active data set is: %s\n", strC);

}

Get and Set LabTalk Variable Values

Origin C provides global functions to get and set the values of LabTalk numeric and string variables. These variables include user-defined LabTalk variables, LabTalk system variables, and LabTalk object properties. LabTalk system variables are variables that are used internally by Origin. LabTalk object properties are attributes of LabTalk objects. Their syntax is objectName.property for numeric values and objectName.property$ for string values. The LabTalk system variables and object properties are reviewed in the LabTalk Help file, as is a discussion on user-defined variables. All example code in this section is also included in the Origin C source file LabTalkAccessEx.c in the \Samples\Programming\Origin C Files subfolder of Origin.

An abbreviated listing of the commonly used LabTalk system variables follows:

The LabTalk numeric system variables include (but are not limited to):

The LabTalk string system variables include (but are not limited to):

Getting and setting numeric variable values:

To get the value of a LabTalk numeric variable from Origin C, use the following global function:

BOOL LT_get_var(LPCSTR lpcszLabTalkVarName, double* pdResult);

where:

lpcszLabTalkVarName = LabTalk numeric variable name (user-defined variable, system variable, or object property). Must be surrounded in quotation marks. Case insensitive.

pdResult = result of getting LabTalk variable value.

This function returns TRUE if lpcszLabTalkVarName is a LabTalk variable. Otherwise, this function returns FALSE.

To set the value of a LabTalk numeric variable from Origin C, use the following global function:

BOOL LT_set_var(LPCSTR lpcszLabTalkVarName, double dValue);

where:

lpcszLabTalkVarName = LabTalk numeric variable name (user-defined variable, system variable, or object property). Must be surrounded in quotation marks. Case insensitive.

dValue = value to set the LabTalk variable to.

This function returns TRUE if lpcszLabTalkVarName is a LabTalk variable. Otherwise, this function returns FALSE.

The following examples assume a graph window is active in Origin. The first example checks if the axes are displayed in the layer. It outputs 0 if not displayed and 1 if displayed.

The next example gets and sets the X1 system variable (the starting X-Axis scale value).

Getting and setting string variable values:

To get the value of a LabTalk string variable from Origin C, use the following global function:

BOOL LT_get_str(LPCSTR lpcszLabTalkString, char* pBuffer, int nBufferSize);

where:

lpcszLabTalkString = LabTalk string variable (%A - %Z) or LabTalk object string property. Must be surrounded in quotation marks. Case insensitive.

pBuffer = character buffer to receive the string.

nBufferSize = size of the buffer including the terminating zero.

This function returns TRUE if lpcszLabTalkString is a LabTalk string variable. Otherwise, this function returns FALSE.

To set the value of a LabTalk string variable from Origin C, use the following global function:

BOOL LT_set_str(LPCSTR lpcszVar, LPCSTR lpcszContent);

where:

lpcszVar = LabTalk string variable (%A - %Z) or LabTalk object string property. Must be surrounded in quotation marks. Case insensitive.

lpcszContent = string content to be copied to the string variable. Can be NULL to empty a string.

The following example gets and outputs the name of the active data set.


Evaluate LabTalk Expressions

Origin C provides the following global function to evaluate a LabTalk expression using the LabTalk interpreter and assign the result to an Origin C variable:

BOOL LT_evaluate(LPCSTR lpcszLabTalkExpression, double* pdResult);

where:

lpcszLabTalkExpression = LabTalk expression. Must be surrounded in quotation marks. Case insensitive.

pdResult = result of the expression evaluation.

This function returns TRUE if lpcszLabTalkExpression is a LabTalk expression that can be evaluated by the LabTalk interpreter. Otherwise, this function returns FALSE.

Note: This function is similar to the LT_get_var function in that it can also get the value of a LabTalk variable. However, using the LT_evaluate function to get the value of a variable is slower than using the LT_get_var function. Furthermore, the LT_get_var function will recognize that a given name corresponds to a LabTalk variable, even when the variable's value is a missing value. This contrasts with the LT_evaluate function, which will return FALSE (0) because it will not recognize the LabTalk variable.

In the following example, an expression is evaluated by the LabTalk interpreter and assigned to the vv variable. The example code for this section is also included in the Origin C source file LabTalkAccessEx.c in the \Samples\Programming\Origin C Files subfolder of Origin.


Execute a LabTalk Statement

// Execute LabTalk statements

void ExecuteStatements()

{

// Make list of all worksheet windows in current project

LT_execute("%Z="";doc -e W {%Z=%Z %H};type -a %Z");

// Run section of LabTalk script

LT_execute("run.section(File.OGS, Open)");

}

// Execute a LabTalk statement with Data1 page temporarily active

void ExecuteStatementWithPageActive()

{

Page pg("Data1");

pg.LT_execute("type -b %H is temporarily set to active page.");

LT_execute("type -b Even though %H is currently the active page.");

}

Execute a LabTalk Statement

Origin C provides the following global function to execute a LabTalk statement:

BOOL LT_execute(LPCSTR lpcszLabTalkStr, int wCntrl = 0);

where:

lpcszLabTalkStr = LabTalk statement to execute, without the terminating semicolon. Must be surrounded in quotation marks. Case insensitive.

wCntrl = for future implementation only. Default value is zero so omit second argument or set as zero.

This function returns TRUE if lpcszLabTalkStr is a LabTalk statement that can be executed. Otherwise, this function returns FALSE.

The following example executes two LabTalk statements. The first statement actually includes three LabTalk statements and the second executes many statements by running the [Open] section of the LabTalk script file File.OGS.

In addition to the LT_execute global function, the Origin C Layer and Page classes also contain LT_execute member functions. The LT_execute member functions work exactly the same as the LT_execute global function with the added condition that the class member functions temporarily activate the Origin layer or page attached to the calling object when executing their LabTalk statements. For example, no matter which window is currently active in Origin the following function will operate on the Data1 worksheet (the example assumes that the Data1 window exists but it need not be the active window).

All example code for this section is also included in the Origin C source file LabTalkAccessEx.c in the \Samples\Programming\Origin C Files subfolder of Origin.


Include LabTalk Code in Your Origin C Source File and Exclude it from Compiling

// Execute section of LabTalk script below

void ExecuteSectionInCFile()

{

LT_execute("run.section(Samples\Programming\Origin C Files\LabTalkAccessEx.c, Main)");

}

#ifdef LABTALK // can be anything not defined

[Main]

type -b "Currently executing a section of LabTalk script

in the source file LabTalkAccessEx.c";

#endif

Include LabTalk Code in Your Origin C Source File and Exclude it from Compiling

By combining a few programming techniques, you can include LabTalk code right in your Origin C source file, exclude the LabTalk code from compiling, and then call that code from your Origin C function. This strategy takes advantage of the following programming techniques:

  • The Origin C compiler supports preprocessor directives to exclude part of your source code from compiling. In this case, the LabTalk section of code will be excluded.

  • The Origin C global function LT_execute lets you execute a LabTalk statement from your Origin C function.

  • LabTalk provides a run.section method to execute a section of LabTalk script. The section of LabTalk script must begin with a section name surrounded by brackets. For example: [MySectionName]

The following example illustrates this programming strategy. The Origin C code and LabTalk script that follows is in the Origin sample source file LabTalkAccessEx.c found in the \Samples\Programming\Origin C Files subfolder of Origin.

When you compile this source file, the Origin C preprocessor runs. The preprocessor first encounters the #ifdef LABTALK directive. Because LABTALK is not defined using a #define directive, the preprocessor will begin excluding code from the compiler until it reaches the #endif directive. Thus, all the LabTalk code is excluded from the compiler.

The output from the preprocessor is then sent to the Origin C compiler, which creates the executable code in a separate file. Keep in mind that the source file, LabTalkAccessEx.c, still exists.

When you call the Origin C ExecuteSectionInCFile function from LabTalk, the Origin C LT_execute global function is called. This function executes a LabTalk statement. In this case, the LabTalk statement is a run.section method, which runs the LabTalk script located in the section named [Main] in the file ExecuteSectionInCFile.c. Of course ExecuteSectionInCFile.c is your source file! Your LabTalk code in this section is then executed.

For more information on the LT_execute global Origin C function, see Execute a LabTalk Statement. For more information on the run.section LabTalk method, see the LabTalk Language Reference section of this Help file.


Execute a Block of LabTalk Object Code

// Execute an _LT_Obj block mixing Origin C statements

// with LabTalk sort object properties and methods

void ExecuteLTObjBlock()

{

string strWinName = "Data1";

_LT_Obj

{

string strDsName = "Data1_A";

Dataset dsData1A(strDsName);

if( dsData1A.IsValid() )

{

int iSize = dsData1A.GetSize();

sort.wksname$ = strWinName;

sort.c1 = 1; // Sort only first 2 cols

sort.c2 = 2;

sort.r1 = 1;

sort.r2 = iSize;

sort.cname1$ = "A: A";

sort.wks();

}

}

}

Execute a Block of LabTalk Object Code

You can include LabTalk script containing object property and method statements in your Origin C functions. The example function ExecuteLTObjBlock demonstrates mixing Origin C and LabTalk object property and method statements. The example function assumes that the Data1 worksheet exists with unsorted data in columns A and B. The following example uses the LabTalk sort object to sort in ascending order the first two columns of the Data1 worksheet based on column A. The example code for this section is also included in the Origin C source file LabTalkAccessEx.c in the \Samples\Programming\Origin C Files subfolder of Origin.

Because this block allows both LabTalk and Origin C, all expressions are first assumed to be Origin C. If the expression is not a valid Origin C expression, then it is assumed to be LabTalk and is sent to the LabTalk interpreter for evaluation.

The _LT_Obj block is particularly useful for accessing LabTalk objects that do not have an Origin C counterpart, or that have limited implementation in Origin C.

The following list clarifies the LabTalk and Origin C support in the _LT_Obj block:

  • LabTalk variable assignments cannot be made in this block. For example, ii = 5; is illegal and will generate a compile error if ii is not a declared Origin C variable.

  • Arguments in LabTalk object methods must be Origin C variables or expressions.

  • You cannot use LabTalk commands in this block - only LabTalk object notation.


Execute LabTalk Object Code Statements Using "LabTalk" and "using" Keywords

// Execute a mix of Origin C statements and LabTalk sort object

// properties and methods using the "LabTalk" and "using" keywords

void ExecuteUsingLabTalkDot()

{

using sort = LabTalk.sort;

string strWinName = "Data1";

string strDsName = "Data1_A";

Dataset dsData1A(strDsName);

if( dsData1A.IsValid() )

{

int iSize = dsData1A.GetSize();

sort.wksname$ = strWinName;

sort.c1 = 1; // Sort only first 2 cols

sort.c2 = 2;

sort.r1 = 1;

sort.r2 = iSize;

sort.cname1$ = "D: A";

sort.wks();

}

}

Execute LabTalk Object Code Statements Using "LabTalk" and "using" Keywords

In addition to the _LT_Obj block you can include LabTalk script containing object property and method statements in your Origin C functions using the LabTalk and using keywords. The example function ExecuteUsingLabTalkDot demonstrates mixing Origin C and LabTalk object property and method statements using this technique. Like the example function in the previous section, the example function below assumes that the Data1 worksheet exists with unsorted data in columns A and B. The following example uses the LabTalk sort object and the Origin C LabTalk and using keywords to sort in descending order the first two columns of the Data1 worksheet based on column A. The example code for this section is also included in the Origin C source file LabTalkAccessEx.c in the \Samples\Programming\Origin C Files subfolder of Origin.

When using the Origin C LabTalk and using keywords the restrictions are the same as those stated in the previous section for the _LT_Obj block. LabTalk variables and commands can not be accessed and arguments to all LabTalk object methods are assumed to be Origin C expressions.


The Origin sample project file calling_c_dll.opj contains a complete example demonstrating how to call a function in a C dll from Origin C. The sample project file calling_c_dll.opj and all supporting files can be found in the \Samples\Programming\Calling C DLL subfolder of Origin. To experiment with calling a function contained in a C dll from Origin C open the sample project file and follow the instructions provided in the Origin note window.

The Origin sample project file Calling Fortran.OPJ contains a complete example demonstrating how to call a function in a Fortran dll from Origin C. The sample project file Calling Fortran.OPJ and all supporting files can be found in the \Samples\Programming\Calling Fortran subfolder of Origin. To experiment with calling a function contained in a Fortran dll from Origin C open the sample project file and follow the instructions provided in the Origin note window.

Extending Origin C via External DLLs

Origin C functions can make calls to functions in external DLLs created by C, C++, or Fortran compilers. To do this, your source file must contain an include directive for the header file which declares the functions in your external DLL. Your include directive can specify a relative or an absolute path. For example:

#include "temp\myFile.h" // in the \OriginC\temp folder

#include <temp\myFile.h> // in the \OriginC\system\temp folder

#include "c:\myFolder\myFile.h" // in specified path

To distinguish these external DLL functions from Origin C functions, you must include the following Origin C pragma directive in the header file, directly before your external DLL function declarations:

#pragma dll(fileName)

where fileName is either a relative or an absolute path and file name of the DLL. For example:

#pragma dll(myDLL) // in the Origin folder

#pragma dll(c:\myFolder\myDLL) // in specified path

Note: You don't need to include the .dll extension in the file name.

All function declarations after this pragma directive will be considered external and from this specified DLL. This assumption is made until a second #pragma dll(fileName) directive is reached, or until the end of the file is reached.

When calling a function in an external DLL, the Origin C compiler supports three calling conventions: __cdecl (default), __stdcall, and __fastcall. These calling conventions determine the order in which arguments are passed to the stack as well as which function (Origin C calling function or called external function) cleans the arguments from the stack.

In each case, the calling convention is specified in the external function declaration using the syntax:

returnType callType funcName(parameterList);

In this case you would replace callType with the desired calling convention (__cdecl, __stdcall, or __fastcall). Because the default calling convention is __cdecl, you need not include this keyword in your external function declaration.

  • The default calling convention is __cdecl. With this type of external function call, the argument passing order is from right to left and the calling Origin C function cleans the stack. You must supply the .h file to declare functions that are called using this convention.

  • In the __stdcall calling convention, the argument passing order is from right to left and the called external function cleans the stack. You must supply the .h file to declare functions that are called using this convention.

  • In the __fastcall calling convention, the arguments are passed in registers, when possible. Otherwise the argument passing order is from right to left. The called external function cleans the stack. You must supply the .h file to declare functions that are called using this convention.

The following example function declaration uses the __stdcall calling convention:

int __stdcall GetWindowText(HWND, LPTSTR, int);

Example 1: Calling a function in a C DLL

Example 2: Calling a function in a Fortran DLL


Extending Origin C via User-Defined Classes (OriginPro)

Extending Origin C via User-Defined Classes

Origin C supports a nearly complete ANSI C language syntax with exceptions noted in the section ANSI C Support. In addition, Origin C supports an array of C++ and C# features outlined in the sections C++ Support and C# Support. Since its inception, Origin C has included built-in classes used primarily to access internal Origin objects and composite data types. One powerful C++ feature now supported by Origin C is user-defined classes.

User-defined classes allow Origin C programmers to create objects of their own type with user-defined methods and data members. Origin C user-defined classes support:

  • Dynamic allocation of objects using the new and delete operators.

  • Data and function encapsulation with the access control keywords public, private, and protected.

  • Overloading of class methods.

  • Class derivation and object inheritance.

  • Casting.

  • Object containership.

  • Polymorphism (or code re-use) with virtual functions.

  • User-defined objects can self-reference using the this pointer.

The following features are not supported by Origin C user-defined classes:

  • Declaring and defining class methods in different source and header files.

  • Template classes and derivation from template classes.

  • static data members and class methods.

  • Operator overloading.

  • const keyword.

The following two sections contain a complete example showing many aspects of how user-defined classes are implemented. If you are not interested in the details of how Origin C user-defined classes are implemented but you are interested in how to use these classes in your programs proceed to the sections Using the EasyLR Class and Running the DemoEasyLR Function. All sample code can be found in the Origin sample files EasyFit.h, EasyLR.h, and EasyLR.c in the \Samples\Programming\Origin C Files subfolder of Origin.


Implementing Base Class EasyFit

class EasyFit

{

public:

// Constructors

EasyFit() {Curve crvTemp; Init(crvTemp);}

EasyFit(Curve& crvOriginal) {Init(crvOriginal);}

EasyFit(LPCSTR lpcszYData) {Curve crvTemp(lpcszYData); Init(crvTemp);}

EasyFit(LPCSTR lpcszXData, LPCSTR lpcszYData) {Curve crvTemp(lpcszXData, lpcszYData); Init(crvTemp);}

EasyFit(Dataset& dsX, Dataset& dsY) {Curve crvTemp(dsX, dsY); Init(crvTemp);}

EasyFit(Worksheet& wks, int nColX, int nColY) {Curve crvTemp(wks, nColX, nColY); Init(crvTemp);}

EasyFit(Worksheet& wks, int nColY) {Curve crvTemp(wks, nColY); Init(crvTemp);}

EasyFit(DataPlot& dp) {Curve crvTemp(dp); Init(crvTemp);}

EasyFit(curvebase& crv, int& nNumMissingInCopy, int& nSrcOffset, DWORD dwOptions = 0,

int nLower = -1, int nUpper = -1);

// Destructor

~EasyFit()

{

// Included to demonstrate calling destructor...Reset and Detach not required for destruction

Settings.Reset();

m_trWhole.Reset();

m_crvInput.Detach();

m_crvOutput.Detach();

}

// Methods

BOOL Attach(LPCSTR lpcszYData) {return m_crvInput.Attach(lpcszYData);}

BOOL Attach(LPCSTR lpcszXData, LPCSTR lpcszYData) {return m_crvInput.Attach(lpcszXData, lpcszYData);}

BOOL CreateOutputCurve(const matrix& mResultCurves);

BOOL PlotCurves();

BOOL OutputResults(LPCSTR lpcszTitle = NULL, int nOutput = WRITE_SCRIPT_WINDOW);

// Public Data Member

Tree Settings;

protected:

// Virtual Methods

virtual BOOL Init(Curve& crv);

virtual BOOL Fit() {return FALSE;}

// Protected Data Members

Tree m_trWhole;

Curve m_crvInput;

private:

// Private Data Member

Curve m_crvOutput;

};

// Constructor

EasyFit::EasyFit(curvebase& crv, int& nNumMissingInCopy, int& nSrcOffset, DWORD dwOptions,

int nLower, int nUpper)

{

Curve crvTemp(crv, nNumMissingInCopy, nSrcOffset, dwOptions, nLower, nUpper);

Init(crvTemp);

}

// Virtual Method

// Initialize input curve

BOOL EasyFit::Init(Curve& crv)

{

if( crv.IsValid() )

m_crvInput.Attach(crv.GetName());

return m_crvInput.IsValid();

}

// Non-virtual Methods

// Create output curve in hidden worksheet

BOOL EasyFit::CreateOutputCurve(const matrix& mResultCurves)

{

WorksheetPage wp;

Worksheet wks;

Column colX, colY;

Dataset dsX, dsY;

wp.Create("Origin", CREATE_HIDDEN);

if( wp.IsValid() )

{

wks = wp.Layers();

if( wks.IsValid() )

{

while( wks.GetNumCols() < 2 )

wks.AddCol();

colX.Attach(wks, 0);

colY.Attach(wks, 1);

if( colX.IsValid() && colY.IsValid() )

{

dsX.Attach(colX);

dsY.Attach(colY);

if( dsX.IsValid() && dsY.IsValid() )

{

mResultCurves.GetColumn(dsX, 0);

mResultCurves.GetColumn(dsY, 1);

m_crvOutput.Attach(wks, 0, 1);

return TRUE;

}

}

}

}

return FALSE;

}

// Plot input data and output fit curves in new graph

BOOL EasyFit::PlotCurves()

{

GraphPage gp;

gp.Create("Origin");

if( gp.IsValid() )

{

GraphLayer gl;

gl = gp.Layers();

if( gl.IsValid() )

{

add_curve_to_graph_layer(m_crvInput, gl, 0, false, IDM_PLOT_SCATTER);

add_curve_to_graph_layer(m_crvOutput, gl, 1, true, IDM_PLOT_LINE);

return TRUE;

}

}

return FALSE;

}

// Output settings and result parameters

BOOL EasyFit::OutputResults(LPCSTR lpcszTitle, int nOutput)

{

Tree trResults;

trResults = m_trWhole;

tree_dump(trResults, lpcszTitle, nOutput);

return TRUE;

}

Implementing Base Class EasyFit

The base class EasyFit contains a number of public methods and a single data member named Settings. The public methods include several constructors, a destructor, two overloaded Attach methods, and methods to create, plot, and output the fit results. Each of the EasyFit constructors declare a temporary Origin C Curve object attached to the input XY data and then pass that curve to an initialization function. The destructor is not technically needed for the EasyFit class but is included for demonstration purposes. Three other class methods are used to create an output fit curve, plot the input and output fit curves, and output the fit results. These last three methods are general and are intended to be re-used by all derived classes. The public data member Settings is an Origin C Tree object and is intended to be used to customize settings supported by each different type of fit. Objects of classes derived from the EasyFit class can use the Settings tree to indirectly set the nodes of another tree (a protected data member) which then controls the fit.

The EasyFit class also contains two protected methods and two protected data members for use by derived classes. The protected method Init is a virtual function and is intended to allow each derived class to initialize itself according to the type of fit it performs. The protected method Fit is also a virtual function and is intended to allow each derived class to customize the type of fit it performs. The protected data member m_trWhole is a Tree object used to pass all input settings to and receive all output results from a low level number crunching function that actually performs the fit. The public data member Settings can be used to initialize m_trWhole. The protected data member m_crvInput is an input Origin C Curve object (input XY data) on which the fit will be performed. Finally, the EasyFit class contains a private data member m_crvOutput. The private data member m_crvOutput is an output curve object which can optionally be saved by the base class to an Origin worksheet.

Note that the EasyFit class is not derived from the Origin C built-in class Curve. Rather, it contains two Curve objects as data members. This is because the Curve class supports a number of underlying base data types (such as double, int, etc.) and thus is a template class. User-defined classes can be derived from built-in classes but not from built-in template classes. The following code implements the EasyFit class.

All sample code can be found in the Origin sample files EasyFit.h, EasyLR.h, and EasyLR.c in the \Samples\Programming\Origin C Files subfolder of Origin. To open EasyFit.h click the button below to open EasyLR.c in Code Builder, in the source file EasyLR.c right-click on the line

#include "EasyFit.h"

and then select Open "EasyFit.h" from the shortcut menu.


Implementing Derived Class EasyLR

class EasyLR : public EasyFit

{

public:

// Constructors

EasyLR():EasyFit() {}

EasyLR(Curve& crvOriginal):EasyFit(crvOriginal) {}

EasyLR(LPCSTR lpcszYData):EasyFit(lpcszYData) {}

EasyLR(LPCSTR lpcszXData, LPCSTR lpcszYData):EasyFit(lpcszXData, lpcszYData) {}

EasyLR(Dataset& dsX, Dataset dsY):EasyFit(dsX, dsY) {}

EasyLR(Worksheet& wks, int nColX, int nColY):EasyFit(wks, nColX, nColY) {}

EasyLR(Worksheet& wks, int nColY):EasyFit(wks, nColY) {}

EasyLR(DataPlot& dp):EasyFit(dp) {}

EasyLR(curvebase& crv, int& nNumMissingInCopy, int& nSrcOffset, DWORD dwOptions = 0,

int nLower = -1, int nUpper = -1)

:EasyFit(crv, nNumMissingInCopy, nSrcOffset, dwOptions, nLower, nUpper) {}

// Destructor

~EasyLR() {}

// Virtual Methods

virtual BOOL Fit();

virtual BOOL Init(Curve& crv);

};

// Virtual Method

// Initialize settings and input curve

BOOL EasyLR::Init(Curve& crv)

{

Tree trTemp;

trTemp.GUI.Fit.ThroughZero.nVal = 0; // Force fit to pass thru zero

trTemp.GUI.Fit.FixSlope.nVal = 0; // Force slope to be fixed

trTemp.GUI.Fit.FixSlopeAt.dVal = 1; // Fixed value of slope (Note: cannot fix slope and thru zero at same time, should return error from LLOC)

trTemp.GUI.Fit.ErrBarWeight.nVal = 0; // Use error column for wt - use (1/err^2) as wt factor

trTemp.GUI.Fit.UseReducedChiSq.nVal= 0; // Scale parameter errors with reduced chisqr

trTemp.GUI.ResultCurves.Points.nVal = 60; // Number of points in fit curve

trTemp.GUI.ResultCurves.ConfBands.nVal = 0; // Create confidence bands - if not set, then matrix will have empty columns

trTemp.GUI.ResultCurves.PredBands.nVal = 0; // Create prediction bands - if not set, then matrix will have empty columns

trTemp.GUI.ResultCurves.Confidence.dVal = 95; // Confidence value to be used

trTemp.Calculation.Control.UseDataXRange.nVal = 1; // Option = 1 to use data range, = 0 to use X1, X2

trTemp.Calculation.Control.X1.dVal = NANUM; // Default X minimum for fit curve

trTemp.Calculation.Control.X2.dVal = NANUM; // Default X maximum for fit curve

m_trWhole.AddNode(trTemp.GUI.Clone());

m_trWhole.AddNode(trTemp.Calculation.Clone());

return EasyFit::Init(crv);

}

// Virtual Method

// Customize settings, perform fit, and create output curve in hidden worksheet

BOOL EasyLR::Fit()

{

matrix mResultCurves;

// Customize Settings

if( Settings.ThroughZero.IsValid() )

m_trWhole.GUI.Fit.ThroughZero.nVal = Settings.ThroughZero.nVal;

if( Settings.FixSlope.IsValid() )

m_trWhole.GUI.Fit.FixSlope.nVal = Settings.FixSlope.nVal;

if( Settings.FixSlopeAt.IsValid() )

m_trWhole.GUI.Fit.FixSlopeAt.dVal = Settings.FixSlopeAt.dVal;

if( Settings.UseReducedChiSq.IsValid() )

m_trWhole.GUI.Fit.UseReducedChiSq.nVal = Settings.UseReducedChiSq.nVal;

if( Settings.Points.IsValid() )

m_trWhole.GUI.ResultCurves.Points.nVal = Settings.Points.nVal;

if( Settings.Confidence.IsValid() )

m_trWhole.GUI.ResultCurves.Confidence.dVal = Settings.Confidence.dVal;

if( Settings.UseDataXRange.IsValid() )

m_trWhole.Calculation.Control.UseDataXRange.nVal = Settings.UseDataXRange.nVal;

if( Settings.X1.IsValid() )

m_trWhole.Calculation.Control.X1.dVal = Settings.X1.dVal;

if( Settings.X2.IsValid() )

m_trWhole.Calculation.Control.X2.dVal = Settings.X2.dVal;

// Perform fit and create output curve in hidden worksheet

if( ERROR_NO_ERROR == stat_linear_fit(m_crvInput, mResultCurves, m_trWhole) )

return CreateOutputCurve(mResultCurves);

else

return FALSE;

}

Implementing Derived Class EasyLR

The class EasyLR is derived from the base class EasyFit and inherits all of its methods (not constructors or destructor) and data members. The EasyLR class does not include but inherits the EasyFit class methods Attach, CreateOutputCurve, PlotCurves, and OutputResults. The EasyLR class also contains a number of public methods including several constructors, a destructor, and two virtual methods. Each of the EasyLR constructors simply calls its corresponding EasyFit constructor. The EasyLR destructor is not technically needed but is included for demonstration purposes. Finally, the EasyLR class contains two public virtual methods which get called in place of the same named methods in the EasyFit class. The virtual functions differentiate the two classes allowing the EasyLR class to customize the type of fit it performs. The virtual method Init initializes the EasyLR object to perform a linear regression and the virtual method Fit performs the linear regression.

Other classes, implementing different types of fits, can additionally and “easily” be derived from the EasyFit class. For example, a hypothetical class, named EasyPR, designed to encapsulate a polynomial regression would essentially be a copy of the EasyLR class but with customized Init and Fit functions that initialize for and perform a polynomial regression. The EasyFit class is a base class in the truest sense of the word. In fact, the EasyFit class is abstracted to the extent that objects of type EasyFit are not even intended to be declared. The EasyFit class contains constructors solely for the purpose of being re-used by derived classes. The EasyFit class exists primarily as a base class from which many other class types (each performing a different type of fit) can be derived. The following code implements the EasyLR class.

All sample code can be found in the Origin sample files EasyFit.h, EasyLR.h, and EasyLR.c in the \Samples\Programming\Origin C Files subfolder of Origin. To open EasyLR.h click the button below to open EasyLR.c in Code Builder, in the source file EasyLR.c right-click on the line

#include "EasyLR.h"

and then select Open "EasyLR.h" from the shortcut menu.


Using the EasyLR Class

// Demonstrate performing an easy linear regression

int DemoEasyLR()

{

// Declare EasyLR object named elrDemo

EasyLR elrDemo("Data1_A", "Data1_B");

// Customize input settings

elrDemo.Settings.ThroughZero.nVal = 1; // Force fit to pass thru zero

elrDemo.Settings.Confidence.dVal = 90; // Set confidence level

// Perform fit

elrDemo.Fit();

// Plot input and output curves

elrDemo.PlotCurves();

// Output results to Script window

elrDemo.OutputResults("Easy Linear Regression Results");

return 0;

}

// Demonstrate performing an easy linear regression with new and delete operators

int DemoEasyLRwithNew()

{

EasyLR *pelrDemo = new EasyLR;

pelrDemo->Attach("Data1_A", "Data1_B");

// Perform fit

pelrDemo->Fit();

// Plot input and output curves

pelrDemo->PlotCurves();

// Output results to Script window

pelrDemo->OutputResults("Easy Linear Regression Results");

// Destroy EasyLR object pointed to by pelrDemo

delete pelrDemo;

return 0;

}

Using the EasyLR Class

Once implemented, the EasyLR class can be used to write simplified code that performs a linear regression. Many of the coding details normally required to implement a linear regression are hidden inside the EasyFit class. The following example function DemoEasyLR uses the EasyLR class to perform a linear regression. All sample code can be found in the Origin sample files EasyFit.h, EasyLR.h, and EasyLR.c in the \Samples\Programming\Origin C Files subfolder of Origin.

The DemoEasyLR example function above uses an EasyLR type specifier to declare (construct) an object of type EasyLR named elrDemo. The EasyLR constructor accepting two data set names as arguments calls the corresponding EasyFit constructor (passing along the data set names Data1_A and Data1_B) which in turn calls the virtual function Init. Since the instantiated object is of type EasyLR and the function Init is virtual the EasyLR version of Init is called which initializes a linear regression tree and then explicitly calls back the EasyFit version of Init. The EasyFit version of Init attaches the class data member m_crvInput (a Curve object) to the specified input data sets and returns.

Once the EasyLR object elrDemo is declared it can be used to perform a linear regression and output the results. Before fitting, a number of settings common to all linear regressions (including an option to force the fit line through the Origin and a confidence level) can be set using the EasyLR data member Settings inherited from the EasyFit class. The line elrDemo.Fit(); calls the EasyLR version of the virtual function Fit since the object is of type EasyLR. The virtual function Fit first collects all initialized settings and then passes them to a global and low level number crunching function that actually performs the regression. Once the regression is complete, the EasyLR version of the Fit function calls the CreateOutputCurve function inherited from the EasyFit class which creates and saves an output fit curve in a newly created Origin worksheet.

After the fit has been performed and the output fit curve has been saved to a worksheet the member function PlotCurves is called. The PlotCurves function inherited from the base class EasyFit creates a new Origin graph window, plots the input curve as a Scatter plot (square black symbols), and then plots the output fit curve as a red Line plot. Note the fit line passes through the Origin. Finally, the OutputResults function, also inherited from the EasyFit class, outputs all input settings and fit results in the Script window.

In addition to declaring objects using a type specifier, such as the type specifier EasyLR in the example function above, Origin C supports the use of the new and delete operators to allocate and free memory. The following example function DemoEasyLRwithNew is nearly identical to the DemoEasyLR function above except it uses the new and delete operators instead of the EasyLR type specifier. Note also the use of the member pointer symbol -> and that no settings are set using the Settings data member.


Running the DemoEasyLR Function

To run the example functions DemoEasyLR and DemoEasyLRwithNew follow the steps below.

  1. Click the New Project button [image] to create a new Origin project file.

  2. Highlight both columns in the Data1 worksheet and select Column:Fill Column With:Uniform Random Numbers to fill the worksheet with data.

  3. With both columns still highlighted, select Plot:Scatter to create an XY Scatter plot.

  4. Click the Code Builder button [image] to open Code Builder.

  5. Select the Code Builder File:Open Workspace menu item. Browse to and open the Code Builder workspace file EasyLR.ocw in the \Samples\Programming\Origin C Files subfolder of Origin.

Note: A workspace file contains a list of source files implementing an application (in this case the DemoEasyLR() function and the EasyFit and EasyLR classes). All source files listed in a workspace file are automatically added to the Code Builder workspace when the workspace file is opened. The sample files listed in EasyLR.ocw (EasyFit.h, EasyLR.h, and EasyLR.c) can also be found in the in the \Samples\Programming\Origin C Files subfolder of Origin. The source file EasyLR.c can alternatively be opened by clicking the button below but must also be added to the workspace by activating its window in Code Builder and pressing CTRL + W.

  6. Click the Rebuild All button [image] to build all the files in the workspace.

  7. Select the Origin Window:Script Window menu item to open the Script window in Origin.

  8. Type the command DemoEasyLR() in the Script window and press the ENTER key.

The DemoEasyLR function runs and performs a linear regression on the data in the Data1 worksheet. Note that the fit curve (red line plot) passes through the Origin.

  9. Repeat step 8 this time entering the function name DemoEasyLRwithNew.

The DemoEasyLRwithNew function runs and performs a second linear regression on the data in the Data1 worksheet. Note that this time the fit curve (red line plot) does not pass through the Origin.


Compiling, Linking, and Loading

Before you can access your Origin C functions from Origin, you will need to compile and link them (a process known as building). While developing your functions, you will most likely perform your compiling and linking in Code Builder. Once your functions compile and link without error, you can then access them from the current Origin session. To access your functions in future sessions of Origin you will need to ensure that they are reloaded and linked. The loading and linking of compiled Origin C functions in new sessions of Origin is fast and can be automated. This chapter covers the compiling, linking, and loading process for both the development phase and the usage phase of Origin C functions.


Understanding the Code Builder Workspace

The Code Builder workspace has four built-in folders named Project, System, Temporary, and User. The adding, compiling, and linking of files in each folder is triggered by different events. Files in the Project folder are saved within the current Origin project file (*.OPJ). They are added to the Project folder of the Code Builder workspace when you open an Origin project file containing them and they are automatically compiled and linked immediately upon opening the project file. Files in the System folder are externally saved in Window’s folders (usually in the Origin C folder or one of its subfolders). They are automatically added to the System folder of the Code Builder workspace, compiled, and linked whenever Origin starts. Files in the Temporary folder are externally saved in Window’s folders and are programmatically added to the Temporary folder of the Code Builder workspace, compiled, and linked at execution time by a LabTalk script or by an Origin C function. Files in the User folder are externally saved in Window’s folders and are manually added to the User folder of the Code Builder workspace, compiled, and linked by users in Code Builder. In addition, files in all Code Builder folders are compiled and linked when the Code Builder Rebuild All toolbar button is clicked or when they are the active window in the Code Builder Multiple Document Interface (MDI) or a dependent of the active window and the Build toolbar button is clicked.

Folders in the Code Builder workspace can include Origin C source files (*.C, *.CPP), preprocessed Origin C files (*.OP), header files (*.H), LabTalk script files (*.OGS), and text files. In order for these files to be part of the workspace, you must first add the files to the workspace; you can not simply open them in Code Builder's MDI. When you create new source files, they are automatically added to the User folder of the workspace. You can can also add any file that is open in the MDI to the User folder of the workspace. Files can be dragged from any Code Builder folder and dropped into the Project, System, or User folders (but not the Temporary folder). Files can only be programmatically added to the Temporary folder. Adding files to any workspace folder provides the following programming advantages:

  • Only source or preprocessed files that have been added to the workspace can be compiled and linked. Once compiled and linked, the Origin C functions contained in those source files can be called from Origin.

  • Files that are added to the workspace display as icons in the Workspace window. You can easily locate files and activate their display in the MDI by double-clicking on their icon in the Workspace window.

  • The User folder of the Code Builder workspace can be saved as a workspace file. In addition to opening and building workspaces from inside Code Builder, Origin provides a method to open and compile a workspace file when Origin starts. There is also a method to programmatically open and build a workspace file. If you have functions that are coded in separate source files, but the source files are saved in the same workspace file, you can simultaneously open and build all the source files included in the workspace file.

When you create a custom Origin routine, in most cases you should do all your Origin C programming in one or more source files that are part of the same workspace file. Deciding whether to program all your functions in the same source file or in separate source files (but in the same workspace file) depends on the number of functions in your program and your personal programming preferences. Because Origin provides methods to open and compile a workspace file, functions can be coded in the same or separate source files but in the same workspace.

After you finish developing your Origin C functions in the User folder of the Code Builder workspace, you must decide how you want the source files added to the Code Builder workspace, compiled, and linked so that the functions can be called from Origin. The following sections discuss this in detail.


Technical Note: One of the files compiled the first time Origin is started is the system header file Origin.h (and all of its included files) which are compiled into Origin.pch (a pre-compiled header file similar in nature to Microsoft Visual C++ pre-compiled header files). When a source file includes Origin.h (as do most OriginLab system files) the pre-compiled header file is not actually copied into the source file before compilation. Rather, it is loaded like a DLL and then accessed in memory greatly speeding the entire build process - since Origin.pch has most likely already been loaded by some other Origin system file. In addition, including Origin.h in your source file makes many Origin related classes and global functions (including all NAG functions) immediately available to be called.

An Overview of the Build Process

In order to compile and link an Origin C source file (of type *.C or *.CPP) or an Origin C preprocessed file (*.OP) you must first add it to a folder in the Code Builder workspace. To learn more about the Code Builder workspace and about adding files to folders in the workspace see Working with Workspaces and Working with Files in the Code Builder User’s Guide.

Once a source or preprocessed file is added to the Code Builder workspace it can be compiled by selecting it in the Code Builder MDI and clicking Compile [image]. Compiling a source or preprocessed file checks it for proper Origin C syntax and compiles the source/preprocessed code into object code. The first time an Origin C source/preprocessed file is successfully compiled the compiler creates an object file having the same name as the source/preprocessed file but with an OCB file extension. The object file is saved in the OCTemp subfolder of the Origin User Files folder.

Once created, object code can be loaded into memory, linked, and made ready for execution by building the Code Builder workspace. To build all files in the Code Builder workspace click Rebuild All [image] or to build the active window in the Code Builder MDI and all dependents of the active window click Build [image]. Building files in the Code Builder workspace recompiles them (as needed and as described above) and then links them so that their functions can be executed.

Once an object file is created for a source/preprocessed file, subsequent building of the source/preprocessed file occurs much faster. If no changes have been made to the source/preprocessed file since the object file was last created, Code Builder only needs to load and link the object file when the source/preprocessed file is built. This mechanism streamlines the entire build process and greatly reduces the overall build time. Origin itself takes advantage of this mechanism by pre-compiling many of its system files the first time Origin is started making them near ready for later use on quick demand. Including the file Origin.h in your source files takes full advantage of the pre-compiling mechanism and is recommended to speed compilation (of your source files).

The compilation process described above can be altered by setting Origin system variables in the Origin Script window or in the Code Builder LabTalk Console. Setting the Origin system variable @OCSB=0 (default is 1) before compiling causes the compiler to create preprocessed files (of type *.OP) instead of creating object files (of type *.OCB). Preprocessed files always have the same name as the source file and are always saved in the same folder as the source file (but have an OP file extension). Once made, a preprocessed file can be added to the Code Builder workspace in place of its source file making the source file no longer necessary for compilation. Developers may want to ship preprocessed files to speed initial compilation. After the first compilation, however, object files are created making preprocessed files less important. In addition, OriginPro developers may want to ship encrypted preprocessed files to hide implementation details. In OriginPro (only), setting the system variable @OCSE=1 (default is 0) causes the compiler to encrypt and render preprocessed OP files unreadable to the human eye. Encrypted OP files, however, can be loaded and linked by any installation of Origin including non-Pro Origin installations. Setting the system variable @OCS=0 (default is 1) before compiling causes the compiler to not create OP files even if @OCSB=0.


Four Methods of Building the Code Builder Workspace

Origin C source/preprocessed files dragged into the Project folder of the Code Builder workspace are saved into the current Origin project file (of type .OPJ) when the project file is saved. Source and preprocessed files saved in an Origin project file are loaded into the Code Builder Project folder and are automatically compiled and linked immediately upon opening the project file that contains them. Files in the Project folder remain in the Project folder until they are dragged out into either the System or User folders or until a new Origin project file (*.OPJ) is opened. Files in the Project folder remain even when a new Code Builder workspace is created or opened.

Origin C source/preprocessed files in the System folder are automatically built when Origin starts. To specify a source/preprocessed file as a system file, drag the file from the Project, Temporary, or User folders of the Code Builder workspace into the System folder. Alternatively, with Origin closed, edit the Origin.INI file adding a key of the form

FileN=FilePath\FileName

in the [OriginCSystem] section where N is the number of the file in System folder. The next time Origin starts the file will be included in the System folder. To remove a file from the System folder simply drag it out of the System folder into the Project or User folder or, with Origin closed, delete the corresponding FileN= line in the Origin.INI file. Any system file can be added or removed using these two methods except for the file sys_utils.c which Origin always includes as a system file. Once a file becomes a system file it is remembered as a system file each time Origin starts, each time a new project file is opened, and even when a new Code Builder workspace file is opened.

In addition to building system files on start up, it is also possible to specify that files in the User folder be loaded and built on Origin start up. User files in the Code Builder workspace last open in the previous session of Code Builder can be automatically built when Origin starts. To configure Origin to automatically build on start up the last open Code Builder workspace, in addition to any system files, follow the steps below:

  1. Right-click on the workspace icon in Code Builder's Workspace window.

  2. Select Build on Startup from the shortcut menu.

  3. Close Code Builder and close Origin to save these settings.

When you restart Origin, the last opened workspace is re-opened and source files in the System and User folders of the Code Builder workspace are automatically built. This makes your functions immediately available to be executed on start up of Origin.

Origin C source files can be added to the Temporary folder in the Code Builder workspace and programmatically built just before calling your functions. This method can be thought of as “just in time” compiling and linking and can be done on an as needed basis. Source files built using this method are added to the Temporary folder of the Code Builder workspace.

Origin provides two different methods for programmatically adding files to the Temporary folder of the Code Builder workspace and then building them. The LabTalk run object includes the LoadOC method and the Origin C Project class contains the FindFunction method. For more information on the run.LoadOC and Project.FindFile methods, and on programmatically building the Code Builder workspace in general, see Programmatically Compiling and Linking.

Programmatically building Origin C source files is most useful when you do not need your functions to be immediately accessible every time you start Origin (i.e. you won't be calling your functions every time you run Origin). For example, you have developed a tool that calls Origin C functions but you do not use this tool every time you start Origin. In such cases, you may want to programmatically compile and link the source files containing these functions when the tool is launched rather than every time you start Origin. Several built-in Origin tools use this method.

The Origin C source files in the Code Builder workspace can be built manually inside the Code Builder interface by selecting Tools:Build (or press SHIFT+F8 keys) or Tools:Rebuild All (or press ALT+F8 keys). Alternatively, you can click the Build [image] or Rebuild All [image] toolbar buttons.

This method is most useful when Code Builder is open while developing your Origin C functions. For information on how to add, remove, and exclude source files in the User folder of the Code Builder workspace see Working with Files in the Code Builder User’s Guide.

Four Methods of Building the Code Builder Workspace

Files can be added to the Code Builder workspace and built using one of four methods. Each method has particular applications.

  • Files in the Project folder of the Code Builder workspace are automatically built when an Origin project file is opened.

  • Files in the System folder of the Code Builder workspace are built automatically when Origin starts.

  • Files can be added to the Temporary folder in the Code Builder workspace and programmatically built just before calling your functions.

  • Files in all folders (including the User folder) of the Code Builder workspace can be manually built inside the Code Builder interface.


Programmatically Compiling and Linking

To programmatically compile and link a source file, or to programmatically build a workspace from a LabTalk script use the run.loadOC method.

err = run.LoadOC("myFile",[option]);

The following rules apply to the err return value

The following rules apply to the myFile argument

The following rules apply to the optional option argument

In the following example, the my_tools.c file is loaded and compiled. If this fails, an error message displays.

if(run.LoadOC("myFolder\my_tools")!=0)

type -b "Cannot load support Origin C file";

In this example, myFolder is assumed to be a subfolder in the \OriginC folder.

In the next example, two source files are loaded, compiled and linked. Linking is explicitly performed by omitting the file argument in the last call to the run.LoadOC method.

err=run.LoadOC(originlab\util,8); // Compile but don't link

err=run.LoadOC(originlab\final,8); // Compile but don't link

if(err == 0)

run.LoadOC(); // Only perform linking if no file specified

  • If err = 0, indicates success. Either myFile is already loaded in the current workspace or it is loaded from a *.C file and compiled and linked successfully.

  • If err = 1, myFile was not found.

  • If err = 2, myFile was found and loaded into the current workspace, but the compiling or linking failed.

  • myFile can be either a workspace file (*.OCW)or a source file (*.C).

  • If myFile is a workspace file, Origin checks each source file in the workspace file to see whether or not it is already loaded.

  • If myFile is a source file, Origin checks to see if it is already loaded.

In either case, if a source file is not already loaded then Origin adds it to the Temporary folder in the Code Builder workspace. When Origin is finished checking, it builds the Code Builder workspace. Files added to the Temporary folder of the Code Builder workspace are removed from the workspace when you close Code Builder or when you open a new or existing workspace file.

  • You must surround myFile with quotation marks ("myFile").

  • If no file extension is included, myFile is assumed to be a source file (*.C).

  • If myFile has a full path, then it is used as is. If a path is not specified, Origin assumes that myFile is located in the \OriginC subfolder.

For network versions of Origin, Origin checks for myFile first in the server's \OriginC subfolder. If it is not found, then Origin checks in the client's \OriginC subfolder.

  • option= 1, myFile should be added to the User folder of the current workspace file and not added to the Temporary folder.

  • option = 2, force myFile to be rebuilt, even if it is already loaded in the current workspace.

  • option= 4, disable adding internal.c to the workspace. (By default, internal.c is added to the workspace when this method is run. The internal.c file contains many function definitions that are used by built-in Origin routines.)

  • option = 8, disable linking, so that you can load and compile multiple source files and link after the last one is compiled.

Note: These are bit values and can be combined using the bit wise OR operator |.

By default all Origin C workspaces contain a global instance of the Project class named Project. The Project class contains a FindFunction method which can be used to find and then build the source file containing a particular function. The prototype of the FindFunction method is

Function FindFunction(LPCSTR lpcszFunctionName, LPCSTR lpcszFileName = NULL, BOOL bCompileDependents = FALSE);

where lpcszFunctionName is the name of the function to find and lpcszFileName is the path and name of file containing the function. bCompileDependents causes files dependent on (included in) lpcszFileName to be also built and can only be used if lpcszFileName is supplied. If lpcszFileName is not specified the function must be in a file already included in the Code Builder workspace. If lpcszFileName is specified then pathing can be absolute or relative to the Origin C subfolder of Origin.

The following example function myFunction is contained in the sample source file FindFunctionEx.c and can be found in the \Samples\Programming\Origin C Files subfolder of Origin. Note the pathing specified is relative to the Origin C subfolder of Origin.

The function above compiles, links, and loads the source file WksFuncs.c and then executes the AddColumns function.

typedef void (*FUNCTYPE)(Worksheet& wks, int nn);

void myFunction()

{

string strPath; // Relative pathing...

strPath = "..\Samples\Programming\Origin C Files\WksFuncs.c";

Function fn = Project.FindFunction("AddColumns", strPath);

FUNCTYPE pfn = fn;

// Can be done in one line:

//FUNCTYPE pfn = Project.FindFunction("AddColumns", strPath);

if( pfn )

{

Worksheet wks;

wks.Create();

pfn(wks, 5);

}

}

// Function to add columns to a worksheet

void AddColumns(Worksheet& wks, int nn)

{

if( wks )

{

for( int ii = 0; ii < nn; ii++ )

{

wks.AddCol();

}

}

}

Programmatically Compiling and Linking

Before you call your Origin C function from Origin, your function must be compiled and linked in the current Origin session. Origin provides the following two methods to programmatically compile and link a source file.

  • From LabTalk use the run object’s LoadOC method.

  • From an Origin C function use the Project object’s FindFile method.


Preprocessor Directives

#define with one or more arguments. For example, the following is supported:

#define MIN(x,y) (x < y ?(x):(y))

#undef is also supported.

The following directives are supported and demonstrated in the following example:

    • #if

    • #elif

    • #else

    • #endif

    • #ifdef

    • #ifndef

#if _OC_VER >= 0x0750

#define MIN(x,y) (x < y ?(x):(y))

#include <analysis_utils.h>

int HelloWorld()

{

printf(“Hello World!”);

return 0;

}

#endif //#if _OC_VER >= 0x0750

#include directive.

Note: Angle brackets (<>) indicate that the included file is located in Origin C's system folder, which is the \OriginC\system subfolder of Origin. Use double-quotes to include your own header file specifying either an absolute or a relative path. Relative paths are relative to the location of the source file containing the #include directive.

For example, if a source file were located in the Origin subfolder \OriginC, the following #include directives would be legal:

// Header file is in the \OriginC\temp folder:

#include "temp\myFile.h"

// Header file is in the \OriginC\system\temp folder:

#include <temp\myFile.h>

// Header file is in specified path:

#include "c:\myFolder\myFile.h"

  • To output a message during compilation:

#pragma message(messageString)

  • To specify packing alignment for structure members:

#pragma pack(push,n)

#pragma pack(pop)

  • To use ^ as the XOR (exclusive "or") operator:

#pragma xor(push, FALSE)

  • To use ^ as the power operator:

#pragma xor(push, TRUE)

  • To return to the default -- use ^ as the power operator:

#pragma xor(pop)

  • To distinguish external DLL functions from Origin C functions:

#pragma dll(fileName)

where fileName is either a relative or an absolute path and file name of the DLL. For example:

#pragma dll(myDLL) // in the Origin folder

#pragma dll(c:\myFolder\myDLL) // in specified path

For more information, see Extending Origin C via External DLLs.

  • To include the file only once in a build by the compiler:

#pragma once

  • The name of the current source file:

__FILE__

  • The line number in the current source file:

__LINE__

Preprocessor Directives

Origin C supports the following preprocessor directives and predefined macros:

Macro Substitution

Conditional Inclusion

File Inclusion

Supported Pragmas

Predefined Macros


Fixing Compiler and Linker Errors

When you compile and link source files in Code Builder, the compiling and linking results are displayed in the Code Builder Output window.

If the compiling and linking was successful, the Output window lists the source files that were compiled. The Done! line indicates success.

If errors were encountered during the compiling and linking process, the Output window lists the file name, line number, and the error encountered. You can double-click on the error line in the Output window to activate the source file and position the cursor on the line of code containing the error.


The ASSERT Macro and Debug Statements

Origin C provides an ASSERT macro to identify logic errors during program development. The Origin C ASSERT macro has the following syntax:

ASSERT(condition)

When a function is called that includes an ASSERT, the ASSERT outputs a diagnostic message to Code Builder's Output window when the condition evaluates to false (zero). The diagnostic message indicates the source file and line number where the assertion failed. Thus, if your function expects a variable value to be non-zero, you could add the following line of code to alert you if the variable value is zero.

ASSERT(myVar != 0);

In the following example, if the size of the vector bb is not equal to the size of the vector aa, then a diagnostic message displays in the Code Builder Output window.

void AssertMacro(int imax = 10)

{

vector<int> aa(imax);

vector<int> bb;

for (int ii = 0; ii < aa.GetSize(); ii++)

aa[ii] = ii;

bb = 10 * aa;

// imax += 1;

ASSERT(bb.GetSize() == imax);

for (ii = 0; ii < bb.GetSize(); ii++)

printf("bb[%d]=%d \n", ii, bb[ii]);

}

If you run the above function with the line imax+=1; commented out then no ASSERT message is output. However, if you uncomment the line imax+=1; (and rebuild) the ASSERT message below is output.

Double-clicking on the line containing the Assert Failed!!! message in the Code Builder Output window will open the appropriate source file (DebugMacros.c) in the Code Builder text editor and position the cursor on the line generating the ASSERT message.

Many programmers use output statements while developing code to indicate program flow and display the values of variables at key moments. A convenient debugging technique is to define an output macro and then place that macro throughout your code as shown below.

#define DBG_OUT(_text, _value) out_int(_text, _value);

void DebugStatements()

{

int ii;

DBG_OUT("ii at t0 = ", ii)

ii++;

DBG_OUT("ii at t1 = ", ii)

ii++;

DBG_OUT("ii at t2 = ", ii)

ii++;

DBG_OUT("ii at t3 = ", ii)

printf("Finished running DebugMacros.");

}

During the development cycle the body of the macro can remain defined as above causing the desired debug messages to be output. However, once development is complete (or at least stable) the macro can be redefined as below causing the debug statements to disappear.

#define DBG_OUT(_text, _value) // out_int(_text, _value);

Commenting out the body of the DBG_OUT macro (and rebuilding) causes the debug statements to disappear without having to remove the many possible instances of its use yet saves them for possible re-use in the future. Should the code ever need to be modified or debugged again the body of the macro can simply be uncommented.

The ASSERT Macro and Debug Statements

Origin C allows users to define multi-parameter macros which have many uses. Two such uses, which help while debugging, are the ASSERT macro and macros containing debug statements. The following sections contain example code and discuss these macros in more detail. The example file DebugMacros.c can be found in the \Samples\Programming\Origin C Files subfolder of Origin.

Checking for Logic Errors Using the ASSERT Macro

Commenting Out the Body of a Debug Statement


Closing Code Builder to Maintain Origin's Speed

To simplify debugging your functions in Code Builder, the debug mode is always on by default. Because of this, unless you are developing, compiling, or debugging your code, you should keep Code Builder closed. If Code Builder is open when you are running Origin, routines that call LabTalk and/or Origin C functions will run slower due to the debugging process.


Calling Origin C Functions

Origin C functions are generally created using Origin’s integrated development environment (IDE) named Code Builder. Once a source file has been added to the Code Builder workspace and compiled and linked without errors, it can then be called from Origin. For the most part, Origin C functions are called from Origin using LabTalk statements. Two exceptions to this rule are the following:

  • When you define a new fitting function, you may select the Use Origin C checkbox (this is selected by default), in which case your function will be coded and compiled using Origin C. You may further choose to define or edit your new function in a specialized instance of Code Builder. Once your function has compiled successfully and you save the function by clicking the Save button in the fitter, you can then access this function during future NLSF sessions. To learn more about defining a new fitting function in the NLSF, search on “defining a new function” in the Origin Help file (Help:Origin).

Note: There are two advantages to defining your function in Code Builder: you can call your function from outside the NLSF (for example, from a LabTalk script file or from the Script window) and (2) when you define the function in Code Builder, you have access to Code Builder's debugging tools.

  • You can also define and compile an expression for setting the values of a matrix in the Set Matrix Values dialog box. This dialog box includes a "Compile as Origin C and Treat x^y as pow(x,y)" check box to compile the code before use. After you enter an expression, select this check box, and then click OK, if any compiler errors are encountered they are output to the Script window.

Other than the two exceptions above, Origin C functions are called by issuing LabTalk commands inside Origin from anywhere LabTalk statements can normally be executed (including the Code Builder LabTalk Console, the Origin Script window, label buttons, graphic objects, toolbar buttons, LabTalk script files, etc.).

All example code for the following sections is contained in the CallingOCFromLabTalkEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Calling Origin C Functions Using LabTalk

Once an Origin C function has been added to the Code Builder workspace, compiled, and linked, it can be accessed in Origin by executing a LabTalk statement that calls the function. The general syntax for calling an Origin C function from LabTalk is:

funcName(arguments);

or, if the Origin C function returns a value, the syntax is:

varName = funcName(arguments);

When "funcName(arguments);" is passed to the LabTalk interpreter, the interpreter will check if funcName is a compiled Origin C function. If it is, the Origin C function will be executed.

For example, if an Origin C function has the prototype:

void doc(string str, int nn)

It could be called using the following LabTalk statement:

doc(%H, 3);

In addition to the general syntax, Origin C functions can also be called using the following LabTalk syntax (omitting the parentheses):

funcName arguments;

For example, the same doc function above could also be called using the LabTalk statement:

doc %H 3;

The example functions in the sections that follow are also contained in the Origin C source file CallingOCFromLabTalkEx.c and can be found in the \Samples\Programming\Origin C Files subfolder of Origin.


Passing Arguments to Origin C Functions

While Origin C functions accessible from LabTalk may contain any of the argument types previously listed, LabTalk itself only supports variables of type double and string. Should the type of a LabTalk value or variable not exactly match the type of the Origin C variable to which it is passed then the value/variable is converted (by casting not by rounding) to the type of the Origin C argument. For example, if the formal parameter type of an argument in an Origin C function is int then the value of a LabTalk numeric variable (e.g. a double) that is passed to this function argument will be converted to an int. For example, if the following Origin C function

// Casting of Arguments

void PrintNumeric(int ii)

{

printf("The number is %d", ii);

}

is called using the LabTalk statement

PrintNumeric(5.7);

it will output

The number is 5

If an Origin C function accepts one or more numeric arguments and returns a numeric argument, Origin will automatically call the function once for element in an input data set if the input data set is passed in to the numeric argument. The results can then be returned to a data set. This mechanism was implemented so that Origin C functions would emulate a LabTalk function’s ability to work with either scalar or vector arguments. It is recommended that data sets only be passed to numeric Origin C arguments of type double. For example, if the following Origin C function

// Operating on Scalars and Vectors

double CallOnceForeachElement(double a, double b)

{

return a + b;

}

is called using the LabTalk statement

col(1)=3*CallOnceForeachElement(col(2),col(3));

the function will execute once for each element in column 2, will pass corresponding values of column 3 for the second argument, and will assign the results to the corresponding values of column 1.

If an Origin C function accepts a string variable as an argument how LabTalk handles the string depends on whether or not the string is surrounded by quotation marks in the function call. If the string is surrounded by quotation marks, then it is considered to be an Origin C string literal (constant). Otherwise, it is considered to be a LabTalk string variable or an object string property. In the latter case, the string variable or object string property is first evaluated by the LabTalk interpreter and replaced with the string value that it represents. For example, if the following Origin C function

// Passing Strings with and without Substitution

void PassString(string str)

{

printf("The string is \"%s\"\n", str);

}

is called using the LabTalk statement

PassString(%C);

it will output

The string is "Data1_B"

assuming Data1_B is the active data set in Origin (the LabTalk string variable %C evaluates to the name of the active data set). Whereas the LabTalk statement:

PassString("%C");

will output

The string is "%C"

In addition to LabTalk string variables, you can also pass LabTalk string object properties to Origin C functions. For example, the LabTalk statement

PassString(nlsf.y$);

will also output

The string is "Data1_B"

Assuming Data1_B is the data set assigned to this object property.

If an Origin C function will sometimes be used to operate on scalars and will sometimes be used to operate on data sets then the function should contain scalar arguments of type double (see the section above Operating on Scalars and Vectors). However, if the function will always be used to operate on a data set (vector) then the function should accept a reference to a vector as its input argument causing the function to be invoked once rather than once for each element. For example, if the following Origin C function

// Passing Vectors by Reference

vector PassVectorByReference(vector& vIn, double f)

{

return (vIn * f);

}

is called using the LabTalk statement

Data1_A=PassVectorByReference(Data1_B,3);

the function will execute exactly once and will multiply all values in the data set Data1_B by 3 and return the results to the Data1_A data set. The Origin data sets must have either a Text & Numeric or Numeric format.

If an Origin C function is to be used to operate on a text data set the entire text data set can be passed in as a vector of strings. For example, if the following Origin C function

// Passing an Array of Strings

vector PassArrayOfStrings(vector<string> vIn)

{

vector vOut(vIn.GetSize());

for(int ii = 0; ii < vIn.GetSize(); ii++)

vOut[ii] = vIn[ii].GetLength();

return vOut;

}

is called using the LabTalk statement

Data1_A=PassArrayOfStrings(Data1_B);

the function will execute exactly once and will accept the entire text data set Data1_B as input and will return the length of each element in Data1_B to the Data1_A data set. The input Origin data set must have either a Text & Numeric or Text format.

Passing Arguments to Origin C Functions

While Origin C supports many basic data types LabTalk only supports variables of type double and string. However, LabTalk values of many types can be passed to and accepted in return from Origin C functions as long as the function is accessible from LabTalk. Values of different types are always cast from (or to) the LabTalk type of double or string to (or from) the data type of the matched Origin C argument. In order for an Origin C function to be accessible from LabTalk, it must contain only the following numeric and string argument types: char, short, WORD, int, DWORD, float, double, and string. All of the preceding types can be passed either by value or by reference. In addition, vectors of doubles can be passed by reference (only) and vectors of strings can be passed by value (only). Origin C functions containing any other argument types will not be accessible from LabTalk. See the section Listing the Origin C Functions that Can be Called From LabTalk for information on how to list Origin C functions that are accessible from LabTalk.

The following sections discuss these and related issues in more detail. The example code for the following sections is also contained in the CallingOCFromLabTalkEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.

Casting of Arguments

Operating on Scalars and Vectors

Passing Strings With and Without Substitution

Passing Vectors by Reference

Passing an Array of Strings


Returning a String to LabTalk

LabTalk supports Origin C functions that return void, numeric, vector, or string. If the Origin C function has a return value of type string, the LabTalk call to this function must always terminate with the dollar sign character ($). For example, if the following Origin C function (which returns a text error message based on an input error code)

// Returning a String

string GetErrorMessage(int iErrorCode)

{

string str;

str.Format("Error message %d", iErrorCode);

return str;

}

is called using the LabTalk statements

%A=GetErrorMessage(111)$;

%A=;

the error message will output as

Error message 111

The example function above is also contained in the CallingOCFromLabTalkEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Returning a Vector to LabTalk

An Origin C function may return a vector to the LabTalk statement invoking the function. In this case the LabTalk call to the Origin C function should assign the Origin C function's return value to an Origin data set. Thus, if the Origin C function prototype is

vector myFunc(parameterList)

the following LabTalk call to this compiled function will assign the return value (a vector) to the Data1_B data set.

Data1_B=myFunc(argumentList);

For example, if the following Origin C function

// Returning a Vector

vector ReturnAVector(double f)

{

vector vData = {0, 1, 2, 3, 4};

return (vData * f);

}

is called using the LabTalk statement

Data1_A=ReturnAVector(3);

the function will execute and assign a returned vector to the Origin data set Data1_A. The returned vector contains the first five multiples of the input argument f. The example function above is also contained in the CallingOCFromLabTalkEx.c source file found in the \Samples\Programming\Origin C Files subfolder of Origin.


Calling Global Origin C Functions from LabTalk

Like user-defined Origin C functions, you can call global Origin C functions from LabTalk if the following conditions are met:

  • The function has been defined in Origin C and compiled. Thus, global Origin C functions that are prototyped - but have no function body - cannot be called. NAG functions fall into this category and thus cannot be called from LabTalk (only from Origin C).

  • All arguments must be numeric or string.

  • The return type can be void, numeric, string, or vector.

  • Overloaded functions cannot be called from LabTalk; they can only be called from other Origin C functions.


Listing Origin C Functions that Can be Called From LabTalk

To list the Origin C functions that can be called from LabTalk, use the LabTalk list command as follows:

list f; // list all Origin C funcs callable from LabTalk

list fs; // list only those returning string

list fv; // list only those returning vector

list fn; // list only those returning numeric

list fo; // list only those returning void

To show the function prototype in the listing, use 'cf' in place of 'f'. For example, use:

list cf;

list cfs;

etc.

To restrict LabTalk function calls to only LabTalk functions (excluding Origin C functions), modify the value of the @OC LabTalk system variable.

@OC = 1 (default), allows calling of Origin C functions from LabTalk

@OC = 0, disallows calling of Origin C functions from LabTalk

The @OC system variable setting also effects the function listing with the list command.


Precedence Rules When a LabTalk and Origin C Function Have the Same Name

When a user-defined or global Origin C function has the same name as a built-in LabTalk function, the Origin C function has higher precedence, except when using LabTalk vector notation. Thus, LabTalk functions like Normal and Data (which return a range of values and are thus used in vector notation) would be higher precedence than Origin C functions of the same name. In all other cases, the Origin C function is called.


Label Buttons

Label buttons are a unique and powerful feature in Origin. A label button is a label (such as an arrow, a text label, a rectangle, or a pasted image) that is associated with an Origin C function or a LabTalk script. When you move, resize, click on, or otherwise manipulate the button, Origin executes the associated function or script.

This section shows how label buttons work, how to copy a label button from one graph window and paste it into a second, and how to edit and create new label buttons. Finally, this chapter demonstrates how to call an Origin C function from a label button and how to call a section of LabTalk script stored in a text file (of type *.OGS).

Note: Label buttons do not appear in printouts.


Copy and Paste a Button

Copying and Pasting a Button

This section demonstrates how buttons work, how to edit the properties of a button, and how to copy/paste a button from one Origin window to another.

Copying a Button to the Clipboard

  1. Select File:Open. This menu command opens the Open dialog box.

  2. Browse to and open the Origin sample project file CopyPasteButton.opj in the \Samples\Programming\User Interface Development subfolder of Origin.

  3. In Graph1 click the Increment Plot Color button several times. The color of the data plot will cycle through the first few colors in the Origin color list.

  4. Select Edit:Button Edit Mode. This menu command is checked when in Button Edit Mode. When in Button Edit Mode, buttons are no longer "active" (cannot be executed) and they can be selected, copied, and edited.

  5. Click on the Increment Plot Color button to select it.

  6. Click the Copy button [image] on the Edit toolbar. The button is copied to the Clipboard.

Pasting a Button into a New Graph Window

  1. Click anywhere in the Graph2 window to activate the Graph2 window and to establish the paste destination.

  2. Click the Paste button [image] on the Edit toolbar. The button pastes into the new graph window. The button is not yet active, though, because you are still in Button Edit Mode.

Exiting Button Edit Mode

  1. Select Edit:Button Edit Mode to exit the editing mode.

The Increment Plot Color button in the Graph2 window is now activated. If you click on it, the color of the data plot in the Graph2 window will now increment.


Creating a Button

Buttons can be created from any label. In the following example, you create a button from a text label and program the button to open a dialog box containing the message “Hello World!”.

Creating the Text Label

  1. Click the New Graph button [image] on the Standard toolbar to open a new graph window.

  2. Open the Tools toolbar by selecting View:Toolbars. Select the Toolbars check box and click Close.

  3. Select the Text tool [image] from the Tools toolbar.

  4. Click in a blank area of the graph window. This action adds a text label to the graph and enters In-Place Editing mode for the text label.

  5. Type Hello in the text box and then click outside the text box to exit In-Place Editing mode.

Changing the Label into a Button

  1. Select Edit:Button Edit Mode to enter Button Edit Mode. This menu command is checked when in Button Edit Mode.

  2. Click once on the Hello text label to select it. From the menu, select Format:Label Control. This menu command opens the associated Label Control dialog box.

  3. Click in the large text box at the bottom of the dialog box and type in the following text (this is the script for the control):

type -b "Hello World!";

Selecting the Script Execution Option

  1. Select Button Up from the Script, Run After drop-down list. The Button Up option informs Origin that the script is to be executed when the button is clicked.

Each of the options from the Script, Run After drop-down list establish a different event for script execution. For example, you would select Moved to execute the associated script when the text label is moved.

  2. Click OK to close the dialog box. If you are in Button Edit Mode, select Edit:Button Edit Mode to exit the editing mode. The Hello text label now displays on your screen as a button. When you click the button, an attention dialog box opens and displays “Hello World!”.

  3. Click OK to clear the Attention dialog box from the screen.

For reference information on the Label Control dialog box see the section Associating LabTalk Script with an Object in the Origin Help file. For reference information on setting properties of a text label object see the section Creating and Editing Text Labels in the Origin Help file. For reference information on setting properties of a graphic object see the section Editing Objects in the Origin Help file.

For reference information on programmatically controlling label objects see the GraphObject class in the Origin C Language Reference or see the Label and Draw commands and the section User-created Visual Objects in the LabTalk Language Reference section of this Help file.


Calling an Origin C Function from a Label Button

This section demonstrates how to call an Origin C function from a label button.

Calling an Origin C function.

  1. Click the Open button [image] on Origin’s Standard toolbar. Browse to and open the Origin sample project file CallExternalCode.opj in the \Samples\Programming\User Interface Development subfolder of Origin.

  2. Click the Code Builder button [image] on Origin’s Standard toolbar.

  3. In the Code Builder Workspace window expand the [+] next to the Project folder and then double-click on the file CallOCFunction.C to open it. Note the name of the Origin C function called by the Call OC Function PlotData label button is PlotData.

In this example the source file containing the function PlotData happens to be in the Project folder of the Code Builder workspace but this is not required. The source file containing a called function may be in any folder of the Code Builder workspace and exist as a separate file outside the Origin project file as long as it is properly compiled and linked at the time the label button is clicked. To learn more about compiling and linking Origin C source files, see Compiling, Linking and Loading.

Editing and Clicking the Label Button.

Holding down the ALT keyboard key while double-clicking on an active label button opens the button’s Label Control dialog box.

  1. Hold down the ALT keyboard key and double-click on the Call OC Function PlotData button to open its Label Control dialog box. Note the Origin C function PlotData is called from inside the Label Control dialog box.

  2. Click Cancel to close the Label Control dialog box without making any changes.

  3. Click the Call OC Function PlotData button to execute the Origin C function PlotData. The function PlotData runs and plots the data in the Expdecay worksheet into Graph1.

Calling an Origin C function from a label button is equivalent to calling an Origin C function from LabTalk (i.e. from the Script Window, from the LabTalk Console, or from a text file).


Calling LabTalk Script from a Label Button

This section demonstrates how to call a section of LabTalk script from a label button.

Calling a section of LabTalk script

  1. Click the Open button [image] on Origin’s Standard toolbar, browse to and open the Origin sample project file CallExternalCode.OPJ in the \Samples\Programming\User Interface Development subfolder of Origin.

  2. Click the Code Builder button [image] on Origin’s Standard toolbar.

  3. In the Code Builder Workspace window expand the [+] next to the Project folder and then double-click on the file MyFit.OGS to open it. Note the name of the LabTalk section called by the Run EXPDECAY1 Section in MyFit.OGS label button is EXPDECAY1 in the file MyFit.OGS.

In this example the text file containing the LabTalk script happens to be in the Project folder of the Code Builder workspace but this is not required. The text file containing the called section may be in any folder of the Code Builder workspace and may exist as a separate file outside the Origin project file as long as the file’s path is correctly specified in the run.section command.

Editing and Clicking the Label Button

In Button Edit Mode right-clicking on a label button and selecting Label Control from the shortcut menu opens the button’s Label Control dialog box.

  1. Select Edit:Button Edit Mode to enter Button Edit Mode. This menu command is checked when in Button Edit Mode.

  2. Right-click on the Run EXPDECAY1 Section in MyFit.OGS button and select Label Control from the shortcut menu. This menu command opens the associated Label Control dialog box. Note the LabTalk section EXPDECAY1 in the text file MyFit.OGS is called from inside the Label Control dialog box.

  3. Click Cancel to close the Label Control dialog box without making any changes.

  4. Select Edit:Button Edit Mode to exit Button Edit Mode. This menu command is unchecked when not in Button Edit Mode.

  5. Click the Run EXPDECAY1 Section in MyFit.OGS button to execute the EXPDECAY1 section of the text file MyFit.OGS. The LabTalk section runs and performs a non-linear curve fit on the data plotted in Graph2.

To learn more about calling sections of LabTalk script saved in text files, see the Run.Section method of the Run object in the LabTalk Language Reference section of this Help file.


Customizing Origin Menus

Origin provides great flexibility when customizing its menus. Origin menus can be modified using the LabTalk menu command and menu object. The following topics include an example in which an existing menu is modified, an example in which an entirely new menu is created, and an example in which an entire built-in menu is deleted. Once completed, menu customizations can be saved in an Origin configuration file (files of type *.CNF). Configuration files can be automatically executed when Origin starts and when menu levels are switched by selecting the Format:Menu menu item.

All example script for this section is contained in the configuration file CustomMenus.CNF and in the script file CustomMenus.OGS found in the Origin samples subfolder \Samples\Programming\User Interface Development. For reference information on the LabTalk menu command and the LabTalk menu object search the index of the Programming help file using the keywords “menu” and “object.”


Modifying an Existing Origin Menu

/////////////////////////////////////////////////////////////////////////
//
// Modifying an Existing Origin Menu
//
/////////////////////////////////////////////////////////////////////////

menu -w; // Activate Worksheet menu bar
menu ?St.1; // Activate Descriptive Statistics submenu on Statistics menu
menu.itemdel(4); // Delete Normality Test (4th) menu item on submenu
menu ?St; // Activate Statistics menu
menu -l -i 3 (&Non-Parametric Hypothesis Testing); // Insert submenu in 3rd position
menu (&Mann Whitney U-Test) {type -b Mann Whitney U-Test};
menu (&Wilcoxon Signed Rank Test) {type -b Wilcoxon Signed Rank Test}; // Append submenu menu items
menu -l; // Close submenu additions
menu ?St.4; // Activate ANOVA submenu on Statistics menu
menu -i 1 (&Repeated Measure ANOVA) {type -b Repeated Measure ANOVA}; // Insert menu item in 1st position
menu -i 2; // Insert menu separator in 2nd position of submenu
menu; // Append menu separator at end of submenu
menu (&MANOVA) {type -b MANOVA}; // Append menu item at end of submenu
menu ?St; // Activate Statistics menu
menu.itemdel(5); // Delete old Multiple Regression menu item on Statistics menu
menu -i 5 (New &Multiple Regression...) {type -b New Multiple Regression...} // Insert new menu item on Statistics menu

Modifying an Existing Origin Menu

Origin menus are window type sensitive. Stated another way, different menus and menu commands are available depending on which type of Origin child window is active. For example, when a worksheet or matrix window is active the Origin Plot menu is available but when a graph, function, or layout window is active the Plot menu disappears. The set of menus available when a particular type of Origin child window is active is known as a menu bar. While some methods of the LabTalk menu object operate on the menu ID of a menu item the LabTalk menu command and other methods of the menu object operate on the active menu of the active menu bar. Consequently, the first step when modifying Origin menus is to identify the active menu bar and the active menu on which the customization will take effect. Once the active menu bar and the active menu have been identified the menu customization can be completed by specifying the menu item position on the menu and the modification to be made.

For example, to insert a new menu item on the Plot menu of the Matrix menu bar you must first activate the Matrix menu bar by issuing the LabTalk command menu –m. Once the Matrix menu bar has been activated the Plot menu can be made active by issuing the command menu ?Pl (identifying the Plot menu by the first two letters of its name) or by issuing the command menu 4 (identifying the Plot menu by its forth position on the Matrix menu bar). Finally, a new menu item can be inserted in the third position of the Plot menu on the Matrix menu bar by issuing the command menu –i 3 (&Say Hello World) {type –b Hello World!} where menu –i 3 inserts a new menu command named Say Hello World (with a hot key S) that executes the LabTalk script type –b Hello World! The following example script demonstrates this procedure in more detail by customizing submenus and menu items on the Statistics menu of the Worksheet menu bar.

To execute the example script below copy the code into the Origin Script window, highlight the code, and then press ENTER. After executing the script, it is necessary to change the active window in Origin for menu modifications to take effect (Origin menus are window type sensitive and update every time the active window changes). In addition, since the script customizes the Worksheet menu bar the active window must be a worksheet to see the changes.

The above LabTalk script customizes the existing Origin Statistics menu. The Descriptive Statistics:Normality Test submenu item is removed (not shown), the Non-Parametric Hypothesis Testing submenu is created, the ANOVA submenu is modified, and the Multiple Regression menu item is replaced with the New Multiple Regression menu item.

The menu –l command is used to create the new Non-Parametric Hypothesis Testing submenu. All menu commands issued after the first menu –l command and before the second menu –l command effect the newly created submenu.

The ANOVA submenu was modified by inserting a Repeated Measure ANOVA menu item and a menu separator and by appending a second menu separator and a MANOVA menu item. The menu separators were added using the menu –i 2 and menu commands with no menu name or menu script arguments. Note the use of the command menu ?St.4 to activate the 4th menu (the ANOVA submenu) on the Statistics menu.

Finally, the Multiple Regression menu item was removed by using the menu.itemdel method of the menu object (menu.itemdel(5)) and then re-added using the menu –i command.


Adding a New Menu

/////////////////////////////////////////////////////////////////////////
//
// Creating a New Menu
//
/////////////////////////////////////////////////////////////////////////
menu -wmpgv;      //
 Activate all Origin menu bars
menu 3 (&GetData); // Create new GetData menu
//
 Add two new menu items and a separator
menu (Calibrate Remote &Transponder) {type -b Calibrate Remote Transponder};
menu (&Test Connection) {type -b Test Connection};
menu;
menu -l (Collect &Data); // Add a submenu with three menu items
menu (From &RS232c) {type -b From RS232c};
menu (From &Com) {type -b From Com};
menu (From &USB) {type -b From USB};
menu -l;         //
 Close submenu additions
menu;            //
 Add a separator
// Create an Uncheck Calibration menu item calling section of script
menu (&Uncheck Calibration) {run.section(CustomMenus.OGS,CheckCalibration)};
run.section(CustomMenus.OGS,InitCalibration); // Initialize LabTalk variables

[CheckCalibration]

// Script is executed only when menu item is selected

Calii=mod(Calii+1,2); // Toggle check mark

if(Calii) // If menu item needs to be checked

{

menu.rename(CheckId,(&Uncheck Calibration)); // Rename menu item

menu.check(CheckId,1); // Check menu item

}

else

{

menu.rename(CheckId,(&Check Calibration)); // Rename menu item

menu.check(CheckId,0); // Uncheck menu item

}

return 0;

[InitCalibration]

CheckId=menu.lastid; // Get menu id of Uncheck Calibration menu item

menu.check(CheckId,1); // Check menu item;

Calii=1; // Initialize LabTalk variable

return 0;

Adding a New Menu

In addition to modifying an existing Origin menu, an entirely new menu can be created. The following example adds to all Origin menu bars a new menu containing two menu items, a menu separator, a submenu with three menu items, another separator, and then one last menu item. The last menu item is checked by default and can be unchecked and checked again by repeatedly selecting it. The script that runs when the last menu item is selected is contained in a LabTalk script file of type *.OGS. LabTalk script that contains statements extending beyond one line can not be included in Origin configuration files of type *.CNF and must be moved to script files of type *.OGS. The script that checks and unchecks the menu item contains an if/else statement extending beyond one line and consequently is contained in a section of a script file (CustomMenus.OGS) which is called from inside the configuration file CustomMenus.CNF using the LabTalk run.section method. In some future version of Origin, menu items may also be enabled or disabled. See the menu.gray method of the menu object in the LabTalk Reference for updated information.

To run the following example, first copy the Origin sample script file \Samples\Programming\User Interface Development\CustomMenus.OGS into the main Origin software folder (the LabTalk run.section command supports pathing to Origin subfolders but this example requires the OGS file be in the Origin folder). Then copy/paste the script below into the Origin Script window, highlight the entire script, and press ENTER. Remember, if at first you do not see the new GetData menu, it is necessary to change the active window in Origin before menu modifications take effect.

The above LabTalk script creates a completely new custom menu named GetData. The menu –wmpgv command causes the GetData menu to be present on all Origin menu bars (w=worksheet, m=matrix, p=layout, g=graph, and v=no active window) and is shown below.

The menu –l command is used to create the Collect Data submenu. All menu commands issued after the first menu –l command and before the second menu –l command effect this submenu.

Selecting the checked Uncheck Calibration menu item above causes the following scripts to be executed. The scripts are called using the run.section commands contained in the last two lines of the Creating a New Menu example script above.

After the scripts run the last menu item becomes unchecked and is renamed Check Calibration. Selecting the menu item again and again repeats the process of checking/renaming and unchecking/renaming.


Removing an Entire Menu

The menu –r command can be used to remove an entire existing Origin menu or an entire user created menu. The following LabTalk script removes the Origin View menu from all Origin menu bars.

/////////////////////////////////////////////////////////////////////////

//

// Removing an Entire Menu

//

/////////////////////////////////////////////////////////////////////////

menu -wgmpv; // Activate all Origin menu bars

menu -r ?Vi; // Remove View menu from all Origin menu bars


Configuring Menus when Origin Starts

Origin is shipped with two built-in menu bar sets or menu levels named Full Menus and Short Menus. Full Menus is the default menu level and includes all Origin menus and menu items. Short Menus is a reduced menu level containing a minimal collection of Origin menus and menu items. Select Format:Menu:Short Menus and note how the Origin menus change. Then select Format:Menu:Full Menus to restore the default Origin menus. Toggling between Short Menus and Full Menus has the additional effect of removing all user initiated menu customizations. The Origin Format:Menu submenu as shipped in Origin is shown below.

As mentioned above, Origin comes with two built-in menu levels but it is possible to create and set as default a user defined menu bar set when Origin starts. To configure Origin’s menus at start up time simply place all desired menu modification commands in a configuration file (a text file having the file type *.CNF) and then modify the file Origin.INI as follows.

To configure Origin’s menus at start up time.

  1. Close Origin.

  2. Copy the Origin sample files CustomMenus.CNF and CustomMenus.OGS from the Origin samples subfolder \Samples\Programming\User Interface Development into the main Origin software folder.

  3. Locate the file Origin.INI located in the Origin User Files folder (if the path to your Origin User Files folder is not known type %Y= in the Origin Script window and press ENTER). Open the file Origin.INI in your User Files folder in a text editor such as Notepad and search for the lines below (less several lines of comments beginning with a ; and other unrelated lines).

NumLevels=2

Title1=Full Menus

File1=Macros FullMenu

Title2=Short Menus

File2=Macros Short

Level=1

  4. Modify the above lines as follows and re-save the Origin.INI file back into your User Files folder.

NumLevels=3

Title1=Full Menus

File1=Macros FullMenu

Title2=Short Menus

File2=Macros Short

Title3=Custom Menus

File3=Macros FullMenu CustomMenus

Level=3

  5. Restart Origin.

When Origin starts note the Statistics menu (requires an active worksheet window) has been modified, the custom GetData menu has been added, and the View menu has been removed. The modified Format:Menu submenu shown below includes the now active Custom Menus menu level.

To remove the Custom Menus menu level simply close Origin (first) and revert the changes made to the Origin.INI file in your User Files folder.

Note: In addition to executing configuration files (files of type *.CNF) at Origin start up time it is also possible to execute sections of LabTalk script at Origin start up time (contained in files of type *.OGS). Configuration files are more than adequate for most menu modifications but they do have the limitation that they are interpreted one line at a time which can sometimes complicate the execution of multi-line LabTalk statements. Executing sections of LabTalk script at start up time has no such restriction and should be considered for more complicated scripts. See the section Executing Script on Origin Events for more information.


Toolbar Buttons

Toolbar buttons provide a quick and easy method of customizing the Origin user interface to run tailor made Origin C functions and LabTalk scripts. Toolbar buttons can be added to any built-in Origin toolbar or to newly created user-defined toolbars. Once created, a toolbar can be opened, closed, docked, or floated. The availability of a toolbar button can be programmed to be window type dependent. Most importantly, the Origin C function or LabTalk script associated with a toolbar button can be executed with the single click of a button!

Toolbars and toolbar buttons are created and modified on the Button Groups tab of the Customize Toolbar dialog box. Select View:Toolbars from the Origin main menu and then click on the Button Groups tab. For reference information on the Customize Toolbar dialog box see the section The Customize Toolbar Dialog Box in the Origin Help file.

The following sections demonstrate how to create and program a toolbar containing two toolbar buttons. One button compiles, links, and executes an Origin C function and the other runs a section of a LabTalk script. Once finished, the toolbar is packed in an Origin *.OPK file which can then be distributed to other Origin users for easy installation.


Creating a New Button Group

This section shows how to create a new Button Group that contains two toolbar buttons.

To create a new Button Group:

  1. Select View:Toolbars from the Origin menu and then select the Button Groups tab of the Customize Toolbar dialog box.

  2. Click the New... button at the bottom of the dialog box to open the Create Button Group dialog box.

  3. Enter MyGroup for Group Name and select 2 for Number of Buttons. Click the Browse button and then browse to and open the file MyGroup.bmp in the \Samples\Programming\User Interface Development subfolder of Origin. The file MyGroup.bmp is a 16 color bitmap containing a 16 x 32 block of pixels (precisely enough for two toolbar buttons).

The selected bitmap must be a 16 color bitmap and each button must be represented by a 16 x 16 block of pixels from this bitmap (e.g. a ten button bitmap file would be 16 x 160 pixels and Origin will segment the bitmap to create the needed ten buttons). Bitmap files can be created using any bitmap editor such as the Window’s Paint program.

  4. Click OK to close the Create Button Group dialog box and to open a Save As dialog box for saving an INI file for the new Button Group’s settings. Browse to and save the Button Group’s INI file named MyGroup.INI in the \Samples\Programming\User Interface Development subfolder of Origin.

You have now created a new Button Group containing two toolbar buttons. The Button Group MyGroup should now appear at the bottom of the Groups list box and once selected two buttons should appear in the Buttons group. In the next section you will see how to program the buttons in the new Button Group and how to create a new toolbar from those buttons.


Programming Buttons and Creating a New Toolbar

This section continues the previous section and shows how to program the buttons in a Button Group and how to create a new toolbar.

To program the toolbar buttons:

  1. Activate the Button Groups tab of the Customize Toolbar dialog box and select the group MyGroup from the Groups list box.

  2. In the Buttons group select (click once to depress it) the leftmost button that looks like a gear or the Code Builder button.

  3. Click the Settings… button in the Button group to open the Button Settings dialog box. Click the Browse button and browse to and open the file MyGroup.OGS in the \Samples\Programming\User Interface Development subfolder of Origin.

  4. Enter ExecuteOCFunction for Section Name and enter Execute an Origin C function for Tool Tip Text and Status Bar. Click OK to save these settings for the leftmost button.

  5. Repeat steps 2 through 4 for the right most button in the Button Group MyGroup but this time enter ExecuteLabTalkSection for Section Name, and enter Execute a LabTalk section for Tool Tip Text and Status Bar. Click OK to save these settings for the rightmost button.

Both buttons actually execute a section of LabTalk script but the section called by the leftmost button programmatically compiles and links an Origin C source file and then calls an Origin C function in that source file.

To create the toolbar:

  1. Activate the Button Groups tab of the Customize Toolbar dialog box and select the group MyGroup from the Groups list box.

  2. In the Buttons group select (click once to depress it) the leftmost button that looks like a gear or the Code Builder button and drag it into the Origin workspace. A toolbar with the one button is newly created.

  3. Repeat step 2 for the rightmost button but drag it onto the newly created toolbar to the right of the first button. The toolbar now has two buttons.

  4. Select the Toolbars tab in the Customize Toolbar dialog box and then select the last toolbar in the Toolbars list box having a name similar to Toolbar1. Enter MyGroup for Toolbar name and then click the Close button.

The MyGroup toolbar is now complete and ready to use (see below). The next sections demonstrate the use of the MyGroup toolbar and describe the process by which a toolbar can be packed and sent to other Origin users for easy installation.


Using the MyGroup Toolbar and Buttons

[ExecuteOCFunction]

// Compile and link source file ProgressBox.c

%A="..\Samples\Programming\";

%B="User Interface Development\ProgressBox.C";

if( run.LoadOC(%A%B) != 0 )

{

type -b "ProgressBox.C failed to load.";

return 1;

}

// Execute Origin C Progress function

Progress(0,20);

return 0;

Using the MyGroup Toolbar and Buttons

This section continues the previous section and shows what happens when you click the toolbar buttons.

To use the toolbar buttons:

  1. Click the Code Builder button [image] on Origin’s Standard toolbar to open Code Builder.

  2. Click the Open button [image] on Code Builder’s Standard toolbar and then browse to and open the file MyGroup.OGS in the \Samples\Programming\User Interface Development subfolder of Origin.

  3. Click the Open button [image] on Code Builder’s Standard toolbar again and this time browse to and open the file ProgressBox.c also in the \Samples\Programming\User Interface Development subfolder of Origin.

The section of LabTalk script in the file MyGroup.OGS identified by the text [ExecuteOCFunction] is the section that is executed when the leftmost button on the MyGroup toolbar is clicked.

  4. In Origin position and hold the mouse cursor over the leftmost button on the MyGroup toolbar. The text Execute an Origin C function displays as balloon help and on the Origin Status Bar.

  5. Now click the leftmost button on the MyGroup toolbar. The section of LabTalk script below residing in the file MyGroup.OGS is executed.

The run.LoadOC command compiles and links the source file ProgressBox.c and returns with an error message if there are any compilation problems. Otherwise, the Origin C function Progress residing in ProgressBox.c is executed. A progress dialog box is open in Origin.

  6. In Origin position and hold the mouse cursor over the rightmost button on the MyGroup toolbar. The text Execute a LabTalk section displays as balloon help and on the Origin Status Bar.

  7. Now click the rightmost button on the MyGroup toolbar. The section of LabTalk script below also residing in the file MyGroup.OGS is executed.

[ExecuteLabTalkSection]

// Execute script

type -b "Execute a section of LabTalk script";

return 0;

The script executes and a message box is opened in Origin. The next section demonstrates how to pack and send a user defined toolbar to other Origin users for easy installation.


Distributing Toolbars

This section continues the previous section and shows how toolbars can be packed and sent to other Origin users for easy installation.

To pack the toolbar:

  1. Select View:Toolbars from the Origin menu and then select the Button Groups tab of the Customize Toolbar dialog box.

  2. On the Button Groups tab of the Customize Toolbar dialog box select the group MyGroup from the Groups list box.

  3. Click the Export… button in the Button Group group to open the Export Button Group dialog box shown below. The dialog box automatically includes all files required by the toolbar (the INI file holding the toolbar settings, the bitmap file holding the button images, and any specified LabTalk script files) but other source files must be explicitly added.

  4. Click the Add File… button and then browse to and open the file ProgressBox.c in the \Samples\Programming\User Interface Development subfolder of Origin.

  5. Click the Export… button and save the packed files as MyGroup.OPK somewhere on your computer for easy retrieval.

The pathing of files packed in the *.OPK file that reside in the Origin folder (or a subfolder of Origin) will be relative to the Origin folder thereby facilitating installation to other Origin folders not having the same pathing as your installation. The file MyGroup.OPK can then be distributed to any Origin user for installation.

To install the toolbar:

  1. On the Button Groups tab of the Customize Toolbar dialog box select the group MyGroup from the Groups list box and then press the Delete button.

  2. On the Toolbars tab of the Customize Toolbar dialog box select the MyGroup toolbar and press the Delete button.

Both the MyGroup Button Group and the MyGroup toolbar must be deleted from your installation of Origin to simulate installing the toolbar in an installation of Origin not previously containing the toolbar.

  3. Close the Customize Toolbar dialog box. Locate the file MyGroup.OPK created above using Window Explorer and drag the file into the Origin workspace.

  4. Select Replace All and click OK in the OPack dialog box to overwrite existing source files (the button group and toolbar were deleted in steps 1 and 2 above but the source files were not deleted).

  5. Click OK twice to close information messages related to installing the button group and toolbar.

A button group and a toolbar named MyGroup is unpacked, installed into your installation of Origin, and ready for immediate use. See the section Sharing Origin Files in the Origin help file for more information on other methods of distributing Origin files. See also the section Origin Pack Files in this help file.


Wait Cursors and Progress Boxes

Whenever a program user takes some action, it is a good idea to provide some kind of feedback to the user. If you create code that takes a while to execute, you should provide some indication that the code is running.

This section demonstrates three standard techniques – varying the mouse pointer, using output messages, and showing a progress box – for providing user feedback during program execution. See the Programming tutorial Programming Cues to Enhance User-Friendliness for an additional example.


The Wait Cursor

// Set the Mouse Pointer to 'Busy' while long process continues

void BusyAsABee()

{

// Create a Worksheet object from the active window

Worksheet wks = Project.ActiveLayer();

// If the active window is not a worksheet, create one from ORIGIN.OTW

if(wks==NULL)

{

wks.Create("origin", CREATE_VISIBLE);

}

waitCursor cur; // waitCursor object

string str; // String for messages

int nCol = 0; // int holds number of columns added

// Loop : 1000 times, but check for user pressing Escape key

for(int ii = 0; ii < 1000 && !cur.CheckEsc(); ii++)

{

// Add a column to the worksheet

wks.AddCol();

// Type a message to the Data Display window and increment column count

str.Format("Adding col %d", nCol++);

SetDataDisplayText(str);

}

// Check if the loop completed normally, otherwise the user must have pressed

// Escape key

if(ii < 1000)

printf("User aborted adding columns. %d columns were added.\n", nCol);

}

The Wait Cursor

One standard Windows technique is to change the mouse cursor to a Busy cursor while a program is running. Typically, this is an hourglass, but the cursor can be customized on most systems. The Busy cursor will appear over the application that created it until the application changes it back to the Normal Select cursor.

You can invoke this cursor in Origin C by declaring a waitCursor object.

To begin this example:

  1. In Origin click the Code Builder button [image] on the Standard toolbar.

  2. From the Code Builder menu, select File:Open, browse to the \Samples\Programming\User Interface Development folder and open WaitCursor.c

  3. To add this file to the workspace, activate the window in the Code Builder MDI and select the File:Add to Workspace menu item.

  4. Click the Build button [image]. The Output window reports Done! when the compile successfully completes.

  5. Return to the Origin workspace and open a new project file (click the New Project button [image]).

  6. Open the Script window (select the Window:Script Window menu item) and type the following:

BusyAsABee()

  7. Press ENTER. The BusyAsABee function executes.

Origin will add columns to the active worksheet until 1000 columns have been added or you press the Escape key. While the program is executing, the mouse pointer will display the Busy cursor over Origin, and a message is displayed in the Data Display window indicating the current new column.


The Progress Box

// Display a Progress Box

void Progress(int iBegin, int iEnd)

{

int iStep = 0;

BOOL bOK = 0;

DWORD dw1 = 0;

DWORD dw2 = 0;

int iDone = 0;

int iTemp;

// Display the progress box

progressBox pbox("Working...", 0);

// Swap the arguments if the first is larger

if(iBegin > iEnd)

{

iTemp = iBegin;

iBegin = iEnd;

iEnd = iTemp;

}

// Set the range

pbox.SetRange(iBegin, iEnd);

// Get the system tick count (in milliseconds)

dw2 = GetTickCount();

// Loop from the first number to the last

for(iStep = iBegin; iStep <= iEnd; iStep++)

{

// Wait 1 second - This function is defined in this file

WaitASec(1.0);

// Set the progress indicator to the next value

bOK = pbox.Set(iStep);

// If the user pressed escape or clicked Cancel, then terminate the loop

if(!bOK)

{

printf("Progress Box terminated by user.\n");

return;

}

}

}

// Delay a specified number of seconds

void WaitASec(double dSeconds)

{

DWORD dw1;

DWORD dw2;

int iDone;

dw1 = GetTickCount();

dw2 = dw1;

for(iDone = 0; iDone==0; )

{

if((dw2 - dw1) < dSeconds * 1000.0)

dw2 = GetTickCount();

else

iDone = 1;

}

}

The Progress Box

Another programming technique that can be particularly useful when you know how many steps you will take – but you don’t know how much time each step will take to execute – is to provide a progress box to indicate a percent of completion. You can use Origin C to display a progress box while your program executes, and update the progress indicator as needed.

To begin this example:

  1. In Origin click the Code Builder button [image] on the Standard toolbar.

  2. From the Code Builder menu, select File:Open, browse to the \Samples\Programming\User Interface Development folder and open ProgressBox.c.

  3. To add this file to the workspace, activate its window in the Code Builder MDI and select the File:Add to Workspace menu item.

  4. Click the Build button [image] on the Code Builder Standard toolbar. The Output window reports Done! when the compile successfully completes.

  5. Return to the Origin workspace and open a new project (select the File:New… menu item and select Project).

  6. Open the Script window (select the Window:Script Window menu item in Origin) and type the following:

Progress(100,0)

  7. Press ENTER. The Progress function executes.

A progress box will display with a bar and number indicating percent of task completion. The percent is calculated automatically from the beginning, current, and end values. Pressing the Esc key or clicking the Cancel button will close the box after the current step completes.


File Dialogs, Message Boxes, and Input Boxes

Origin C includes a number of global functions which can be used to open different types of user interface controls. Origin C global functions exist which create Open dialogs, Save As dialogs, and Modify Location dialogs as well as several variations of Message Boxes. In addition, an Input Box that accepts text input can easily be created. This section introduces these functions with three simple examples. For more detailed reference information see the User Interface Controls chapter in the Global Functions book of the Origin C Language Reference.


File Dialogs

void FileDialogEx()

{

string strPath;

StringArray saFiletypes;

saFiletypes.SetSize(3);

saFiletypes[0]="[Project (*.OPJ)] *.OPJ";

saFiletypes[1]="[Old version (*.ORG)] *.ORG";

saFiletypes[2]="[Worksheets (*.OGW)] *.OGW";

strPath = GetOpenBox(saFiletypes, "C:\\Program Files\\", "Untitled", "OpenOPJ");

if( !Project.Open(strPath) )

printf("The file chosen %s is not a valid Origin file.\n", strPath);

}

File Dialogs

File dialogs are used in Origin to enter or browse to and select Window’s folders and files for opening and saving. Origin C supports a number of different file dialogs each of which has its own purpose. An Open dialog is used for opening a single file, a MultiOpen dialog is used for simultaneously opening a multiple number of files, a Save As dialog is used for saving a file with a specified path and name, and a Modify Location dialog is used for selecting the path to a folder. Origin C includes an overloaded GetOpenBox function to open Open dialogs, an overloaded GetMultiOpenBox function to open MultiOpen dialogs, an overloaded GetSaveAsBox function to open SaveAs dialogs, and a BrowseGetPath function to select a path to a folder. The overloaded functions each take different arguments depending on how the Files of type combo box is populated. See the User Interface Controls chapter in the Global Functions book of the Origin C Language Reference for more information on function arguments.

The following example function specifies file types in a StringArray (a vector of strings) and then opens an Open dialog. If a valid Origin file is entered or browsed for and selected it is opened in Origin. Otherwise, the function terminates with a message. The example function is contained in the source file FileDialog.c and can be found in the \Samples\Programming\User Interface Development subfolder of Origin.

When executed the above function creates the dialog shown below.


Message Boxes

void MessageBoxEx()

{

int iRet;

string strMsg;

// This is an OK/Cancel message box with a question mark icon that

// is modal with respect to the active Origin window

iRet = MessageBox(GetWindow(), "Click OK to continue and Cancel to abort.",

"An OK/Cancel Message Box", MB_OKCANCEL | MB_ICONQUESTION);

if( IDOK == iRet )

strMsg = "You clicked OK.";

else

strMsg = "You clicked Cancel.";

// This is a modeless OK message box with no icon and a default title

iRet = MessageBox(NULL, strMsg);

}

Message Boxes

Message boxes are used to convey information to a program user and/or to present a program user with a limited number of operational choices. The information presented to the user is considered important enough to require the user’s attention before they are allowed to continue. The operational choices include such responses as OK, Cancel, Yes, No, Retry, Abort, etc. and can be specified by argument. A number of functions exist which can open message boxes the most powerful of which is the global function MessageBox. See the User Interface Controls chapter in the Global Functions book of the Origin C Language Reference for more information on the many possible arguments to the MessageBox function. See also the Write method of the string class and the out_str function in the Basic I/O chapter in the Global Functions book of the Origin C Language Reference for information on related functions.

The following example function opens an OK/Cancel message box. The dialog is modal to the tool or window that is active when the dialog is opened. Among many possible options the dialog contains a user specified title, an informational message, and a question mark icon. The return value of the MessageBox function indicates which button was used to close the dialog. The example function is contained in the source file MessageBox.c and can be found in the \Samples\Programming\User Interface Development subfolder of Origin.

When executed the above function creates the message box shown below.


Input Boxes

void InputBoxEx()

{

string strInput;

try

{

strInput = InputBox("Please enter your name:");

}

catch(int nErr)

{

printf("You clicked Cancel.\n");

return;

}

printf("You entered: %s\n", strInput);

}

Input Boxes

Input boxes are used to solicit textual information from program users. The global function InputBox is used to open an input box. See the User Interface Controls chapter in the Global Functions book of the Origin C Language Reference for more information on the InputBox function. See also the GetNBox function later in this chapter for information on a related function. The GetNBox function is nearly as easy to use as the InputBox function but it is much more powerful.

The following example function opens an input box dialog. If the Cancel button is clicked an Origin C run time error is generated and must be caught by a try/catch block. If the OK button is clicked program control proceeds as usual to the last statement of the example function. The example function is contained in the source file InputBox.c and can be found in the \Samples\Programming\User Interface Development subfolder of Origin.

When executed the above function creates the dialog shown below.


GetN Dialog Box

The GetN (Get Number) dialog box is a dynamically generated, easy to use, and powerful graphical user interface device. The GetN dialog box has two styles – a more traditional Box style and a Tree based style. The GetN dialog box supports user input from a variety of types of user specified interface controls, validates numeric input, and then directly stores entered values in a user defined tree structure. Values stored in the tree structure can be subsequently accessed by the calling program. Display options such as dialog gridding, branch and node label colors, and branching behavior can be specified. Row based event handlers can also be optionally specified. The GetN dialog box includes OK and Cancel buttons and optionally includes an Apply button. Event handling on user entry is also supported.

All example code for this section can be found in the Origin subfolder:

\Samples\Programming\User Interface Development

To execute any of the example functions in this section, add the file having the same name as the function to the Code Builder workspace, rebuild the workspace, and then enter the name of the desired function in the Script window or LabTalk Console. When creating functions that use a GetN dialog box the system header files Origin.h and GetNBox.h must be included in your source file. See the header files Origin.h and GetNBox.h or the Origin C Language Reference for more information.


Core Concept

void CoreConcept()

{

// Use GETN_BOX macro to declare a tree for a Box style GetN dialog

GETN_BOX(tr)

// Use macro to add a checkbox node named UpperCase having caption

// "Upper Case" initialized to false (unchecked)

GETN_CHECK(UpperCase, "Upper Case", false)

// Use macro to add a string edit box node named InputText having

// caption "Enter Text" initialized to text value "Some sample text"

GETN_STR(InputText, "Enter Text", "Some sample text")

// Output GetNBox tree before editing input defaults

out_tree(tr);

// Open GetNBox dialog and edit input defaults passing GetN tree named tr

// and having dialog title "Get Text"

if( GetNBox(tr, "Get Text") ) // If user clicks OK button GetNBox function returns true

{

// Directly evaluate and manipulate GetN tree values

if( tr.UpperCase.nVal ) // If checkbox is checked

tr.InputText.strVal.MakeUpper(); // Upper case string value

}

// Else if user clicks Cancel button GetNBox function returns false so do nothing

// Output GetNBox tree after editing inputs in dialog and upper casing

out_tree(tr);

}

Core Concept

The GetN dialog box is easy to use. To create a GetN dialog box all that is needed is to define an Origin C Tree structure and then pass it as an argument to an Origin C function named GetNBox. The tree itself and the nodes of the tree are declared and initialized by calling one of several predefined Origin C macros. Use the GETN_BOX macro to declare a tree that causes a Box style dialog to be created. Each subsequent macro declares a type of node in the tree and each type of node is associated with a particular type of user interface control. The user interface controls in a Box style GetN dialog consist of rows of boxes arranged in the order they are declared. The GetN tree is passed to the GetNBox function which opens the GetN dialog box and dynamically creates the associated user interface controls for each node in the declared tree.

The example function CoreConcept declares a tree structure containing a checkbox node and a string edit box node and then passes it to the GetNBox function which creates a GetN dialog of Box style with a checkbox and a text edit box. The example function CoreConcept is contained in the source file CoreConcept.c and can be found in the \Samples\Programming\User Interface Development subfolder of Origin.

In the example above:

  1. The GETN_BOX macro declares an Origin C Tree object named tr to which two nodes are added. Note the use of the GETN_BOX macro causes a Box style GetN dialog to be created.

  2. The GETN_CHECK macro adds a tree node named UpperCase and specifies that a checkbox should be created.

  3. The GETN_STR macro adds a tree node named InputText and specifies that an edit box containing a string should be created.

  4. The tree is then passed to the function GetNBox along with the dialog title “Get Text” causing the GetN dialog box to open with the specified controls.

If the user clicks OK to close the dialog box the function GetNBox returns true and the outer most if block is entered. The node values of the GetN tree are directly evaluated and manipulated using methods and properties of the Origin C Tree class. The core concept of the GetN dialog box is that user input occurs via an Origin C Tree object in effect making the GetN dialog box a “tree editor.” Subsequently passing the edited tree to other functions becomes a convenient technique for easily collecting, storing, and operating on user input.


Using GETN Macros to Create a Dialog

Usage | Underlying Data Type | GetN Macro
Declare a Tree style GetN tree. | N/A | GETN_TREE(TreeName)
Declare a Box style GetN tree | N/A | GETN_Box(TreeName)
Group following nodes in branch.* | N/A | GETN_BEGIN_BRANCH(NodeName, Caption)
Group preceding nodes in branch.* | N/A | GETN_END_BRANCH(NodeName)
Add checkbox node. | bool (int) | GETN_CHECK(NodeName, Caption, DefaultValue)
Add numeric edit box node. | double | GETN_NUM(NodeName, Caption, DefaultValue)
Add numeric combobox node. | double | GETN_COMBO(NodeName, Caption, DefaultValue, ComboValues)
Add string list box node. | string | GETN_LIST(NodeName, Caption, DefaultValue, ListValues)
Add string edit box node. | string | GETN_STR(NodeName, Caption, DefaultValue)
Add string edit box with button node. | string with button | GETN_BUTTON(NodeName, Caption, DefaultValue)
Add color list combobox node. | Origin color (uint) | GETN_COLOR(NodeName, Caption, DefaultValue)

*  The begin and end branch macros (GETN_BEGIN_BRANCH and GETN_END_BRANCH) are only supported when creating a Tree style GetN dialog (e.g. when using the GETN_TREE macro to declare the GetN tree).

    • TreeName (not in quotes) is the name of the GetN tree associated with the dialog box.

    • NodeName (not in quotes) is the name of the tree node associated with the user interface control.

    • Caption (in double quotes) is the dialog caption for each user interface control.

    • DefaultValue is the default value initially displayed in each user interface control (possible values are dependent on the underlying data type).

    • ComboValues (in double quotes) is a list of numeric values separated by vertical bars.

    • ListValues (in double quotes) is a list of text values separated by vertical bars.

void UsingGetNMacros()

{

// Use GETN_TREE macro to declare a tree for a Tree style GetN dialog

GETN_TREE(tr)

// Add a string edit box node named WksName having caption "Worksheet Name"

// initialized to string value "Data1"

GETN_STR(WksName, "Worksheet Name", "Data1")

// Group following nodes in collapsible branch named Fit having caption

// "Fitting Options"

GETN_BEGIN_BRANCH(Fit, "Fitting Options")

// Use macro to add a checkbox node named ThroughZero having caption

// "Force Fit Line Through Zero" initialized to true (checked)

GETN_CHECK(ThroughZero, "Force Fit Line Through Zero", true)

// Add a numeric edit box node named YIntercept having caption "Y Intercept"

// initialized to numeric value 1.5

GETN_NUM(YIntercept, "Y Intercept", 1.5)

// Add non-editable drop down list box node named Order having caption

// "Polynomial Order" initialized to 2 with list values 2,3,4,5,6

GETN_COMBO(Order, "Polynomial Order", 2, "2|3|4|5|6")

// End nodes in collapsible branch

GETN_END_BRANCH(Fit)

// Add editable drop down combobox node named ColWidth having caption

// "Column Width" initialized to 5 with list values 1,2,5,10,20,30,50

GETN_COMBO(ColWidth, "Column Width", 5,"|1|2|5|10|20|30|50")

// Add non-editable drop down list box node named LineColor having caption

// "Fit Curve Color" initialized to blue with list values from the Origin color palette

GETN_COLOR(LineColor, "Fit Curve Color", 3)

// Add non-editable drop down list box node named Type having caption

// "Analysis Type" initialized to "Correlation" with list values "t-Test, Correlation," etc.

GETN_LIST(Type, "Analysis Type", 1, "t-Test|Correlation|NLSF|Polynomial Fit|Statistics")

// Output GetNBox tree before editing input defaults

out_tree(tr);

// Open GetNBox dialog and edit input defaults passing GetN tree named tr

// and having dialog title "Using GetN Macros" and dialog description "This is

// a GetN dialog"

if( GetNBox(tr, "Using GetN Macros", "This is a GetN dialog") )

out_tree(tr); // Output GetNBox tree after editing input defaults

}

In the example, the GETN macros are used to create an Origin C Tree structure named tr which contains a number of tree nodes. Some of the tree nodes are grouped together in a branch subnode named Fit having the caption “Fitting Options.” The different GetN macros add tree nodes having different underlying data types as described above. The GetN tree tr is then passed to the GetNBox function opening a dialog and causing a user interface control to be created for each node in the tree. The controls each have their own caption and are initialized with their own default values. The dialog title "Using GetN Macros" and the dialog description "This is a GetN dialog" are also passed to the GetNBox function as arguments. The resulting dialog box is shown below.

If the user clicks OK to close the dialog box the function GetNBox returns true and the out_tree global function is executed causing the edited node values in the GetN tree to be printed.

Using GETN Macros to Create a Dialog

The GetN dialog box supports a number of different types of user interface controls each of which has its own predefined Origin C macro. The GetN macros are similar to one another but take slightly different arguments depending on their usage and underlying data type. This table lists all GetN macros, their usage, and their underlying data types:

The GetN macros are used to create an Origin C Tree that is then passed as an argument to a function named GetNBox. The GetNBox function is a global Origin C function and is prototyped below.

bool GetNBox(TreeNode& trNode, LPCSTR lpcszTitle=NULL, LPCSTR lpcszDescription=NULL, PAPPLY_FUNC pfn = NULL, PEVENT_FUNC pEvtFn = NULL, HWND hWndParent = NULL);

The GetNBox function takes the following arguments:

  • A GetN tree as its first argument.

  • A dialog title as its second argument.

  • A dialog description as its third argument.

  • A pointer to an apply function as its fourth argument.

  • A pointer to an event handler function as its fifth argument.

  • A window handle to the dialog’s parent window as its sixth argument.

The GetNBox function returns a value of type bool equal to:

  • true when the dialog box is closed by clicking the OK button.

  • false when the dialog box is closed by clicking the Close or Cancel buttons.

The example function UsingGetNMacros illustrates the use of the GetN macros and the GetNBox function to create a sample GetN dialog box. Note the use of the GETN_TREE macro and the resulting Tree style dialog. The user interface controls in a Tree style GetN dialog consist of a tree with collapsible (and non-collapsible) branches arranged in the order they are declared. The dialog itself contains a number of different controls some of which are grouped in a branch subnode. All nodes are initialized with representative values. The example function UsingGetNMacros is contained in the source file UsingGetNMacros.c and can be found in the \Samples\Programming\User Interface Development subfolder of Origin.


Adding an Apply Button

// This function is executed when the Apply button is clicked

bool ApplyOnClick(TreeNode& tr)

{

out_str("\n-----from inside function ApplyOnClick");

out_tree(tr);

printf("The Y Intercept times 2 is %g.\n", tr.Fit.YIntercept.dVal * 2);

out_str("-----exit from ApplyOnClick\n");

return false;

}

Adding an Apply Button

Well designed tools allow users to change input values and execute the tool a number of times without having to re-open and initialize the tool each time. The GetN dialog box supports this feature by allowing developers to add an Apply button.

To add an Apply button to a GetN dialog box, simply pass a pointer to a function as the fourth argument to the GetNBox function. The GetNBox function dynamically adds an Apply button to the GetN dialog box and automatically executes the function whose pointer is passed when the Apply button is clicked. The Apply button function can have any name but must accept an Origin C Tree object as its only argument.

The Apply button function should return a value of type bool equal to:

  • true if the dialog needs to be refreshed (for example, if the Apply function changes the value of a control on the dialog).

  • false if the dialog does not need to be refreshed.

When the Apply button is clicked the current values entered in the GetN dialog box are saved in the GetN tree which is then passed to the Apply function defined by the developer.

The example function UsingGetNMacrosWithApply is a modified version of the UsingGetNMacros function in which the call to the GetNBox function has been replaced with the code below.

if( GetNBox(tr, "Using GetN Macros", "This is a GetN dialog with an Apply button", ApplyOnClick) )

out_tree(tr); // Output GetNBox tree after editing input defaults

The change above causes an Apply button to be added to the resulting GetN dialog box.

Clicking the Apply button will execute the ApplyOnClick function without closing the GetN dialog box. The function ApplyOnClick, also contained in UsingGetNMacrosWithApply.c, outputs the updated tree and performs a computation using one of the tree values each time the Apply button is clicked. After the Apply button is clicked, the OK button becomes disabled until a user interface control is changed and the Cancel button is renamed Close. Values displayed in the GetN dialog box can be changed and the Apply button can be clicked as many times as desired. The dialog box will remain open until the Close or OK button is clicked.

All example code for this section is contained in the UsingGetNMacrosWithApply.c source file found in the \Samples\Programming\User Interface Development subfolder of Origin.


Running Code when Users Change a Value

Type of Node | Macro Definition
Checkbox | TRGP_CHECK
Numeric edit box | TRGP_DOUBLE
Numeric combobox | TRGP_ENUM_COMBO
String edit box | TRGP_STR
String edit box with Button | TRGP_STR_BUTTON
String list box | TRGP_STR_LIST
Color list combobox | TRGP_COLOR

// This function is executed once for each type of control on the dialog when the

// dialog is first opened and is also executed when a value on the dialog is changed

bool DialogOnChangeEvent(TreeNode& tr, int nRow, int nType, Dialog& Dlg)

{

// Output GetN tree, nRow, and nType

out_tree(tr);

printf("nRow = %d nType = %d\n\n\n", nRow, nType);

if( nType != TRGP_CHECK && nType != TRGP_COLOR )

return false; // Return false to indicate no update of display is needed

if( TRGP_CHECK == nType ) // If checkbox node is changed

{

if( tr.Fit.ThroughZero.nVal )

tr.Fit.YIntercept.Show = false; // If checked hide Y Intercept

else

tr.Fit.YIntercept.Show = true; // Else unchecked so show Y Intercept

}

else if( TRGP_COLOR == nType ) // If colors list box node is changed

{

switch( tr.LineColor.nVal )

{

case 0:

tr.Type.Enable = false; // If black (0) disable Analysis Type

break;

case 3:

tr.Type.Enable = true; // Else enable Analysis Type

break;

default:

tr.Type.Enable = true;

break;

}

}

return true; // Return true to indicate update of display is needed

}

The event handler defined above hides the YIntercept edit box when the ThroughZero checkbox is checked and shows the YIntercept edit box when the ThroughZero checkbox is cleared. The event handler also disables the Analysis Type list box if the color Black (having Origin color index 0) is selected in the LineColor color list box and enables the Analysis Type list box if any other color is selected.

The event handler function DialogOnChangeEvent returns a value of true when a control in the dialog is shown, hidden, disabled, or enabled to force a refresh and returns false when no refresh is needed.

Running Code when Users Change a Value

It is sometimes useful to run code when users change a value in a dialog box. For example, a developer may want to hide, show, disable, or enable other controls on a dialog based on the changing value of a checkbox. The changing of a value in a dialog box is sometimes known as an event and the function or code that gets run when a value is changed is often known as an event handler. The GetN dialog box supports the running of code when a value in the dialog box is changed by allowing developers to specify an event handler function. To specify an event handler function for a GetN dialog box simply pass a pointer to a function as the fifth argument to the GetNBox function.

Each GetN dialog box may have one event handler function and if specified the event handler function is executed each time any value in the dialog box is changed. The GetN event handler function is also called once for each type of control on the dialog when the dialog is first opened (to allow for initialization). Since there is only one event handler function it must include logic specifying which code if any is to run when particular values in the dialog box are changed. The event handler function must have the prototype

bool FunctionName(TreeNode& tr, int nRow, int nType, Dialog& dlgGetN);

where FunctionName is the name of the event handler function and tr is a GetN tree holding the most recently changed dialog values. The argument nRow is normally the 0 based row index of the control whose value was changed except when the dialog is initializing its value is always –1. The argument nType is the type of node (see table below) in the GetN tree whose value was changed. The argument dlgGetN is a reference to the GetN dialog itself. The event handler function should return a value of type bool equal to true if the dialog needs to be refreshed (for example, if the event handler changes the value, usability, or visibility of a control on the dialog) and should return a value of false if the dialog does not need to be refreshed.

The example function UsingGetNMacrosWithEvent is a modified version of the UsingGetNMacros function in which the call to the GetNBox function has been replaced with the code below.

if( GetNBox(tr, "Using GetN Macros", "This is a GetN dialog with an event handler",

NULL, DialogOnChangeEvent) )

out_tree(tr); // If user clicks OK to close dialog Output edited GetNBox tree

The modifications above cause the event handler function DialogOnChangeEvent defined below to be called whenever a value in the GetN dialog box is changed. All example code for this section is contained in the UsingGetNMacrosWithEvent.c source file found in the \Samples\Programming\User Interface Development subfolder of Origin.


Adding Push Button Controls

void GetNStringButton()

{

// Use GETN_TREE macro to declare a tree for a Tree style GetN dialog

GETN_TREE(tr)

// Use macro to add a checkbox node named Save having caption

// "Save Temp Files" initialized to false (unchecked)

GETN_CHECK(Save, "Save Temp Files", false)

// Add a string edit box node named Path having caption "File Path",

// initialized to string value "C:\Temp", and having a push button

// that opens a browse dialog box

GETN_BUTTON(Path, "File Path", "C:\Temp")

// Open GetNBox dialog and edit input defaults passing GetN tree named tr,

// having dialog title "GetPath", and calling the event handler function

// DialogOnClickButtonEvent

if( GetNBox(tr, "Get Path", NULL, NULL, DialogOnClickButtonEvent) )

out_tree(tr);

}

// This function is executed once for each type of control on the dialog when the

// dialog is first opened and is also executed when a value on the dialog is changed

bool DialogOnClickButtonEvent(TreeNode& tr, int nRow, int nType, Dialog& Dlg)

{

if(TRGP_STR_BUTTON == nType) // If Browse button clicked then open browse dialog

{

string strPath = BrowseGetPath(tr.Path.strVal);

if( !strPath.IsEmpty() )

tr.Path.strVal = strPath;

}

else

tr.Path.Enable = tr.Save.nVal; // Else disable/enable browse button

return true; // Return true to indicate update of display is needed

}

Adding Push Button Controls

When collecting input it is sometimes convenient to allow users to select desired objects rather than having to enter information by keystroke. For example, an edit box control used to request the path to a file or folder could be set by typing in the path or by browsing to and selecting the file or folder using a Window’s like file open dialog box. The GetN dialog box supports this mechanism by pairing a string edit box control with a push button control. When the push button is clicked the GetN dialog triggers the dialog event handler function (see the Running Code when Users Change a Value section) which in turn can execute code that opens a file open or browse dialog. The example functions GetNStringButton and DialogOnClickButtonEvent below demonstrate this ability.

When the GetNStringButton function is executed the Get Path dialog box pictured above opens. Checking the Save Temp Files check box enables the File Path edit box. Click in the edit box and the "…" push button appears to the right. Clicking the "…” push button then triggers the DialogOnClickButtonEvent function which opens a Window’s like browse dialog box. When the user selects a folder and clicks OK in the browse dialog box the File Path edit box in the Get Path dialog updates accordingly. All example code for this section is contained in the GetNBoxWithStringButton.c source file found in the \Samples\Programming\User Interface Development subfolder of Origin.


Using GETN Option Macros

Usage | Can be Applied to | GetN Option Macro
Specify gridding option for dialog. | Root GetN Tree | GETN_OPTION_GRIDLINE(GridOption)
Specify label color of branch or node. | Branch or Node | GETN_OPTION_COLOR_LABEL(RGBValue)
Specify branching options. | Branch | GETN_OPTION_BRANCH(BranchOptions)
Specify row based event handler. | Node | GETN_OPTION_EVENT(EventHandler)

For the above macros:

    • GridOption is any VS Flex Grid gridding option including flexGridFlatVert (a flat vertical gridline) , flexGridInsetVert (an inset vertical gridline), or flexGridRaisedVert (a raised vertical gridline).

    • RGBValue is any valid RGB value including those generated using the RGB macro defined in the system header file mswin.h.

    • BranchOptions can be any combination of the bitwise predefined macros in the table below.

    • EventHandler is the name of an event handler function having the prototype

bool FunctionName(TreeNode& tr, int nRow, int nType, Dialog& dlgGetN);

where FunctionName is the name of the row based event handler function and tr is a GetN tree holding the most recently changed dialog values. The argument nRow is the 0 based row index of the control whose value was changed. The argument nType is the type of node in the GetN tree whose value was changed (see the node type table in the Running Code when Users Change a Value section above for a list of node types). The argument dlgGetN is a reference to the GetN dialog itself. The event handler function should return a value of type bool equal to true if the dialog needs to be refreshed (for example, if the event handler changes the value, usability, or visibility of a control on the dialog) and should return a value of false if the dialog does not need to be refreshed.

Branch Option | Causes
GETNBRANCH_OPEN | Branch to expand when dialog opens.
GETNBRANCH_KEEP_SIZE_ON_COLLAPSE | Dialog to not resize when branch is collapsed.
GETNBRANCH_KEEP_SIZE_ON_EXPAND | Dialog to not resize when branch is expanded.

void UsingGetNOptions()

{

// Use GETN_TREE macro to declare a tree for a Tree style GetN dialog

GETN_TREE(tr)

GETN_OPTION_GRIDLINE(flexGridRaisedVert) // Option to add vertical divider line

// Add a string edit box node named WksName having caption "Worksheet Name"

// initialized to string value "Data1"

GETN_STR(WksName, "Worksheet Name", "Data1")

GETN_OPTION_COLOR_LABEL(COLOR_RED) // Option to color node label red

// Group following nodes in collapsible branch named Fit having caption

// "Fitting Options"

GETN_BEGIN_BRANCH(Fit, "Fitting Options")

GETN_OPTION_COLOR_LABEL(COLOR_NAVY) // Option to color branch label navy blue

// Option to expand branch when dialog opens and to keep dialog same size when collapsing branch

GETN_OPTION_BRANCH(GETNBRANCH_OPEN | GETNBRANCH_KEEP_SIZE_ON_COLLAPSE)

// Use macro to add a checkbox node named ThroughZero having caption

// "Force Fit Line Through Zero" initialized to true (checked)

GETN_CHECK(ThroughZero, "Force Fit Line Through Zero", true)

GETN_OPTION_COLOR_LABEL(COLOR_NAVY) // Option to color node label navy blue

// Add a numeric edit box node named YIntercept having caption "Y Intercept"

// initialized to numeric value 1.5

GETN_NUM(YIntercept, "Y Intercept", 1.5)

GETN_OPTION_COLOR_LABEL(COLOR_NAVY) // Option to color node label navy blue

// Add non-editable drop down list box node named Order having caption

// "Polynomial Order" initialized to 2 with list values 2,3,4,5,6

GETN_COMBO(Order, "Polynomial Order", 2, "2|3|4|5|6")

GETN_OPTION_COLOR_LABEL(COLOR_NAVY) // Option to color node label navy blue

// End nodes in collapseable branch

GETN_END_BRANCH(Fit)

GETN_BUTTON(Path, "File path", "c:\\")

GETN_OPTION_COLOR_LABEL(COLOR_GREEN) // Option to color node label green

GETN_OPTION_EVENT(RowBasedOnClickButtonEvent) // Option specifying event handler for browsing

// Output GetNBox tree before editing input defaults

out_tree(tr);

// Open GetNBox dialog and edit input defaults passing GetN tree named tr

// and having dialog title "Using GetN Macros" and dialog description "This is

// a GetN dialog with options"

if( GetNBox(tr, "Using GetN Options", "This is a GetN dialog with options specified", NULL, NULL) )

out_tree(tr); // If user clicks OK to close dialog Output edited GetNBox tree

}

// This function is executed when the browse button for the Path node is clicked

static bool RowBasedOnClickButtonEvent(TreeNode& tr, int nRow, int nCntrlType, Dialog& getNDlg)

{

string str = BrowseGetPath(GetAppPath() + "OriginC\\", "Browse");

if( !str.IsEmpty() )

{

tr.Path.strVal = str;

return true;

}

else

return false;

}

Using GETN Option Macros

It is possible to alter several characteristics of GetN trees, branches, and nodes using predefined GetN option macros. Characteristics that can be altered include dialog gridding, branch and node label colors, and various branching behaviors. Row (or node) based event handlers can also be specified using GetN option macros. GetN option macros apply only to the tree, branch, or node that directly precedes it in the definition of the GetN tree. The following table lists the GetN option macros, their usage, and the tree nodes to which they can be applied.

The following example function UsingGetNOptions illustrates the use of the GetN option macros and the GetNBox function to create a sample GetN dialog box with options specified. The dialog itself contains a number of different controls some of which are grouped in a branch subnode. The branch subnode is altered to expand when the dialog is opened and to not resize the dialog when the branch is collapsed (note the use of the bitwise OR operator | to combine two options). In addition, all branch and node labels are colored and the Path node has a row based event handler. Row based event handlers only trigger when their associated node value is changed and not when any other node value is changed as is the case for event handlers specified in the GetNBox function call. All nodes in the dialog are initialized with representative values.

When the UsingGetNOptions function above is executed the Using GetN Options dialog box pictured above opens. Click in the File Path edit box and the “…” push button appears to the right. Clicking the “…” push button then triggers the RowBasedOnClickButtonEvent function defined below which opens a Windows like browse dialog box. When the user selects a folder and clicks OK in the browse dialog box the File Path edit box in the Using GetN Options dialog updates accordingly. Changes to any other values in the GetN dialog box do not trigger this or any other event handler. The event handler function RowBasedOnClickButtonEvent returns a value of true when the value of the Path node is changed and returns false when no refresh is needed. All example code for this section is contained in the UsingGetNOptions.c source file found in the \Samples\Programming\User Interface Development subfolder of Origin.


Subsequently Process a GetN Tree

void SubsequentlyProcessGetNTree()

{

// Use GETN_TREE macro to declare a tree for a Tree style GetN dialog

GETN_TREE(tr)

// Add a numeric edit box node named Days having caption "Enter Days:"

// initialized to numeric value 0

GETN_NUM(Days, "Enter Days:", 0)

// Add a numeric edit box node named Hours having caption "Enter Hours:"

// initialized to numeric value 0

GETN_NUM(Hours, "Enter Hours:", 0)

// Add a numeric edit box node named Minutes having caption "Enter Minutes:"

// initialized to numeric value 0

GETN_NUM(Minutes, "Enter Minutes:", 0)

// Add a numeric edit box node named Seconds having caption "Enter Seconds:"

// initialized to numeric value 0

GETN_NUM(Seconds, "Enter Seconds:", 0)

// Open GetNBox dialog passing GetN tree name tr and having dialog title

// "Compute Elapsed Seconds"

if( GetNBox(tr, "Compute Elapsed Seconds") ) // If user clicks OK GetNBox function returns true

{

// Process GetN tree values computing elapsed seconds

if( ComputeElapsedSeconds(tr) ) // If elapsed seconds computation is successful...

printf("%g Days + %g Hours + %g Minutes + %g Seconds = %g Seconds\n",

tr.Days.dVal,

tr.Hours.dVal,

tr.Minutes.dVal,

tr.Seconds.dVal,

tr.ElapsedSeconds.dVal

); // Output elapsed seconds

}

// Else if user clicks Cancel button GetNBox function returns false so do not process

}

// Function to process an input GetN tree named tr computing elapsed seconds from nodes Days,

// Hours, Minutes, and Seconds and storing result in newly created node named ElapsedSeconds

bool ComputeElapsedSeconds(TreeNode &tr)

{

tr.ElapsedSeconds.dVal = tr.Days.dVal * 24 * 60 * 60 +

tr.Hours.dVal * 60 * 60 +

tr.Minutes.dVal * 60 +

tr.Seconds.dVal;

return true;

}

Subsequently Processing a GetN Tree

Input parameters collected using a GetN dialog box can easily be processed after the dialog is closed (or when the Apply button…if any…is clicked) by passing the tree used to create the dialog to any analysis function. When the OK button on a GetN dialog box is clicked the current values in the GetN dialog are copied to the GetN tree and the GetNBox function returns it by reference along with a return value of true. When the Apply button (if any) on a GetN dialog is clicked the current values in the GetN dialog are copied to the GetN tree which is then passed to the Apply button function (see the Adding an Apply Button section).

Whether returning from the GetNBox function call or running the Apply function the GetN tree can then be passed to any other function as an argument. In addition to the ease with which GetN dialogs allow developers to collect, organize, and process input parameters, GetN dialogs and subsequently called analysis functions are highly scalable. Nodes can simply be added to (or removed from) the GetN tree which can then be passed to the same GetNBox and analysis functions without requiring changes to any argument list. Processing functions that know about the newly added (or removed) tree node can use it as desired and functions that don’t know about it can be designed to run to completion.

The example functions SubsequentlyProcessGetNTree and ComputeElapsedSeconds below demonstrate the passing of a GetN tree to an analysis function. A GetN dialog named Compute Elapsed Seconds is opened and then elapsed seconds is computed and output from the input parameters Days, Hours, Minutes, and Seconds. All example code for this section is contained in the SubsequentlyProcessGetNTree.c source file found in the \Samples\Programming\User Interface Development subfolder of Origin.

The resulting Tree style GetN dialog follows below.

When the OK button in the above dialog was clicked the following output was printed in the Origin Script window.

1 Days + 3 Hours + 5 Minutes + 26 Seconds = 97526 Seconds


Creating Complex Dialogs and Wizards with Dialog Builder

Dialog Builder allows developers to use Microsoft Visual C++ resources to build floating tools, dialog boxes, and wizards for use in Origin. All elements of a resource, including buttons, check boxes, radio buttons, sliders, edit boxes, combo boxes, list boxes, rich edit boxes, and graph controls can be programmatically accessed and controlled using the Origin C programming language. Resource operations can be programmed entirely in Origin C or can be programmed in a C++ Dynamic Link Library (DLL).

To create a resource-only DLL that is accessible in Origin using Origin C the DLL must be built using Microsoft Visual C++ version 5.0 or higher. OriginPro Dialog Builder includes an Origin Dialog AppWizard which simplifies the process of creating a resource-only DLL in Microsoft Visual C++. To access this wizard in Microsoft Visual C++, copy the file

ODialog.awx

from the \ATI\Dialog Builder subfolder of Origin to the \Common\MSDev98\Template subfolder of Microsoft Visual Studio. After copying the file perform the steps in the following section to start the Dialog Builder AppWizard and to construct and launch a resource-only DLL containing a “Hello World” dialog. Additional sections describe how to use a number of complete Dialog Builder samples that come with OriginPro and where to find reference information on Dialog Builder classes.


Create a "Hello World" Dialog

    1. Start Microsoft Visual C++.

    2. In Microsoft Visual C++ select the File:New menu item to open the New dialog.

    3. On the Projects tab, select Origin Dialog AppWizard from the list box and then specify a project name and location in the associated fields. For this tutorial use HelloWorld (without a space) for the project name and a subfolder in the Origin software folder named \HelloWorld (without a space) for the project location. For example, if the project name is HelloWorld the project location might be something like

C:\Program Files\OriginLab\OriginPro75\HelloWorld

    4. Click OK. The Origin Dialog AppWizard opens in Microsoft Visual C++.

    5. Select A simple dialog for What kind of Origin Dialog project do you want to create? and click Next.

    6. Select the Origin C radio button and check the Use classes checkbox for What language will you use to control the dialog? Click Next.

Template code to control your dialog will be created for you using the Origin C language and user-defined classes.

    7. Enter Hello World (with space) for Caption, enter IDD_HW_DLG for Resource ID, enter HelloWorld (without space) for Origin C Name, and then click Finish.

    8. Peruse and then click OK on the New Project Information dialog. The Origin Dialog AppWizard closes and the Microsoft Visual C++ workspace contains a simple dialog which can be modified as described below.

    9. Select the Build:Set Active Configuration menu item, choose HelloWorld – Win32 Release from Project Configurations, and then click OK to close the Set Active Project Configuration dialog box.

    10. Select the Project:Settings menu item, select the Link tab in the Project Settings dialog, and then clear and enter HelloWorld.DLL for Output file name. Click OK.

    11. Select the View:Resource Includes menu item, clear and enter HelloWorldRes.h (without quotes) for Symbol header file, and then clear and enter

#include "afxres.h"

(with quotes) for Read-only symbol directives. If not empty, clear Compile-time directives. Click OK twice.

    12. On the ResourceView tab in the Microsoft Visual C++ workspace window expand the [+] next to the“HelloWorld resources folder, expand the [+] next to the Dialog folder, and then double-click on the IDD_HW_DLG resource to open the HelloWorld dialog.

    13. Add a static text object to the HelloWorld dialog by depressing the Static Text button [image] on the Controls toolbar and then dragging out a static text object on the HelloWorld dialog. Vertically and horizontally center the static text object by selecting it and then clicking the Center Vertical and Center Horizontal buttons [image] on the Dialog toolbar. If the Controls or Dialog toolbars are not visible right-click on a blank area of the toolbar spacer and enable them.

    14. Right-click on the newly added static text object, select Properties from the shortcut menu, and enter IDC_HW_STATIC for ID on the General tab. Select the Styles tab and then select Center from the Align text combox.

    15. Select the Build:Rebuild All menu item (and if asked click Yes to Replace existing file? and Yes to Do you want to reload it?) to build the workspace causing Microsoft Visual C++ to recreate the HelloWorldRes.h Symbol header file.

    16. Select the FileView tab in the Microsoft Visual C++ workspace window, expand the [+] next to the HelloWorld files icon, and then expand the [+] next to the Header Files folder. Double-click on the HelloWorldRes.h header file in the Header Files folder on the FileView tab in the Microsoft Visual C++ workspace window to open it. Copy the line

#define IDD_HW_DLG 100

and paste it into the file HelloWorldRes.h just above the line

#define IDC_HW_STATIC 6000

    17. Also, in the file HelloWorldRes.h change the line

#define _APS_NEXT_RESOURCE_VALUE 100

to

#define _APS_NEXT_RESOURCE_VALUE 101

    18. Select the File:Save All menu item (and if asked click Yes to Do you want to reload HelloWorld.rc?) to save the changes in the file HelloworldRes.h and then close the HelloWorldRes.h window.

    19. Select the Build:Rebuild All menu item (again) in Microsoft Visual C++ to re-compile the resource-only DLL. Verify that the file HelloWorld.DLL is created in the Origin \HelloWorld subfolder of Origin.

    20. Launch Origin and open Code Builder by clicking the Code Builder toolbar button [image] on Origin’s Standard toolbar. Click the Open toolbar button [image] in Code Builder, check the Add to Workspace checkbox at the bottom of the Open dialog box, and then browse to and open the files HelloWorld.c, HelloWorld.h, and HelloWorldRes.h found in the \HelloWorld subfolder of Origin.

    21. Study the code in the three files as desired. HelloWorld.c contains a function which launches the Hello World dialog, HelloWorld.h contains the implementation of the HelloWorld user-defined class, and HelloWorldRes.h contains all resource IDs used by the HelloWorld resource only DLL.

    22. Activate the HelloWorld.h window in Code Builder and modify the HelloWorld class member function named OnInitDialog as follows.

BOOL OnInitDialog()

{

Control ctrl = GetItem(IDC_HW_STATIC);

ctrl.Text = "Hello World!";

return TRUE;

}

    22. Select the Tools:Rebuild All menu item in Code Builder to compile and link all the files in the Origin C workspace including HelloWorld.c, HelloWorld.h, and HelloWorldRes.h.

    23. Activate Origin and open the Script Window by selecting the Origin Window:Script Window menu item. Enter DoHelloWorld in the Script Window to execute the DoHelloWorld function which launches the HelloWorld dialog. Click OK or Cancel to close the HelloWorld dialog.

Create a “Hello World” Dialog

To create a simple “Hello World” dialog in a resource only DLL using Microsoft Visual C++ and the Origin Dialog AppWizard first copy the file ODialog.awx from the \ATI\Dialog Builder subfolder of OriginPro to the \Common\MSDev98\Template subfolder of Microsoft Visual Studio. Then, follow the steps below.

Steps 1 - 8: Use the Dialog Builder AppWizard to create a resource.

Steps 9 - 11: Edit the Microsoft Visual C++ project settings.

Steps 12 - 14: Add a Static control to the Hello World dialog.

Steps 15 - 18: Adjust header files to work more efficiently with Origin C.

Step 19: Build Dialog Builder resource only DLL.

Steps 20 - 23: Edit and execute Origin C code to launch the “Hello World” dialog in Origin.


Origin C Dialog Builder Examples

    1. If needed start Origin and open Code Builder by clicking the Code Builder toolbar button [image] on Origin’s Standard toolbar.

    2. Select the File:Open menu item in Code Builder. Browse to any of the Origin C Dialog Builder example subfolders (e.g. \Samples\Programming\User Interface Development\Dialog Builder\Graphs) and open the example file of type *.C in Code Builder (e.g. TwoGraphs.c). Study the code as desired.

    3. Add the *.C file (e.g. TwoGraphs.c) to the Code Builder workspace by activating it in the Code Builder Multiple Document Interface (MDI) and then pressing the CTRL+W keys. Select the Tools:Rebuild All menu item in Code Builder to compile and link all the files in the Origin C workspace.

    4. Search in the example *.C file (e.g. TwoGraphs.c) for a function (e.g. TwoGraphs) containing code that declares an instance of a user-defined class object that encapsulates the example dialog (e.g. CTwoDialog GraphDlg;). The function should also include a statement that launches the example dialog using the Origin C Dialog class DoModal or Create member functions (e.g. GraphDlg.DoModal( GetWindow());).

    5. Copy the name of the Origin C function containing the code described above to the clipboard (e.g. TwoGraphs).

    6. Activate Origin. Create and activate an Origin worksheet containing three columns of numeric data.

    7. Open the Script Window by selecting the Origin Window:Script Window menu item. Paste the name of the function (e.g. TwoGraphs) into the Script Window and press the Enter key. The function executes and launches the example dialog (e.g. Graph Controls) shown below.

    8. Close the example dialog (e.g. Graph Controls) in Origin, close Code Builder, and close Origin.

    9. Start Microsoft Visual C++. Select the File:Open Workspace menu item and select Projects (*.dsp) from the Files of type drop down list in the Open Workspace dialog.

    10. Browse to any of the Dialog Builder example subfolders in Origin (e.g. \Samples\Programming\User Interface Development\Dialog Builder\Graphs\ResDLL) and open an example workspace project file (e.g. Graphs.dsp).

    11. Study (and customize) the Microsoft Visual C++ example project as desired and then select the Microsoft Visual C++ Build:Rebuild All menu item to rebuild the resource creating a new version of the DLL (e.g. \Samples\Programming\User Interface Development\Dialog Builder\Graphs\Graphs.DLL).

Origin C Dialog Builder Examples

OriginPro includes a number of sample dialogs each demonstrating how to programmatically access one or more controls on a Dialog Builder dialog. This section describes how to use Origin and Code Builder to launch any of the Origin C Dialog Builder examples. It also describes how to use Microsoft Visual C++ to open and rebuild any of the example resource files used to construct the dialogs. The steps below use the Origin C Dialog Builder TwoGraphs example for demonstration purposes but all Origin Dialog Builder examples work in a similar manner.

Use Origin and Code Builder to launch an example dialog.

Use Microsoft Visual C++ to edit and rebuild an example resource file.


Origin C Header Files

In order to programmatically access controls on a Dialog Builder dialog you must first attach an Origin C object of the appropriate type to the control on the dialog. Origin C supports many control types including buttons, check boxes, radio buttons, sliders, edit boxes, combo boxes, list boxes, rich edit boxes, and graph controls. The available control types are built-in Origin C classes containing methods and properties. The class methods and properties of each type can be used to manipulate controls on a dialog once an Origin C object of the appropriate type is declared and attached to a control on the dialog. The type of the Origin C object must match the type of the control on the dialog.

The control types (classes) and their methods and properties are prototyped in several Origin C header files in the \OriginC\System subfolder of Origin. These header files also contain reference information for each class and for the class methods and properties. Origin C system header files containing Dialog Builder related classes include Dialog.h, Control.h, mswin.h, and MsgMap.h. The system header file Dialog.h includes all other Dialog Builder related header files. It is sufficient and recommended to include just Dialog.h in any source file used to control Dialog Builder dialogs.


Adding an ActiveX Control to a Dialog Builder Dialog

It is possible to add ActiveX controls to Dialog Builder dialogs and programmatically manipulate them using Origin C. The ability to easily add user created and third party ActiveX controls to Dialog Builder dialogs greatly expands the possibilities available to developers who create custom applications in Origin. ActiveX controls are added to Dialog Builder dialogs much the same way as Visual C++ controls are added with a few additional steps. This section describes how to add ActiveX controls to Dialog Builder dialogs and refers to two OriginPro sample Dialog Builder dialogs containing ActiveX controls. The section Creating Complex Dialogs and Wizards with Dialog Builder describes the general process of creating Dialog Builder dialogs and should be reviewed first.

Add an ActiveX control to a Dialog Builder dialog.

  1. Build and register with Windows a user created ActiveX component and/or install third party software containing an ActiveX component on to your computer system. If you do not have an installation program for your ActiveX component copy it to your Windows system DLL folder (e.g. \winnt\system32) and execute the following command from the Windows Start:Run dialog or a DOS command prompt:

regsvr32 <your ActiveX component name>

  2. Use the OriginPro Dialog Builder AppWizard to create a Microsoft Visual C++ project containing the resources for a Dialog Builder dialog. For information on how to do this see the section Creating Complex Dialogs and Wizards with Dialog Builder.

  3. In Microsoft Visual C++ select the Project:Add To Project:Components and Controls menu item to open the Components and Controls Gallery.

  4. In the Components and Controls Gallery browse to and select the desired ActiveX component (most likely residing in the \Common\MSDev98\Gallery\Regeisterd ActiveX Controls subfolder of Microsoft Visual Studio). Click the Insert button and then click OK if asked Insert this component? Finally, click OK in the Confirm Classes dialog and click the Close button in the Components and Controls Gallery.

You have now added your ActiveX component to the Microsoft Visual C++ project containing the resources for your Dialog Builder dialog.

  5. On the ResourceView tab in the Microsoft Visual C++ workspace window expand the [+] next to your resources folder, expand the [+] next to the Dialog folder, and then double-click on the ID of your resource to open your dialog.

  6. A button for your ActiveX control should now appear on the Microsoft Visual C++ Controls toolbar (if the Controls toolbar is not visible right-click on a blank area of the toolbar spacer and enable it). Depress the button for your control on the Controls toolbar and drag out an instance of the control on your dialog. Position, size, and assign properties to the new ActiveX control as desired.

  7. Select the Build:Rebuild All menu item in Microsoft Visual C++ to compile the resource-only DLL containing the Dialog Builder dialog with your ActiveX control.

The resource-only DLL containing the Dialog Builder dialog with your ActiveX control is now ready to be launched and manipulated in Origin using Origin C. OriginPro contains a number of example dialogs which fully implement Dialog Builder dialogs some containing ActiveX controls. Source files that launch and manipulate the dialogs are also included. To learn how to launch and manipulate a Dialog Builder dialog with an ActiveX control first review the section Origin C Dialog Builder Examples and then follow the steps in the next section Programmatically Accessing a Dialog Builder Dialog with an ActiveX Control.


Programmatically Accessing a Dialog Builder Dialog with an ActiveX Control

To learn how to launch and manipulate a Dialog Builder dialog with an ActiveX control first review the section Origin C Dialog Builder Examples and then follow the steps below. The steps below use Origin and Code Builder to launch and manipulate an example dialog with an ActiveX control.

  1. If needed start Origin and open Code Builder by clicking the Code Builder button [image] on Origin’s Standard toolbar.

  2. Select the File:Open menu item in Code Builder. Check the Add to Workspace checkbox at the bottom of the Open dialog box and then browse to and open the sample files ActiveXDLG.c, ActiveXDlgCls.h, and ActiveXDLG.h in the \Samples\Programming\User Interface Development\Dialog Builder\ActiveXDLG subfolder of Origin. The source files are also added to the Code Builder workspace. Study the code as desired to gain an understanding of how to launch and manipulate a Dialog Builder dialog containing an ActiveX control.

  3. In the header file ActiveXDlgCls.h locate the line of code below.

m_objActiveX = GetItem( IDC_AXD_VSFLEXGRID ).GetActiveXControl();

The GetItem method of the Dialog class is chained together with the GetActiveXControl method of the Control class to attach the class data member m_objActiveX to a VSFlexGrid ActiveX control from ComponentOne Software. The ActiveX control has the resource ID IDC_AXD_VSFLEXGRID.

  4. Select the Tools:Rebuild All menu item in Code Builder to compile and link all the files in the Origin C workspace.

  5. Activate Origin and open the Script Window by selecting the Origin Window:Script Window menu item. Type LaunchActiveXDLG() into the Script Window and press the Enter key. The function executes and launches the Active X Dialog example dialog containing the VSFlexGrid ActiveX control.

For additional example dialogs containing ActiveX controls see the source files contained in the \Samples\Programming\User Interface Development\Dialog Builder\ActiveXNI subfolder of Origin.


Introduction to COM Programming

The Microsoft Component Model (COM) is a software architecture that allows applications to be built from binary software components. COM is the underlying architecture that forms the foundation for higher-level software services, like those provided by OLE (Object Linking and Embedding). Components developed using COM thus provide the means by which two applications could communicate by calling each other’s methods. For example, Microsoft's Internet Explorer web browser supports calling into COM objects through script, making it possible to create Web pages that tap into the functionality of other applications.

Origin provides the capability for COM client programming, whereby Origin can access COM components of other applications (such as Microsoft Word, Excel) from within the Origin C programming environment. Origin C source code that includes COM client programming can only be compiled in OriginPro. Once the source code has been compiled, the pre-parsed file (.OP file) can be distributed for use by standard Origin users.

Origin can also function as an Automation Server, where other applications (such as Microsoft Excel, Internet Explorer, Visual Basic, LabVIEW) communicate with Origin using COM programming. The standard version of Origin supports Automation Server programming. The OriginPro version has additional capability that provides access control for multiple clients (such as multiple web pages) to communicate with the same instance of OriginPro.

The following sections describe the client and server aspects of COM programming supported in Origin.


COM Client Programming with OriginPro

void COMExample()

{

// Declare Excel objects

Object oExcel, oExcelWkbks, oExcelWkbk, oExcelWksh;

// Create an Excel application object and set it as invisible

oExcel = CreateObject( "excel.application" );

oExcel.Visible = false;

// Get the workbooks collection of the Excel object

oExcelWkbks = oExcel.Workbooks;

// Open the workbook with data to be analyzed

oExcelWkbk = oExcelWkbks.Open( "c:\\temp\\MyData.xls" );

foreach (oExcelWksh in oExcelWkbk.Worksheets)

{

// Create Origin worksheet, and declare datasets

Worksheet wksData;

bool bRetW = wksData.Create( "Origin.OTW" );

Dataset dsX( wksData, 0 );

Dataset dsY( wksData, 1 );

dsX.SetSize( 10 );

dsY.SetSize( 10 );

// Read from Excel wksht to Origin Wksht

dsX = oExcelWksh.Range( oExcelWksh.Cells(1,1),

oExcelWksh.Cells(10,1) ).Value;

dsY = oExcelWksh.Range( oExcelWksh.Cells(1,2),

oExcelWksh.Cells(10,2) ).Value;

}

// Close the Excel application

oExcel.Quit();

}

COM Client Programming with OriginPro

COM client programming, where Origin calls functions and methods from other applications, is supported only in OriginPro. The Origin C programming environment in OriginPro uses the type Object to represent all COM (automation) objects. Any Object can be initialized in two ways:

  • By creating a new object using the CreateObject function, as in standard in VBA. For example:

Object ocrs;

ocrs = CreateObject("ADODB.Recordset");

which creates a new COM object of the type "ADODB.Recordset" .

  • By getting objects from existing objects (usually as properties or return values of methods). For example:

// Declare Excel objects

Object oExcel, oExcelWkbks;

// Create an Excel application object

oExcel = CreateObject("excel.application");

// Get the workbooks collection of the Excel object

oExcelWkbks = oExcel.Workbooks;

The sample code above first creates an excel.application object using the CreateObject function, and then gets an object representing the collection of all workbooks using the Workbooks property of the excel.application object.

Some examples of COM client programming follow.

Accessing MS Office Programs

COM client programming in Origin C can be used to programmatically exchange data with MS Office applications.

The following Origin C function fetches data from an Excel file and places the data in an Origin worksheet column:

Click Here to See Code

Note that the above code assumes that there is an Excel file named MyData.xls in the C:\temp subfolder, and that this Excel file has one worksheet with data in the first two columns, from rows 1 through 10.

For a more comprehensive example, review the Origin C code in the following example \Samples\COM Clients\ReportCreation.c, which does the following:

  1. Opens an Excel Workbook named ExcelData.XLS from the \Samples\COM Clients subfolder of Origin.

  2. Reads the data in all (2) worksheets of this sample Excel file.

  3. Graphs the data in Origin using a custom template and performs a nonlinear curve fit.

  4. Exports the resulting graph with fit curve to a BMP file.

  5. Creates a new Word document for each worksheet, using a custom template.

  6. Places the graph image and other relevant information into the Word document.

Database Access

COM programming within Origin C can be used to communicate with databases by accessing an ActiveX Data Object (ADO).

For more information, see the file ADOSample.c in your \Samples\COM Clients folder. This Origin C program demonstrates that SQL and Access databases can be imported to a worksheet and subsequent data modifications returned to the database.

Using the MS XML Parser to Convert an Origin Worksheet into an XML Document

The OriginC COM interface can be used to programmatically create XML documents.

For more information, see the file WksToXML.c in the \Samples\COM Clients subfolder of Origin. This OriginC program uses the Microsoft MSXML parser to convert an Origin worksheet into an XML document.


Automation Server Programming

' Before compiling this code, open the References dialog

' in VB (menu: Project:References)and add the Origin application

' Declare Origin application and launch it

Dim oApp As Origin.Application

Private Sub Command1_Click()

' Make connection to Origin

Set oApp = GetObject("", "Origin.Application")

' Send a script command to Origin

' to bring up attention box with message

Dim bRet As Boolean

bRet = oApp.Execute("type -b Hello!;")

End Sub

' Before compiling this code, open the References dialog

' in VB (menu: Project:References)and add the Origin application

' Declare Origin application and launch it

Dim oApp As Origin.ApplicationSI

Private Sub Command1_Click()

' Make connection to Origin

Set oApp = GetObject("", "Origin.ApplicationSI")

' Send a script command to Origin

' to bring up attention box with message

Dim bRet As Boolean

bRet = oApp.Execute("type -b Hello!;")

End Sub

Automation Server Programming

Origin can function as an automation server whereby other applications communicate with Origin via exposed methods and properties. This feature is available in both Standard and Pro installations of Origin.

Sample files that demonstrate how to connect to an Origin server from Excel, Visual Basic, and LabVIEW clients can be found in the subfolder \Samples\AutomationServer under the main Origin installation area. In the case of LabVIEW, Origin provides a collection of building-block VIs that can be utilized in creating custom VIs to communicate with Origin. The custom LabVIEW VIs are documented in the file LabVIEW_Connectivity.pdf, which can be found in the subfolder mentioned above.

The following discussions cover basic features of the Automation Server assuming Visual Basic as the client application. For detailed documentation on Origin's Automation Server methods and properties, please view the help topic Origin Automation Server Reference.

The external application (such as VB, MS Excel) first needs to create a new object that connects to the Origin application. This can be done in two ways:

Dim oApp As Origin.Application

Set oApp = GetObject("", "Origin.Application")

or

Dim oApp As Origin.ApplicationSI

Set oApp = GetObject("", "Origin.ApplicationSI")

In either of the above cases, if no instance of Origin is currently available, the Origin application is first launched. The difference between the two is that in the first case a new instance of Origin is launched each time, where as in the second case all clients connect to the same instance of the Origin application.

The various Origin methods and properties that are exposed to COM access are listed in the language reference help files, under the topic Origin Automation Server Reference.

The following code segment illustrates a simple VB example that launches Origin and then opens an attention box with a "Hello!" message in Origin:

Click here to display the code segment

Note: Before you compile VB code that invokes the Origin application, you need to add the Origin application to your project references, using the Project:References menu item in VB (or Tools:References in Visual Basic Editor used by MS Office applications).

The above code will launch a new instance of Origin. To connect to an existing instance of Origin, the code should be changed as follows, using ApplicationSI object:

Click here to see the change

When multiple clients try to connect to the same Origin session using the ApplicationSI object, one client can interrupt the communication of another client that is already connected. OriginPro provides a mechanism to handle multiple clients in the same Origin session, as described in the section below.


Supporting Multiple Clients with OriginPro

' Before compiling this code, open the References dialog

' in VB (menu: Project:References)and add the Origin application

' Declare Origin application and launch it

Dim oApp As Origin.ApplicationSI

Private Sub Command1_Click()

' Make connection to Origin

Set oApp = GetObject("", "Origin.ApplicationSI")

' Use BeginSession to lock to this client

Dim bRet As Boolean

bRet = oApp.BeginSession

' Send a script command to Origin

' to bring up attention box with message

bRet = oApp.Execute("type -b First Client!;")

' Release Origin for use by other clients

bRet = oApp.EndSession

End Sub

' Before compiling this code, open the References dialog

' in VB (menu: Project|References)and add the Origin application

' Declare Origin application and launch it

Dim oApp As Origin.ApplicationSI

Private Sub Command1_Click()

' Make connection to Origin

Set oApp = GetObject("", "Origin.ApplicationSI")

Dim bRet As Boolean

On Error Resume Next

' Try sending a script command to Origin

bRet = oApp.Execute("type -b Second Client!;")

If Not bRet Then

MsgBox "Cannot connect to Origin. Try later!"

End If

End Sub

Supporting Multiple Clients with OriginPro

OriginPro supports two additional methods that can be used to lock an existing instance of Origin to one client, thereby denying access to other clients until the current client releases the connection (with Origin). The BeginSession method reserves the current Origin session for exclusive use by a client, and the EndSession method releases the current Origin session for use by other clients. These two methods have meaning only for clients accessing a single instance of the Origin automation server. In other words, the clients need to declare the Origin object using the ApplicationSI method. These two methods are available only to clients that connect to an OriginPro session.

The following code illustrates the same example presented in the earlier section, but with the BeginSession and EndSession methods added:

View Code

A second client could then check if Origin is available for connection, such as in the following example:

View Code

More detailed examples on connecting to Origin from Visual Basic, Excel and LabVIEW can be found in the subfolder \Samples\Automation Server under the main Origin installation folder.


Introduction to Distributing Custom Applications

This section provides information on how to distribute your custom applications developed in Origin, to other users. Custom applications can be as simple as one Origin project file, or may involve multiple files. Origin provides two methods for distributing files. One method is to attach all files associated with the application, to an Origin project file. The second method is to package all files as an Origin Pack file (.OPK). The first two topics in this section provide more details on these two methods.

Two related topics are also discussed. Executing code when Origin events occur can be useful when distributing custom applications. A detailed example demonstrating how to execute a LabTalk script and an Origin C function when an Origin project file is opened is included. The script and function are used to open another application from inside Origin. The script, function, and a help file (the other application) are all contained in the Origin project file. Finally, a section discussing how to protect proprietary source code with encryption is included.


Packaging an Application as an Origin Project

The easiest way to distribute your custom application to another user is by attaching all necessary files to an Origin project (*.OPJ) file. This method works well in the simple case where all that is needed in addition to the project is Origin C (*.C) or Origin Script (*.OGS) source files. However, files of any type, such as ASCII Text files, Microsoft Word files, or Adobe Acrobat files, can also be attached to the project.

The current mechanism for attaching and retrieving files to the project is via the Code Builder interface. The workspace tree in Code Builder has a Project branch which lists files that are attached to the currently open Origin project. Files can be added to this branch by simply right-clicking on the Project branch, then selecting Add Files, and navigating to the files to be added. Files can also be dragged and dropped to the Project branch from other branches of the workspace tree.

Files attached to the Origin project are all stored in a temporary windows folder. The attached files are appended to the project on saving, and are retrieved when the project is opened in Origin. The location of the temporary folder can be viewed by right-clicking on the Project branch of the workspace tree, and then selecting Show Full Path from the context menu.

When viewing the list of files attached to the project in the Code Builder interface, users can double-click on a file to open it. If the file is of a type that is recognized by Code Builder (as Origin C source file, Origin script file, simple ASCII file, etc.), then the file will be opened within the Code Builder multi-document interface. If the file is not recognized by Code Builder, then the file will be passed on to Windows for opening. For example, if a Microsoft Word file is attached, double-clicking on the file will result in the file opening in the Microsoft Word application.

All Origin C files that are attached to the project are loaded and compiled automatically when the project is opened in Origin. The functions contained in theses Origin C files are thus available for immediate access on opening the project, and may be associated with GUI components such as buttons in the project. The GUI components will then be functional as soon as the project file is opened.

The path for the temporary folder that contains all attached files can be obtained in Origin C using:

string strPath = GetProjectAttachedFilesPath();

LabTalk script contained in script (*.OGS) files attached to the project is also accessible immediately on opening the project. Any time a script section is referred to in the Origin GUI using a command such as

run.section(file name, section name)

Origin first checks to see if there is a script (*.OGS) file by the specified name attached to the project, and if that file contains a section by the specified name. If such a file and section are found in the attachments, then that code is executed. If such a file or section is not found in the attachments, then Origin searches for the file and section in the User Files (INI) path, and subsequently in the Origin application path.

The main limitation of distributing an application by attaching files to the Origin project is that the application is available only within the scope of the project file. For more advanced applications that need to provide features such as custom toolbars and dialogs, the second method described in the following section is more appropriate.


Origin Pack Files

When an OPK file is unpacked by Origin (either by dragging and dropping it into the Origin workspace or by using the Origin Pack tool) the internal unpacking mechanism runs two sections of LabTalk script. To take advantage of this mechanism developers must include a LabTalk script file (of type *.OGS) inside their Origin Pack file. The script file must have the name MyOPKNameSetup.OGS where MyOPKName is the name of the OPK file and it must include sections of script named OnBeforeSetup and OnAfterSetup. The OnBeforeSetup section is run just prior to unpacking the OPK file and the OnAfterSetup section is run immediately afterward. An example of such a script file is shown below. The file, named MyGroupSetup.OGS, can be found in the \Samples\Programming\User Interface Development subfolder of Origin.

The OnBeforeSetup section in the above example simply asks whether or not the user agrees to some license agreement. However, this trivial message box could be replaced with a more robust dialog (see the section Creating Complex Dialogs and Wizards with Dialog Builder) containing a complete license agreement and requiring a license key. Developers can encrypt the license key, save it in a binary file or in the Window’s Registry, and then require the encrypted key before allowing their application to install and/or run. A value of 1 must be returned by the OnBeforeSetup section in order for the OPK file to be unpacked and for the packed files to be installed. The licensing dialog box and encryption code can all be implemented in an Origin C function which can itself be encrypted (see the next section Encrypting Files for Distribution with OriginPro) thereby ensuring security from all but the most determined (and talented) hackers.

The OnAfterSetup section runs after the unpacking and installation of all packed files is complete and is well suited to create custom toolbars and make menu modifications. The above LabTalk script uses the system.toolbar object to create a custom toolbar, uses the run.file command to execute the configuration file CustomMenus.CNF (to modify menus in the current session of Origin), and uses the ini object to customize the Origin.INI initialization file so that it runs the configuration file CustomMenus.CNF each time Origin starts (to modify menus in future sessions of Origin).

The steps below outline the procedure for creating an OPK file that prompts for agreement to a license, creates a custom toolbar, and modifies the Origin menu. For more details on the source files included in the OPK file see the sections Toolbar Buttons and Customizing Origin Menus.

To create the MyGroup.OPK file.

To extract MyGroup.OPK using the Origin Pack tool.

To uninstall the MyGroup.OPK file and to delete the MyGroup button group and toolbar.

[OnBeforeSetup]

// Script to request and verify License key and/or (Dis)Agree to License

run.section(,AgreeToLicenseYorN);

if(ClickedNo)

type -b "Installation terminated.";

return ClickedNo; // Returning value of 1 causes installation of OPK to terminate

[OnAfterSetup]

// Script to create MyGroup Toolbar

system.toolbar.createcategory("Samples\Programming\User Interface Development\MyGroup.INI");

system.toolbar.create(MyGroup);

%A=$General.UserDefinedGroupAdded;

%B=$General.UserDefinedGroup;

type.msgBox(MyGroup %A, %B);

// Script to update menu for this session of Origin

run.file(CustomMenus.CNF);

// Script to update menu for future sessions of Origin

ini.get.filename$="Origin.ini";

%Z=ini.config.file1$;

ini.config.file1$=%Z CustomMenus;

return 0;

[AgreeToLicenseYorN]

// Script to capture Yes or No response

ClickedNo=1; // Preset to expect No answer which causes section to terminate

type -n "Click Yes to agree or No to disagree with License.

(You must click Yes to continue with installation.)";

ClickedNo=0;

return 0;

    1. Copy the files CustomMenus.CNF and CustomMenus.OGS from the \Samples\Programming\User Interface Development subfolder of Origin into the main Origin software folder (configuration files of type *.CNF must be located in the main Origin software folder when executed).

    2. Select the Origin menu item Tools:Pack/UnPack OPK Files… to open the Origin Pack tool.

    3. Click the Add toolbar button [image] on the Origin Pack tool.

    4. Browse to and add the files copied into the Origin software folder in step 1 above.

    5. Browse to the \Samples\Programming\User Interface Development subfolder of Origin and add the files MyGroup.INI, MyGroup.BMP, MyGroup.OGS, ProgressBox.C, and most importantly, MyGroupSetup.OGS.

    6. Click the OK button to add all seven of the above mentioned files to the Origin Pack tool’s File List.

    7. Click the Pack toolbar button [image] on the Origin Pack tool.

    8. Browse to your Desktop (or some other convenient location) and save the newly created Origin Pack file as MyGroup.OPK.

Note: Precise naming is important. The OnBeforeSetup and OnAfterSetup sections of script in the MyGroupSetup.OGS file will not be executed if the OPK file is not named MyGroup.OPK.

Once the MyGroup.OPK file has been created it can be installed into Origin either by dragging and dropping it into the Origin workspace or by extracting it using the Origin Pack tool. In order for MyGroup.OPK to install without warning messages you must first ensure that the MyGroup.OPK file, the MyGroup button group, and the MyGroup toolbar are not currently installed. For instructions on how to uninstall/delete them (should they currently be installed) follow the steps outlined at the very end of this section.

    1. Click the Open toolbar button [image] on the Origin Pack tool.

    2. Browse to and open the MyGroup.OPK file created above. The MyGroup.OPK file must first be opened in the Origin Pack tool before it can be extracted.

    3. Click the Extract toolbar button [image] on the Origin Pack tool.

    4. Click “Yes” to agree to the license agreement when MyGroup.OPK is opened.

    5. Create or activate a new Origin child window to force a refresh of the Origin menus.

The MyGroup.OPK file is unpacked, the MyGroup toolbar is created, and several Origin menu modifications are made (the GetData menu is added, menu items are added to the Statistics menu, and the View menu is removed).

    1. Select the Origin Tools:Uninstall OPK Files… menu item, select MyGroup (if present) in the Uninstall Opack dialog, and then click the Uninstall button.

    2. Select the Window:Script Window menu item to open the Origin Script window. Copy/paste the following script into the Script window, highlight it, and then press the ENTER key. The script runs removing all menu customizations in the current and in future Origin sessions.

menu.cleanup();

ini.get.filename$=Origin.ini;

ini.config.file1$=Macros FullMenu;

    3. Create or activate a new Origin child window to force an update of the Origin menus.

    4. Select the View:Toolbars menu item in Origin. On the Toolbars tab select the MyGroup toolbar (if present) and click the Delete button. On the Button Groups tab select the MyGroup button group (if present) and click the Delete button.

Origin Pack Files

If the custom application you wish to distribute has many files, or if the files exist in a folder structure that you want to maintain, you can pack all the files into a single Origin Pack file (of type *.OPK) for easier distribution. Once the recipient receives your Origin Pack file, they can unpack the file to automatically gain access to your custom routines. If your application uses many Origin C files such as source files, custom header files, and DLLs, you could create a Code Builder workspace and then package this workspace along with the necessary files when creating your Origin Pack file. An OPK file (an Origin Pack file) is also the device to use when you want to enforce a license key or agreement, to create custom toolbars, or to make Origin menu modifications.

For general instructions on how to pack and unpack files, refer to the Origin Help topic Distributing your application. The primary focus of this section is to describe the OPK file installation process itself and is not to describe toolbar creation and menu modifications. Therefore, before continuing, you may find it helpful to review the sections Toolbar Buttons and Customizing Origin Menus to familiarize yourself with how toolbar buttons and menu modifications are made. The remainder of this section describes how to run LabTalk script when an OPK file is installed.


Executing Script on Origin Events

Event/Section Name | Description of Origin Event
BeforeUserCNF | This event is triggered before any user CNF files are executed. Execution of system CNF files takes place earlier so system.cnf, option.cnf, and orgsys.cnf are executed before this event is triggered.
AfterUserCNF | This event is triggered after all user CNF files are executed.
BeforeCompileSystem | This event is triggered before Origin begins the start up compilation of files in the Code Builder System folder.
AfterCompileSystem | This event is triggered after Origin finishes the start up compilation of files in the Code Builder System folder. Use this event for additional customization of Origin that requires Origin C functions compiled on start up. Inside the AfterCompileSystem section of script the LabTalk string variable %1 is 1 if compilation was successful and otherwise it is 0.
BeforeOpenDoc | This event is triggered before an Origin project file is opened. Inside the BeforeOpenDoc section of script the LabTalk string variable %1 is the project file path in quotes.
AfterOpenDoc | This event is triggered after an Origin project file is opened. Inside the AfterOpenDoc section of script the LabTalk string variable %1 is the project file path in quotes.
BeforeCloseDoc | This event is triggered before a project file is closed.
AfterCloseDoc | This event is triggered after a project file is closed.
OnExitOrigin | This event is triggered on exiting Origin (after AfterCloseDoc is triggered).

  1. Close Origin (see step 2 before closing Origin).

  2. Locate the file Origin.ini located in the Origin User Files folder (if the path to your Origin User Files folder is not known type %Y= in the Origin Script window and press ENTER). Open the file Origin.ini in your User Files folder in a text editor such as Notepad and search for the lines below in the Config section.

; Ogs1 = OEvents

; Ogs2 = OEvents

  3. Modify the above lines as follows and re-save the Origin.ini file back into your User Files folder. Be sure to remove the semi-colon at the beginning of each line and to spell the LabTalk script file names correctly.

Ogs1 = MyOEventsEx

Ogs2 = MyOEventsEx

  4. Restart Origin.

  5. Click the Open button [image] on Origin’s Standard toolbar. Browse to and open the Origin sample project file MyOEventsEx.opj found in the \Samples\Programming subfolder of Origin.

Note that immediately upon opening the sample Origin project file MyOEventsEx.opj the CodeBuilderUsersGuide.chm help file is opened (i.e. another application is launched when the project file is opened). The following steps explain in detail the technical process by which this happens.

  6. Click the Code Builder button [image] on the Standard toolbar of Origin to open Code Builder.

  7. In the Code Builder Workspace window expand the [+] next to the Project folder. The three files included in the Code Builder Project folder (CodeBuilderUsersGuide.chm, MyOEventsEx.c, and MyOEventsEx.ogs) were embedded and saved inside the Origin project file MyOEventsEx.opj when it was saved. When an Origin project file containing embedded files is opened the embedded files are listed in the Project folder of the Code Builder Workspace window and are then separately saved in a temporary Windows folder. See the previous section Packaging an Application as an Origin Project for more information on files added to the Project folder of the Code Builder workspace.

  8. Double-click on the file MyOEventsEx.ogs in the Project folder to open it in Code Builder and then review its contents. MyOEventsEx.ogs is a modified copy of a template script file named OEvents.ogs found in the main Origin folder and contains sections of LabTalk script (most of which are empty) for all Origin events triggered using the OEvents mechanism. The AfterOpenDoc section includes the lines

[AfterOpenDoc]

%A=GetMyTempPath()$; // Get the path of the temporary file CodeBuilderUsersGuide.chm

run -st "%ACodeBuilderUsersGuide.chm"; // Launch CodeBuilderUsersGuide.chm

The first line calls the Origin C function GetMyTempPath to get the path of the separately saved temporary files embedded in the Origin project file and listed in the Project folder of the Code Builder workspace. The path of the temporary files is assigned to the LabTalk string variable %A. The second line uses the LabTalk run –st command and the %A string variable to launch the CodeBuilderUsersGuide.chm help file.

  9. Double-click on the file MyOEventsEx.c in the Project folder to open it in Code Builder and then review its contents. MyOEventsEx.c contains the Origin C source code for the function GetMyTempPath called in the AfterOpenDoc section of script shown above.

string GetMyTempPath()

{

string strPath;

strPath = GetProjectAttachedFilesPath(); // Get path of chm file

return strPath;

}

When the Origin project file MyOEventsEx.opj is opened the files in the Project folder are separately saved in a temporary Windows folder and the embedded source file MyOEventsEx.c is automatically compiled and linked (making the function GetMyTempPath immediately available for execution). After the project file is opened the AfterOpenDoc section of LabTalk script in the MyOEventsEx.ogs file is triggered using the OEvents mechanism. The script executes getting the path of the temporary files and then opening the CodeBuilderUsersGuide.chm help file.

Executing Script on Origin Events

It is possible to execute LabTalk script on a number of different Origin events. LabTalk script triggered by these Origin events can perform many tasks including calling Origin C functions, opening GetN dialogs, opening custom tools, customizing Origin menus, and launching other applications. This section describes the mechanism by which sections of LabTalk script can be executed when certain Origin events occur. Executing script when Origin events occur can be useful when implementing and when distributing custom applications.

Initializing Origin to trigger sections of LabTalk script when an event occurs requires customization of the Origin.ini file. Customizing the Origin.ini file can be done manually or when installing an add-on module using an Origin Pack file (files of type *.OPK). The mechanism by which sections of LabTalk script are executed on Origin events is similar to the mechanism by which Origin menus are customized when Origin starts by executing Origin configuration files (files of type *.CNF). Uncommenting (remove the ;) the line

;OgsN = OEvents

in the Config section of the Origin.ini file causes a set of LabTalk sections with predefined names in the script file OEvents.ogs to execute when triggered. Script files specified using this mechanism are associated with menu levels as are configuration files (e.g. if OGS1 = MyOEvents then sections of script in the file MyOEvents.ogs are triggered when their Origin event occurs and when the menu level 1 is set). This device is often referred to as the OEvents mechanism but the LabTalk script file names are not restricted to OEvents.OGS.

Origin events available to be triggered can loosely be categorized into events that occur when Origin launches, events that occur when a project file is opened or closed, and events that occur when Origin is exited. The following table lists all Origin events available to be triggered using the OEvents mechanism and the LabTalk sections that are triggered by them.

The remainder of this section includes an example that manually customizes Origin to trigger a section of LabTalk script on an Origin event. The section of script that gets triggered executes an Origin C function and launches another application. All files for this example are included in the Origin sample project file MyOEventsEx.opj and can be found in the \Samples\Programming subfolder of Origin.

To Trigger a section of LabTalk script when an Origin event occurs


Encrypting Files for Distribution with OriginPro

When custom applications are distributed using either the method of attaching files to a project file or by packaging them in an OPK file, it is not necessary to distribute the Origin C source code. The source file (*.C) can be replaced with the pre-parsed file (*.OP). In version 7.5, Origin by default does not generate these pre-parsed files, but rather directly generates pre-compiled binary files (*.OCB) from the source code. It is not possible to distribute the binary files. However, pre-parsed files can be created by using the @OCSB system variable. In order to create pre-parsed files for distribution, this system variable should be set to zero. The following commands can be issued from the Origin script window:

@OCSB = 0; // create OP files

@OCSB = 1; // do not create OP files

The pre-parsed files are saved to the same folder location as their corresponding Origin C source code files.

The benefit of shipping pre-parsed files instead of the Origin C source files is that the source code can be protected. Pre-parsed (*.OP) files created in OriginPro are by default encrypted as well to ensure protection of the information contained in the code. Encryption and decryption occur automatically at the time of creation and use of the files. The encryption feature can be turned on or off using the @OCSE system variable. The encryption feature is available only in OriginPro. Pre-parsed files created using standard Origin cannot be encrypted. The following commands can be issued from the Origin script window:

@OCSE = 1; // encrypt OP files

@OCSE = 0; // do not encrypt OP files

Once a pre-parsed file is created, the Origin C source file can be replaced with this pre-parsed file before packaging the application.