|  | 
  Unlike Visual Basic where you can save forms in a text format, Forte
  only offers PEX files in which forms themselves are stored in some
  sort of uu-encoded format, i.e. totally unreadable and inaccessible.
  You can insert/modify class definitions, but forms themselves seem
  impossible at this stage.
  Theo
 | 
|  | 	I have another customer who is just starting to look into doing 
    something like this. So I began playing around yesterday and the attached 
    PEX file is what I came up with it. It is defintely not fancy but it
    does have examples of adding: labels, datafields, radiolists, dropdown,
    pushbuttons, submenus and menu items. Since pop-ups aren't
    supported in V2 I didn't mess with them but under V3 you should be able 
    to do them as well.
    
        Again,  this is very simple example but points out how to do
    several things like how to know when a dynamically created button is
    clicked as well as when a dynamically created menu itme is activated.
    
    Have Fun!
    
    Jeff
    
    
    
begin TOOL dynoscreen;
includes DisplayProject;
includes Framework;
-- START FORWARD CLASS DECLARATIONS
forward main is mapped;
-- END FORWARD CLASS DECLARATIONS
-- START FORWARD CURSOR DECLARATIONS
-- END FORWARD CURSOR DECLARATIONS
-- START CONSTANT DEFINITIONS
-- END CONSTANT DEFINITIONS
-- START C DATA TYPE DEFINITIONS
-- END C DATA TYPE DEFINITIONS
-- START CLASS DEFINITIONS
class main is mapped inherits from DisplayProject.UserWindow
has public  event addedfield;
has public  event getval;
has public  method Init;
has public  method Display;
has public  method CheckIfFieldExists(input FieldName: Framework.TextData): boolean;
has property
	shared=(allow=on, override=on, default=off);
	transactional=(allow=on, override=on, default=off);
	monitored=(allow=on, override=on, default=off);
	distributed=(allow=off, override=off);
has
+515146310000109800000d5a9fe4010100002101020000000002020600940800
+1d009fff010104210f1011120101011700009fff000000000900000bb80fa000
+000000000000000000010160600000000000000000009d0bb89d0fa000000105
+030301fffd0000000000000c0405000600000201000100004b000001000b0300
+0021010200000000050400001c01000506007a08004d009fff010101010f1011
+120101011700009fff010000000900005dc05dc0000000000303030300020404
+a0a00000000000000000009d5dc09d5dc000000105066b010000005dc05dc000
+060006000021010200000000070706007c08000d009fff010104010f10111201
+01011700009fff34000000097d4b094f0df70000000003030303000501016060
+0000000000000000009d094f9d0df700000105081001000000094f0df7000402
+01009fff009fff0001010000090000000404000000020a000b0c080000210202
+000000000a0b0906000302010000006400000a06007c08000d009fff01010401
+0f1011120101011700009fff3500000009000006830df7000100010303030300
+07010160600000000000000000009d06839d0df7000001050d10010000000683
+0df700040201009fff009fff00010100000e0000000404000000020f0010000d
+0000210202000000000f100e06000302010000000000000f06007c08000d009f
+ff010104010f1011120101011700009fff36000000099d01340003410b8e0001
+000103030303000a010160600000000000000000009d03419d0b8e0000010511
+100100000003410b8e00040102009fff009fff00010100001200000004040000
+0002131415001100002102020000000013151206000302010000006400001306
+007c08000d000000010104010f1011120101011700009fff3a00000009000002
+dd05f50001000103030303000f010160600000000000000000009d02dd9d05f5
+0000010516100100000002dd05f500040202009fff009fff0001010000170000
+000004040000000002001819001a001b00160000210302000000001a191b1706
+000302010000000000001806000302070000000000001906007c08000d009fff
+010104010f1011120101011700009fff3b000000099d02790000a7037c000100
+02030303030013010160600000000000000000009ca79d037c000001051c1001
+00000000a7037c00040101009fff009fff00010100001d000004040000021e00
+1c0000210102000000001e1d06000302010000000000001e060092080081029f
+ff21210401212121212121212100009fff3c00000009000000a7037c00010001
+0303030300190101a0a00000000000000000009ca79d037c0000010301091f02
+0100009e00442094001f00001c0113135768696368206669656c6420746f2067
+65740a1a06007808020102080867657476616c75650102042121212121212121
+1700019fff0e00000009009d013d010b0279000200010303030300130101a0a0
+0000000000000000009d010b9d02790000010909096765742076616c75650002
+011b0600b008000902080877686963686f6e6501020421212121210101011700
+020808746578746461746114000000099d03209ca70237022e00020002030303
+030013010180a00000000000000000009d02379d022e00000103020103200300
+03042000002104020001a60121222324210001a6010125002500001c0103034f
+6e65220001a6010226002600001c01030354776f230001a6010327002700001c
+0105055468726565240001a6010428002800001c010404466f75721406000302
+070000000000001506007c08000d000000010104010f1011120101011700009f
+ff3d000000099d05f564021505990001000203030303000f0101606000000000
+00000000009d02159d0599000001052910010000000215059900040201009fff
+009fff00010100002a0000000404000000022b002c0029000021020200000000
+2b2c2a06000302010000000000002b06007c08000d000000010104010f101112
+0101011700009fff3e000000091100014d057000010001030303030015010160
+600000000000000000009d014d9d0570000001052d1001000000014d05700004
+0201009fff009fff00010100002e0000000404000000022f0030002d00002102
+0200000000302f2e06000302010000000000002f06007c08000d009fff010104
+010f1011120101011700009fff4000000009000000a705700001000103030303
+002b010160600000000000000000009ca79d05700000010531100100000000a7
+057000040102009fff009fff0001010000320000000404000000023300340031
+000021020200000000333432060003020100000000006433060092080081029f
+ff21210401212121212121212100009fff4100000009000000a7027100010001
+03030303002f0101a0a00000000000000000009ca79d02710000010301093502
+0100009e00442094003500001c010b0b526f7720746f205573650a3406009208
+0081029fff21210401212121212121212100009fff42000000099d02d50000a7
+02370001000203030303002f0101a0a00000000000000000009ca79d02370000
+0103010936020100009e00442094003600001c010b0b436f6c20746f20557365
+0a3006009208008102000021210401212121212121212100009fff3f00000009
+9d01669ca700a702a30002000103030303002b0101a0a0000000000000000000
+9ca79d02a300000103010937020100009e00442094003700001c010d0d496e73
+6572742057686572650a2c06007c08000d000000010104010f10111201010117
+00009fff4300000009009d014d00c80599000200010303030300150101606000
+00000000000000009cc89d05990000010538100100000000c805990004010200
+9fff009fff0001010000390000000404000000023a003b003800002102020000
+00003a3b3906000302010000000000003a0600f6080089020303726f7701020b
+21212121210101011700030707496e74656765721000000009000000c802cd00
+01000103030303002c010280a00000000000000000009cc89d02cd0000010302
+0107000a000009ff8100009e004000240301003b0600f6080089020606636f6c
+756d6e01020b21212121210101011700040707496e746567657211000000099d
+02cd0000c802cd0001000203030303002c010280a00000000000000000009cc8
+9d02cd00000103020107000a000009ff8100009e004000240301001006007c08
+000d000707427574746f6e73010104010f1011120101011700059fff2e000000
+09009d034103410df70002000103030303000a01016060000000000000000000
+9d03419d0df7000001053c100100000003410df700040304009fff009fff0001
+0100003d00000000000000040400000000000000023e000000000000003f0040
+004100420000004300440000003c00002107020000000041423f3e4043443d06
+0003020100000000001e3e060092080081029fff212104012121212121212121
+00009fff44000000090000012c0279000100010303030300100101a0a0000000
+0000000000009d012c9d027900000103010945020100009e0044209400450000
+1c0115154669656c64204e616d650a546f204372656174650a3f0600f6080089
+0209096669656c646e616d6501020b2121212121010101170008080854657874
+446174612200000009199d014d00c8023f00020001030303030010010280a000
+00000000000000009cc89d023f000001030201070008000009ff8100009e0040
+0014030100400600780802010209096d616b656c6162656c0102042121212121
+2121211700099fff31000000099d02d59d012c010b02dd000200020303030300
+100101a0a00000000000000000009d010b9d02dd000001090a0a6d616b65206c
+6162656c00020141060078080201020d0d6d616b65646174616669656c640102
+0421212121212121211700069fff0c000000099d06409d012c010b037c000200
+030303030300100101a0a00000000000000000009d010b9d037c000001090d0d
+6d616b65646174616669656c6400020142060078080201020c0c6d616b656472
+6f70646f776e01020421212121212121211700079fff15000000099d0a179d01
+2c010b03be000200040303030300100101a0a00000000000000000009d010b9d
+03be000001090c0c6d616b6564726f70646f776e00020143060078080201020d
+0d6d616b65726164696f6c697374010204212121212121212117000a9fff3200
+0000099d029b9d0237010b0352000300020303030300100101a0a00000000000
+000000009d010b9d0352000001090d0d6d616b65726164696f6c697374000201
+44060078080201020e0e6d616b6570757368627574746f6e0102042121212121
+21212117000b9fff33000000099d060e9d0237010b03e8000300030303030300
+100101a0a00000000000000000009d010b9d03e8000001090e0e6d616b657075
+7368627574746f6e0002010b06007c08000d0008084d61696e47726964010104
+010f10111201010117000c9fff0d00000009009d06e702050205000200010303
+03030007010160600000000000000000009d02059d020500000105461001ffff
+0001f401f400040000009fff009fff0001010000470404024600002100020000
+00004706000302010000000000000c0600030209000000000000471a7e898f9c
+e29ced9d015a9d01669d01729d01df9d01eb9d01f79d02669d02729d027e9d02
+f19d02fe9d030a9d03169d03809d038b9d03979d03e99d04039d04619d04c29d
+04d09d04d89d04e29d04ea9d04f49d04fc9d05089d05109d051b9d05279d0596
+9d05a29d05ae9d061b9d06279d06339d069f9d06ab9d06b79d07099d071b9d07
+6f9d07819d07d69d07ea9d08589d08649d08709d08d39d093b9d09cd9d09de9d
+09ea9d0a3d9d0a599d0ac59d0b279d0b909d0bf79d0c609d0ccb9d0d389d0d42
+9d0d4e9d0d5a9cd9191a385e5f6b7e88898d8f9cad9cd39cd49ce09ce29cec9c
+ed9d010b9d01319d01329d013e9d01559d015a9d01649d01669d01729d01909d
+01b69d01b79d01c39d01da9d01df9d01e99d01eb9d01f79d02159d023d9d023e
+9d024a9d02619d02669d02709d02729d027e9d029c9d02c29d02c39d02cf9d02
+e89d02f19d02fb9d02fe9d030a9d03169d03349d035b9d035c9d03689d037d9d
+03809d038a9d038b9d03979d03b59d03da9d03db9d03dd9d03e99d03ed9d0403
+9d04299d04519d04529d04619d048f9d04b89d04b99d04bc9d04c09d04c29d04
+cc9d04d09d04d89d04dc9d04e29d04ea9d04ee9d04f49d04fc9d05009d05089d
+05109d05149d051b9d05279d05459d056d9d056e9d057a9d05919d05969d05a0
+9d05a29d05ae9d05cc9d05f29d05f39d05ff9d06169d061b9d06259d06279d06
+339d06519d06769d06779d06839d069a9d069f9d06a99d06ab9d06b79d06d59d
+06fa9d06fb9d06fd9d07099d070d9d071b9d07399d07609d07619d07639d076f
+9d07739d07819d079f9d07c79d07c89d07ca9d07d69d07da9d07ea9d08089d08
+2f9d08309d083c9d08539d08589d08629d08649d08709d08989d08bd9d08be9d
+08c19d08c69d08d39d08fe9d09259d09269d09299d092e9d093b9d09609d0988
+9d09899d09959d09b49d09cd9d09d79d09de9d09ea9d0a089d0a2e9d0a2f9d0a
+319d0a3d9d0a419d0a599d0a889d0aaf9d0ab09d0ab39d0ab89d0ac59d0aec9d
+0b169d0b179d0b279d0b529d0b7c9d0b7d9d0b909d0bba9d0be49d0be59d0bf7
+9d0c229d0c4c9d0c4d9d0c609d0c8c9d0cb69d0cb79d0ccb9d0cf19d0d199d0d
+1a9d0d269d0d379d0d389d0d429d0d429d0d4e9d0d5a0000
-20caa1f1
end class;
-- END CLASS DEFINITIONS
-- START SERVICE OBJECT DEFINITIONS
-- END SERVICE OBJECT DEFINITIONS
-- START CURSOR DEFINITIONS
-- END CURSOR DEFINITIONS
-- START TYPEDEF DEFINITIONS
-- END TYPEDEF DEFINITIONS
-- START METHOD DEFINITIONS
------------------------------------------------------------
method main.Init
begin
super.Init();
row = 1;
column = 1;
whichone = new;
fieldname = new;
whichone = new;
end method;
------------------------------------------------------------
method main.Display
begin
//
// Sample code to generate and work with a dyanmic screen.
//
// What we are basically doing is to create new widgets and
// parent them to a grid that is on the display. My grid
// is called MainGrid.
//
//
// Author: Jeff Nester 
// Phone:  (423)989-9515
///////////////////////////////////////////////////////////
self.Open();
//
// Set up a counter to use when creating labels.
//
TextGraphicCounter : integerdata = new(value=1);
//
// The following is setting up a Submenu called Jeff
// that has doit as an item. If you do not have a menu bar
// already you must instantiate one. My example is starting
// without a menu
//
window.menu = new;          // create the necessary holder for the menu
smenu :submenu = new;       // create a submenu
smenu.name = 'mFile';        // Name it mFile
smenu.text ='File';          // and display the item File
smenu.parent = self.window.menu; // put it on the screen
mitem : menucommand = new;  // create an item
mitem.name = 'mExit';       // the name is mExit
mitem.text = 'Exit';        // and the display message is Exit
mitem.parent = smenu;       // add it to the sub menu we set up
event loop
//
// Post the addedfield event so the screen will start with
// the correct data in the list of fields field.
    post addedfield;
    
	when task.Shutdown do
		exit;
// Make a label
//		
	when <makelabel>.click do
//
// Labels are of type textgraphic
//
  	    newfield : textgraphic = new;
	    newfield.text = fieldname.value; // set the label
//	    
// I am going to generate a unique name for the labels
//
	    n : textdata = new;
	    n.replaceparameters('Label %1',TextGraphicCounter);
	    TextGraphicCounter.setvalue(TextGraphicCounter.value + 1);
	    newfield.name = n; // set the widgets name
//
// To position the field into the appropriate cell in the
// grid we must set the row and column.
//
	    newfield.row = row;
	    newfield.column = column;
	    newfield.parent = <MainGrid>; // set grid as parent
	    column = column + 1;
        post addedfield; // Notify the screen that a field was added
//
// Add a pushbutton
//
	when <makepushbutton>.click do
//
// Verify if the field name already exists if it does
// don't let them add it again.
//
	    if CheckIfFieldExists(fieldname) then
	       self.window.messagedialog('Field with name already exists!');
	       continue;
	    end if;	    
	    newfield : pushbutton = new; // Create the button widget
	    newfield.label = fieldname.value; // set its label
	    newfield.name = fieldname.value;  // set its name
//
// To position the field into the appropriate cell in the
// grid we must set the row and column.
//
	    newfield.row = row;
	    newfield.column = column;
	    newfield.height = 250;  // set button height
	    newfield.parent = <MainGrid>; // set grid as parent
	    column = column + 1;
        post addedfield; // notify form that it has added a field
//
// Make a DataField
//
	when <makedatafield>.click do
	    if CheckIfFieldExists(fieldname) then
	       self.window.messagedialog('Field with name already exists!');
	       continue;
	    end if;
	    newfield : datafield = new;
	    newfield.name = fieldname.value; // set the field name
	    newfield.textvalue = 'test';     // set a default value
	    newfield.row = row;              // set location to insert
	    newfield.column = column;
	    newfield.parent = <MainGrid>;    // define parent
	    column = column + 1;	    
        post addedfield;                 // notify the list of fields field
//
// Make a drop down list
//
	when <makedropdown>.click do
	    if CheckIfFieldExists(fieldname) then
	       self.window.messagedialog('Field with name already exists!');
	       continue;
	    end if;
	    newfield : droplist = new;  // create the new widget
	    newfield.name=fieldname.value; // set its name
//
// The next several lines are to create the array of listelements
// to set the droplist to
//
	    tmp : listelement = new; 
	    tmp.textvalue='One';
	    tmparray : array of listelement = new;
	    tmparray.appendrow(tmp);
	    tmp = new;
	    tmp.textvalue  ='Two';
	    tmparray.appendrow(tmp);
//	    
	    newfield.setelementlist(tmparray); // set the element list
	    newfield.row = row; // set the insert point
	    newfield.column = column;
	    newfield.textvalue = tmparray[1].textvalue;
	    newfield.parent = <MainGrid>;  // define the parent
	    column = column + 1;   
        post addedfield;  // notify the list all fields field
        
//
// Make a radio list
//        
	when <makeradiolist>.click do
	    if CheckIfFieldExists(fieldname) then
	       self.window.messagedialog('Field with name already exists!');
	       continue;
	    end if;
	    newfield : radiolist  = new;  // create new widget
	    newfield.name=fieldname.value;// set its name
//
// Set up the array of listelements that we need for the 
// radio button
//
	    tmp : listelement = new;
	    tmp.textvalue='One';
	    tmp.integervalue = 1;
	    tmparray : array of listelement = new;
	    tmparray.appendrow(tmp);
	    tmp = new;
	    tmp.textvalue  ='Two';
	    tmparray.appendrow(tmp);
//
	    newfield.setelementlist(tmparray); // set the widget
	    newfield.row = row;			       // define the insert position
	    newfield.column = column;
	    newfield.parent = <MainGrid>;      // set the parent
	    column = column + 1;   
        post addedfield; 			    // notify the list all fields field
//
// When you double click on the list of fields or select
// one and click on the getvalue button we want to go get
// the data associated with the field
//
    when <whichone>.doubleclick do
       post getval;
	when <getvalue>.click do
 	   post getval;
//
// This code actually retrieves the data that is stored in the
// field
//
 	when getval do
       tmp : textdata = new;
//
// Use GetFieldByName to retrieve the particular fieldwidget
       fieldobj : fieldwidget = <maingrid>.getfieldbyname(whichone);
//
// Since different kind of widgets store their data differently
// you must cast the object to get to the appropriate attributes
//
       if fieldobj <> NIL then
          if fieldobj.isa(datafield) then
             self.window.messagedialog((datafield)(fieldobj).textvalue);
          elseif fieldobj.isa(droplist) then
             self.window.messagedialog((droplist)(fieldobj).textvalue);
          elseif fieldobj.isa(radiolist) then
              self.window.messagedialog((radiolist)(fieldobj).textvalue); 
          elseif fieldobj.isa(textgraphic) then
              self.window.messagedialog((textgraphic)(fieldobj).text);
          elseif fieldobj.isa(pushbutton) then
              self.window.messagedialog((pushbutton)(fieldobj).label);         
          else
             self.Window.messagedialog('Dont know the field type');
          end if;
       else
          self.window.messagedialog ('No such field');
       end if;
//
// To trap a click on a dynamic button you must catch ChildClick
// on the grid and then evaluate what was clicked on and then take
// appropriate action
//
    when <maingrid>.ChildClick (DE=eventInfo, FW=child, x=x, y=y, mod=modifier, Node=node, row=row, col=column) do
       if fw.isa(pushbutton) then
          tmp : textdata = new;
          tmp.ReplaceParameters(
                'PushButton: %1 was pushed.',
                (pushbutton)(fw).name);
          self.window.messagedialog(tmp);
       end if;
//
// The addedfield event tells us to update the whichone field
// this field is where I show the list of fields. I am updating
// it this way to show how to run through all of the fields in the
// grid.
//
    when addedfield do
       tmp : array of listelement = new;
       tmp2 : listelement;
//
// Performing a For loop through <grid>.Children will return
// all children of the grid.
//
       for fw in <maingrid>.children do
          tmp2 = new;
          tmp2.textvalue.setvalue(fw.name);
          tmp.appendrow(tmp2);
       end for;
       <whichone>.setelementlist( tmp );
//
// To catch activation of the dyanmically created menu bars you
// have to listen for menu.childactivate and then determine
// which one was activated and then take what ever action you 
// need to
//
    when self.window.menu.childactivate (m = child ) do
        if (m.name.isequal('mExit')) then
           post task.shutdown;
        end if;
end event;
self.Close();
end method;
------------------------------------------------------------
method main.CheckIfFieldExists(input FieldName: Framework.TextData): boolean
begin
       fieldobj : fieldwidget = <maingrid>.getfieldbyname(FieldName);
       if fieldobj <> NIL then
          return TRUE;
       end if;
       return FALSE;
end method;
-- END METHOD DEFINITIONS
HAS PROPERTY
	CompatibilityLevel = 0;
	ProjectType = APPLICATION;
	Restricted = FALSE;
	MultiThreaded = TRUE;
	LibraryName = 'dynoscre';
	StartingMethod = (class = main, method = Display);
end dynoscreen;
 |