26

Re: Creating form with objects on it programatically

cetinbasoz yazdı:


Also I repeat that you should avoid & as much as possible. & doesn't have a use case in VFP except in some SQL strings.

Okay, let me comment on this too.

It might sound silly, but I do not really know what the alternative to

.Caption = lcCaption&ixxx

in he code below is in order to avoid "&".

Visual Fox Pro
FOR ix = 1 TO lnRecCnt

 
    WITH THISFORM.cntMenuContainer.cmgMenuGroup.buttons[m.ix]
 
        ixxx = STR(ix,1)
 
        .Caption = lcCaption&ixxx
 
        .AutoSize = .T.
 
        .Forecolor = &lcCmdForeColor
 
        .Backcolor = &lcCmdBackColor
 
        .Top  = ((m.ix - 1) * 1.5 * .Height) + lnBtwButtons
 
        .Left = 10
 
        lnButtonHeight = .Height
 
        IF lnButtonWidth < .Width
 
            lnButtonWidth = .Width
 
        ENDIF
 
        .AutoSize = .F.
 
    ENDWITH
 
ENDFOR

Regards,

Hans L

27

Re: Creating form with objects on it programatically

evaluate( 'm.lcCmdForeColor' + m.ixxx )

28

Re: Creating form with objects on it programatically

Thanks for the replacement of "&".

By the way, by changing

THISFORM.cntMenuContainer.NewObject('cmgMenuGroup','clCommandGroup')

to

THISFORM.cntMenuContainer.NewObject('cmgMenuGroup','clCommandGroup','main_menu_again.prg')

it seems as if I have gotten this whole thing to work. Boy, am I relieved (I need to get to the next step, which is a list of records, for which I will use one of the Foxy Classes).

But, man, have I learned a lot during this excruciating (:-) process!!!

Hans L

29

Re: Creating form with objects on it programatically

cetinbasoz yazdı:


  For ix=1 To m.lnRecordCount
\      Case This.Value = << m.ix >>
\        << EVL(EVALUATE( 'm.lcClick' + LTRIM(STR( m.ix ))),'') >>
  Endfor

Cetin, I assume that "EVL" above should be "EVAL".

Hans L

30

Re: Creating form with objects on it programatically

Darn, I lost my whole post. Don't know what happened. Trying again.

What is a Sunday without 10 hours of futile programming big_smile

As I mentioned, I am trying to put menu option text and click commands in the same place, in this case in a form method, looking like this:

Visual Fox Pro
*  Method "Set_up_menu" in form "frmMainmenu"

 
 
Local ix, ixxx, lnButtonHeight, lnButtonWidth, lnRecCnt, lnContTop, lnContLeft, lnTopPart, ;
        lcClick1, lcClick2, lcClick3, lcClick4, lcClick5, lcClick6, lcClick7, lcClick8, lcClick9
 
 
 
Store 0 To lnRecCnt
 
lnContTop = 200      && Top of container
 
lnContLeft = 500     && Left of container
 
* lnButtonHeight = 30  && Height of buttons
 
lnButtonWidth = 0  && Will become width of all butttons
 
lnBtwButtons = 15    && Distance between buttons as well as between buttons and top/bottom of commandgroup
 
lnTopPart = 60  && Distane between top of container and top of commandgroup
 
lcFrmBackColor = "RGB(211,223,254)"
 
lcCntBackColor = "RGB(205,200,245)"
 
lcCmgBackColor = "RGB(191,166,191)"
 
lcCmdForeColor = "RGB(255,255,255)"
 
lcCmdBackColor = "RGB(0,0,100)"
 
lcLblForeColor = "RGB(0,0,0)"
 
*
* CREATE CURSOR BUTTON GROUP
*
 
Create Cursor curCommandGroup (ButtonCaption c(25))  && Max 25 characters, max 9 menu options.
 
Insert Into curCommandGroup  Values ('\<')
Insert Into curCommandGroup  Values ('\<Applications')
Insert Into curCommandGroup  Values ('\<')
Insert Into curCommandGroup  Values ('\<')
Insert Into curCommandGroup  Values ('\<Hardware')
Insert Into curCommandGroup  Values ('\<')
Insert Into curCommandGroup  Values ('\<')
Insert Into curCommandGroup  Values ('\<Settings')  && This must be next to the last menu option.
Insert Into curCommandGroup  Values ('\<Exit')      && This must be the last menu option.
 
 
* ============================  Code in click method  ==========
 
 
TEXT TO lcClick1  && Code for 1st button above
 
Just any command.
 
ENDTEXT
 
* --------------------------------------------
 
TEXT TO lcClick2  && Code for 2nd button above
 
Just any command.
 
ENDTEXT
 
* --------------------------------------------
 
TEXT TO lcClick3  && Code for 3rd button above
 
Just any command.
ENDTEXT
 
* --------------------------------------------
 
 
TEXT TO lcClick4  && Code for 4th button above
 
THISFORM.Release
CLEAR EVENTS
 
ENDTEXT
 
* --------------------------------------------
 
 
TEXT TO lcClick5  && Code for 5th button above
 
[No commands here or later, because I only need 4 buttons in this menu]
 
ENDTEXT
 
* --------------------------------------------
 
 
TEXT TO lcClick6  && Code for 6th button above
 
 
 
ENDTEXT
 
* --------------------------------------------
 
 
TEXT TO lcClick7  && Code for 7th button above
 
 
 
ENDTEXT
 
* --------------------------------------------
 
 
TEXT TO lcClick8  && Code for 8th button above
 
 
 
ENDTEXT
 
* --------------------------------------------
 
 
TEXT TO lcClick9  && Code for 9th button above
 
 
 
ENDTEXT
 
 
 
* ==============================================================================================
 
 
Thisform.Newobject('cntMenuContainer','Container')  && Creating a container
 
Thisform.Newobject('lblAppdescr','Label')  && Creating an application description label
 
Thisform.Newobject('lblCopyright','Label')  && Creating a copyright label
 
Thisform.cntMenuContainer.Newobject('lblMainmenu','Label')  && Creating Label
 
Thisform.cntMenuContainer.Newobject('linMainmenu','Line')  && Creating Line
 
 
* ==============================================================================================
 
SCAN FOR LEN(TRIM(ButtonCaption)) > 2
 
    lnRecCnt = lnRecCnt + 1
 
    lnRecCnt_C = STR(lnRecCnt,1)
 
    lcCaption&lnRecCnt_C = TRIM(ButtonCaption)
 
ENDSCAN
 
*
 
DO TwsMainMenu.prg WITH lcClick1, lcClick2, lcClick3, lcClick4, lcClick5, lcClick6, lcClick7, lcClick8, lcClick9, lnRecCnt
 
*
 
THISFORM.cntMenuContainer.NewObject('cmgMenuGroup','clCommandGroup','twsmainmenu.prg')
 
FOR ix = 1 TO lnRecCnt
 
    WITH THISFORM.cntMenuContainer.cmgMenuGroup.buttons[m.ix]
 
        ixxx = STR(ix,1)
 
        .Caption = lcCaption&ixxx
 
        .AutoSize = .T.
 
        .Forecolor = &lcCmdForeColor
 
        .Backcolor = &lcCmdBackColor
 
        .Top  = ((m.ix - 1) * 1.5 * .Height) + lnBtwButtons
 
        .Left = 10
 
        lnButtonHeight = .Height
 
        IF lnButtonWidth < .Width
 
            lnButtonWidth = .Width
 
        ENDIF
 
        .AutoSize = .F.
 
    ENDWITH
 
ENDFOR
 
 
FOR ix = 1 TO lnRecCnt
 
    THISFORM.cntMenuContainer.cmgMenuGroup.buttons[m.ix].Width = lnButtonWidth  && Setting (same) width for all buttons
 
ENDFOR
 
 
 
*
*  SET VALUES FOR COMMANDGROUP
*
 
WITH THISFORM.cntMenuContainer.cmgMenuGroup  && CommandGroup
 
    .Backcolor = &lcCmgBackColor
 
    .Top = lnTopPart  && From container top
 
    .Left = 10    && From container left
 
    .Height = (.ButtonCount * lnButtonHeight) + ((.ButtonCount + 1) * lnBtwButtons)
 
    .Width = lnButtonWidth + 20
 
    .SetAll('Visible',.T.)
 
    .Visible = .T.
 
ENDWITH
 
 
*
*  SET VALUES FOR CONTAINER, LABEL & LINE
*
 
WITH THISFORM.cntMenuContainer  && Container
 
    .Backcolor = &lcCntBackColor
 
    .Top = lnContTop  && Container top
 
    .Left = lnContLeft    && Container left
 
    .Height = .cmgMenuGroup.Height + 75  && Container height
 
    .Width = .cmgMenuGroup.Width + 20  && Container width
 
    .Visible = .T.  && Container visible
 
    *
 
    WITH .lblMainmenu  && Label ("MAIN MENU")
 
        .Caption = 'MAIN MENU'
 
        .BackStyle = 0
 
        .ForeColor = &lcLblForeColor
 
        .FontSize = 12
 
        .AutoSize = .T.
 
        .Top = (lnTopPart /2) - (.Height/2)
 
        .Left = (Thisform.cntMenuContainer.Width/2) - (.Width/2)
 
        .Alignment = 2
 
        .Visible = .T.
 
    ENDWITH
 
    *
 
    WITH .linMainmenu  && Line
 
        .Top = 50
 
        .Left = 0
 
        .Height = 0
 
        .Width = Thisform.cntMenuContainer.Width
 
        .Visible = .T.
 
    ENDWITH
 
ENDWITH
 
 
*
* SETTING VALUES FOR FORM LABELS (2)
*
 
WITH Thisform.lblAppdescr
 
    .Caption = 'TERMINOLOGY WEB SEARCH'
 
    .BackStyle = 0
 
    .FontSize = 16
 
    .AutoSize = .T.
 
    .Top = lnContTop - 50
 
    .Left = lnContLeft + (Thisform.cntMenuContainer.Width/2) - (.Width/2)
 
    .Alignment = 2
 
    .Visible = .T.
 
ENDWITH   
 
*
 
WITH Thisform.lblCopyright
 
    .Caption = '© Copyright TransManage Software 2010'
 
    .Backstyle = 0
 
    .FontSize = 8
 
    .AutoSize = .T.
 
    .Top = lnContTop + Thisform.cntMenuContainer.Height + 50
 
    .Left = lnContLeft + (Thisform.cntMenuContainer.Width/2) - (.Width/2)
 
    .Alignment = 2
 
    .Visible = .T.
 
ENDWITH   
 
 
Thisform.BackColor = &lcFrmBackColor

The file that is called from the method is twsmainmenu.prg (I have changed the names a little and cleaned up here and there). It looks like this:

Visual Fox Pro
*  twsmainmenu.prg

 
 
LPARAMETERS lcClick1, lcClick2, lcClick3, lcClick4, lcClick5, lcClick6, lcClick7, lcClick8, lcClick9, lnRecCnt
 
LOCAL ixx  &&, lcMyClass
 
* SET TEXTMERGE TO Memvar lcMyClass Noshow
 
* SET TEXTMERGE ON
 
*
 
DEFINE CLASS clCommandGroup AS CommandGroup
 
    *
 
    ButtonCount = lnRecCnt
 
    *
 
    PROCEDURE Click
 
        DO CASE
 
            FOR ixx = 1 TO m.lnRecCnt
 
                CASE This.Value = EVALUATE(m.ixx)
 
                        EVALUATE( 'm.lcClick' + LTRIM(STR( m.ixx )))
 
            ENDFOR
 
        ENDCASE
 
    ENDPROC
 
ENDDEFINE
 
 
*SET TEXTMERGE TO
 
*SET TEXTMERGE OFF
 
*RETURN m.lcMyClass

I know that you had "\" and "\\" and "textmerge" and stuff, and I tried it, but still did not get the click event to work. The reason I do not call a procedure, but rather a prg file,  from the form method is that an error message eons ago told me that I could not define a class within a procedure. And, still, your code has a define class within a procedure. I am confused about that, but it does not matter, because these days, it is a constant state of my mind.

The only reason I do not cry at this stage is that I am a man, and men do not cry tongue

Any way to get the click events to work based on what I have, with appropriate changes, of course?

Thanks for you immense patience.

Hans L

31

Re: Creating form with objects on it programatically

Oh, let me mention that I start here (main.prg):

Visual Fox Pro
* 

 
*  MAIN FILE
 
*  Settings for this application
*
*CLEAR CLASSLIB "D:\VFP apps\Classes\hplBaseClasses"
*CLEAR ALL
*CLEAR PROGRAM
*CLOSE ALL
*
*
SET TALK OFF
SET BELL OFF
SET CONFIRM ON
SET CENTURY ON
SET DELETED ON
SET EXCLUSIVE ON
SET HEADINGS OFF
SET SECONDS OFF
SET STATUS OFF
SET STATUS BAR OFF
SET SYSMENU OFF
SET NULLDISPLAY TO '-'
*
*
*
SET DEFAULT TO SYS(5) + SYS(2003)
*
SET PATH TO ;
BITMAPS, DATA, FORMS, INCLUDE, LIBS, PROGS, REPORTS, D:\DATABASES\CLASS LIBRARIES\HANS FOXY CLASSES, ;
D:\DATABASES\CLASS LIBRARIES\HANS VFP COMMON CLASSES, D:\DATABASES\CLASS LIBRARIES\HANS VFP COMMON SUBCLASSES
 
 
 
*OPEN DATABASE Mysoft && EXCLUSIVE
*SET MULTILOCKS ON
*
*  SET PROCEDURE TO main_menu_again.prg   && Procfile
*
*
DO FORM Mainmenu
READ EVENTS
*
*  Resettings for this application
*
*
SET NULLDISPLAY TO 'NULL'
SET BELL ON
SET CENTURY OFF
SET CONFIRM OFF
SET DELETED OFF
SET EXCLUSIVE OFF
SET HEADINGS ON
SET SECONDS ON
SET STATUS ON
SET STATUS BAR ON
SET SYSMENU ON
SET TALK ON
*
* End resetting for this application
*
CLEAR ALL
CLOSE ALL
QUIT

32

Re: Creating form with objects on it programatically

evl() was Evl() and not Eval(). evl() is a new function and shortcut for:

iif( empty( v1 ), v2, v1 ) && evl( v1, v2 ) - if v1 is empty use v2 else v1

I told that you cannot define a class within a procedure. However I am not defining a class within a procedure but 'typing' some code which happens to be a class definition within a procedure. It is like we did in old days:

set alternate to ...
? ...
? ...

and the file had some content. Instead now using 'textmerge' I do the same thing writing into a memory variable. First I will provide you a working version of your code. Then using that code will try to go backwards how, why and why not (it works, but it doesn't mean it is the way to do that. You are inventing sort of your own framework as I understood but its maintenance would be very hard IMHO). Anyway let's start with working version:

*  twsmainmenu.prg

Visual Fox Pro
Lparameters lcClick1, lcClick2, lcClick3, lcClick4, lcClick5, lcClick6, lcClick7, lcClick8, lcClick9, lnRecCnt

 
Local ixx  , lcMyClassCode
Set Textmerge To Memvar lcMyClassCode Noshow
Set Textmerge On
\\DEFINE CLASS clCommandGroup AS CommandGroup
*
\    ButtonCount = << m.lnRecCnt >>
*
 
\    PROCEDURE Click
\        DO CASE
For ixx = 1 To m.lnRecCnt
\                CASE This.Value = << m.ixx >>
\                      << EVL(EVALUATE( 'm.lcClick' + LTRIM(STR( m.ixx ))),'') >>
Endfor
\        ENDCASE
\    ENDPROC
\ENDDEFINE
Set Textmerge To
Set Textmerge Off
Return m.lcMyClassCode

And a form using that within a Set_Up_menu procedure (your code with some revisions, especially removing &:):

Visual Fox Pro
Clear All

Public oForm
oForm = Createobject('MainMenu')
oForm.Show()
 
Define Class mainMenu As Form
  Height = 600
  Width = 800
  Procedure Init
    This.Set_Up_Menu()
  Endproc
 
  Procedure Destroy
    Clear Class ('clCommandGroup')
  Endproc
 
  Procedure Set_Up_Menu
    *  Method "Set_up_menu" in form "frmMainmenu"
 
    Local ix, ixxx, lnButtonHeight, lnButtonWidth, lnRecCnt, lnContTop, lnContLeft, lnTopPart, ;
      lcClick1, lcClick2, lcClick3, lcClick4, lcClick5, lcClick6, lcClick7, lcClick8, lcClick9
 
 
    lnContTop = 200      && Top of container
    lnContLeft = 500     && Left of container
    * lnButtonHeight = 30  && Height of buttons
    lnButtonWidth = 0  && Will become width of all butttons
    lnBtwButtons = 15    && Distance between buttons as well as between buttons and top/bottom of commandgroup
    lnTopPart = 60  && Distane between top of container and top of commandgroup
    lcFrmBackColor = Rgb(211,223,254)
    lcCntBackColor = Rgb(205,200,245)
    lcCmgBackColor = Rgb(191,166,191)
    lcCmdForeColor = Rgb(255,255,255)
    lcCmdBackColor = Rgb(0,0,100)
    lcLblForeColor = Rgb(0,0,0)
 
    *
    * CREATE CURSOR BUTTON GROUP
    *
 
    Create Cursor curCommandGroup (ButtonCaption c(25))  && Max 25 characters, max 9 menu options.
 
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<Applications')
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<Hardware')
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<Settings')  && This must be next to the last menu option.
    Insert Into curCommandGroup  Values ('\<Exit')      && This must be the last menu option.
 
 
    * ============================  Code in click method  ==========
 
 
    TEXT TO lcClick1  && Code for 1st button above
 
MESSAGEBOX('Just any command. - 1')
 
    ENDTEXT
 
    * --------------------------------------------
 
    TEXT TO lcClick2  && Code for 2nd button above
 
MESSAGEBOX('Just any command. - 2')
 
    ENDTEXT
 
    * --------------------------------------------
 
    TEXT TO lcClick3  && Code for 3rd button above
 
MESSAGEBOX('Just any command. - 3')
 
    ENDTEXT
 
    * --------------------------------------------
 
 
    TEXT TO lcClick4  && Code for 4th button above
 
CLEAR EVENTS
THISFORM.Release
 
    ENDTEXT
 
    * --------------------------------------------
 
 
    TEXT TO lcClick5  && Code for 5th button above
 
MESSAGEBOX( [No commands here or later, because I only need 4 buttons in this menu] )
 
    ENDTEXT
 
    * --------------------------------------------
 
    * ==============================================================================================
 
 
    Thisform.Newobject('cntMenuContainer','Container')  && Creating a container
    Thisform.Newobject('lblAppdescr','Label')  && Creating an application description label
    Thisform.Newobject('lblCopyright','Label')  && Creating a copyright label
    Thisform.cntMenuContainer.Newobject('lblMainmenu','Label')  && Creating Label
    Thisform.cntMenuContainer.Newobject('linMainmenu','Line')  && Creating Line
 
    * ==============================================================================================
 
 
    Store 0 To lnRecCnt
    Scan For Len(Trim(ButtonCaption)) > 2
      lnRecCnt = m.lnRecCnt + 1
      Store Trim(ButtonCaption) To ( 'm.lcCaption'+Ltrim(Str(m.lnRecCnt)) )
    Endscan
 
    Local lcClassCode, lcCodeFile
 
    lcClassCode = TwsMainMenu(m.lcClick1, m.lcClick2, m.lcClick3, m.lcClick4, ;
      m.lcClick5, m.lcClick6, m.lcClick7, m.lcClick8, m.lcClick9, m.lnRecCnt)
 
    lcCodeFile=Forcepath('MyClass.prg',Sys(2023))
    Strtofile( m.lcClassCode, m.lcCodeFile)
    Compile (m.lcCodeFile)
 
    Thisform.cntMenuContainer.Newobject('cmgMenuGroup','clCommandGroup',m.lcCodeFile)
    Thisform.cntMenuContainer.Visible = .T.
 
    For ix = 1 To lnRecCnt
      With Thisform.cntMenuContainer.cmgMenuGroup.Buttons[m.ix]
        .Caption = Evaluate( 'm.lcCaption'+Ltrim(Str(m.ix)) )
        .AutoSize = .T.
        .ForeColor = m.lcCmdForeColor
        .BackColor = m.lcCmdBackColor
        .Top  = ((m.ix - 1) * 1.5 * .Height) + m.lnBtwButtons
        .Left = 10
        lnButtonHeight = .Height
        If m.lnButtonWidth < .Width
          lnButtonWidth = .Width
        Endif
        .AutoSize = .F.
      Endwith
    Endfor
 
    For ix = 1 To lnRecCnt
      Thisform.cntMenuContainer.cmgMenuGroup.Buttons[m.ix].Width = lnButtonWidth  && Setting (same) width for all buttons
    Endfor
 
    *
    *  SET VALUES FOR COMMANDGROUP
    *
    With Thisform.cntMenuContainer.cmgMenuGroup  && CommandGroup
      .BackColor = m.lcCmgBackColor
      .Top = lnTopPart  && From container top
      .Left = 10    && From container left
      .Height = (.ButtonCount * lnButtonHeight) + ((.ButtonCount + 1) * lnBtwButtons)
      .Width = lnButtonWidth + 20
      .SetAll('Visible',.T.)
      .Visible = .T.
    Endwith
 
    *
    *  SET VALUES FOR CONTAINER, LABEL & LINE
    *
    With Thisform.cntMenuContainer  && Container
      .BackColor = m.lcCntBackColor
      .Top = lnContTop  && Container top
      .Left = lnContLeft    && Container left
      .Height = .cmgMenuGroup.Height + 75  && Container height
      .Width = .cmgMenuGroup.Width + 20  && Container width
      .Visible = .T.  && Container visible
      *
 
      With .lblMainmenu  && Label ("MAIN MENU")
        .Caption = 'MAIN MENU'
        .BackStyle = 0
        .ForeColor = m.lcLblForeColor
        .FontSize = 12
        .AutoSize = .T.
        .Top = (lnTopPart /2) - (.Height/2)
        .Left = (Thisform.cntMenuContainer.Width/2) - (.Width/2)
        .Alignment = 2
        .Visible = .T.
      Endwith
 
      *
      With .linMainmenu  && Line
        .Top = 50
        .Left = 0
        .Height = 0
        .Width = Thisform.cntMenuContainer.Width
        .Visible = .T.
      Endwith
    Endwith
 
 
    *
    * SETTING VALUES FOR FORM LABELS (2)
    *
 
    With Thisform.lblAppdescr
      .Caption = 'TERMINOLOGY WEB SEARCH'
      .BackStyle = 0
      .FontSize = 16
      .AutoSize = .T.
      .Top = lnContTop - 50
      .Left = lnContLeft + (Thisform.cntMenuContainer.Width/2) - (.Width/2)
      .Alignment = 2
      .Visible = .T.
    Endwith
 
    *
 
    With Thisform.lblCopyright
      .Caption = '© Copyright TransManage Software 2010'
      .BackStyle = 0
      .FontSize = 8
      .AutoSize = .T.
      .Top = lnContTop + Thisform.cntMenuContainer.Height + 50
      .Left = lnContLeft + (Thisform.cntMenuContainer.Width/2) - (.Width/2)
      .Alignment = 2
      .Visible = .T.
    Endwith
 
 
    Thisform.BackColor = m.lcFrmBackColor
  Endproc
Enddefine

33

Re: Creating form with objects on it programatically

Now what is wrong with this code though it works.

Visual Fox Pro
Text to lcClick1 ...

 
text to lcClick9
 
endtext

and then:

Visual Fox Pro
lcClassCode = TwsMainMenu(m.lcClick1, m.lcClick2, m.lcClick3, m.lcClick4, ;

      m.lcClick5, m.lcClick6, m.lcClick7, m.lcClick8, m.lcClick9, m.lnRecCnt)
 
    lcCodeFile=Forcepath('MyClass.prg',Sys(2023))
    Strtofile( m.lcClassCode, m.lcCodeFile)
    Compile (m.lcCodeFile)

This part of the code's all purpose is to create the FXP file ('MyClass.prg') with a commandgroup class definition in it. Defining and compileing is something that needs to be done once, however code is doing that with each run. And if we look closely, we are already writing the class' body with a series of text .. endtext. It just adds complexity IMHO. Having a cursor for button captions do not have an importance either but we could live wih it. A revised version might be like:

*  twsmainmenu.prg

Visual Fox Pro
Define Class clCommandGroup As CommandGroup

  ButtonCount = 4
 
  Procedure Click
    Do Case
      Case This.Value = 1
        Messagebox('Just any command. - 1')
      Case This.Value = 2
        Messagebox('Just any command. - 2')
      Case This.Value = 3
        Messagebox('Just any command. - 3')
      Case This.Value = 4
        Clear Events
        Thisform.Release
    Endcase
  Endproc
Enddefine

As you see we moved click method bodies from text...endtext into class definiton where it is much easier to maintain. Then the form code as revised:

Visual Fox Pro
Public oForm

oForm = Createobject('MainMenu')
oForm.Show()
 
Define Class mainMenu As Form
  Height = 600
  Width = 800
  Procedure Init
    This.Set_Up_Menu()
  Endproc
 
  Procedure Set_Up_Menu
    *  Method "Set_up_menu" in form "frmMainmenu"
 
    Local ix, ixxx, lnButtonHeight, lnButtonWidth, lnRecCnt, lnContTop, lnContLeft, lnTopPart, ;
      lcClick1, lcClick2, lcClick3, lcClick4, lcClick5, lcClick6, lcClick7, lcClick8, lcClick9
 
 
    lnContTop = 200      && Top of container
    lnContLeft = 500     && Left of container
    * lnButtonHeight = 30  && Height of buttons
    lnButtonWidth = 0  && Will become width of all butttons
    lnBtwButtons = 15    && Distance between buttons as well as between buttons and top/bottom of commandgroup
    lnTopPart = 60  && Distane between top of container and top of commandgroup
    lcFrmBackColor = Rgb(211,223,254)
    lcCntBackColor = Rgb(205,200,245)
    lcCmgBackColor = Rgb(191,166,191)
    lcCmdForeColor = Rgb(255,255,255)
    lcCmdBackColor = Rgb(0,0,100)
    lcLblForeColor = Rgb(0,0,0)
 
    *
    * CREATE CURSOR BUTTON GROUP
    *
 
    Create Cursor curCommandGroup (ButtonCaption c(25))  && Max 25 characters, max 9 menu options.
 
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<Applications')
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<Hardware')
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<')
    Insert Into curCommandGroup  Values ('\<Settings')  && This must be next to the last menu option.
    Insert Into curCommandGroup  Values ('\<Exit')      && This must be the last menu option.
 
 
    * ==============================================================================================
 
 
    Thisform.Newobject('cntMenuContainer','Container')  && Creating a container
    Thisform.Newobject('lblAppdescr','Label')  && Creating an application description label
    Thisform.Newobject('lblCopyright','Label')  && Creating a copyright label
    Thisform.cntMenuContainer.Newobject('lblMainmenu','Label')  && Creating Label
    Thisform.cntMenuContainer.Newobject('linMainmenu','Line')  && Creating Line
 
    * ==============================================================================================
 
 
    Store 0 To lnRecCnt
    Scan For Len(Trim(ButtonCaption)) > 2
      lnRecCnt = m.lnRecCnt + 1
      Store Trim(ButtonCaption) To ( 'm.lcCaption'+Ltrim(Str(m.lnRecCnt)) )
    Endscan
 
    Thisform.cntMenuContainer.Newobject('cmgMenuGroup','clCommandGroup','TwsMainMenu.prg')
    Thisform.cntMenuContainer.Visible = .T.
 
    For ix = 1 To lnRecCnt
      With Thisform.cntMenuContainer.cmgMenuGroup.Buttons[m.ix]
        .Caption = Evaluate( 'm.lcCaption'+Ltrim(Str(m.ix)) )
        .AutoSize = .T.
        .ForeColor = m.lcCmdForeColor
        .BackColor = m.lcCmdBackColor
        .Top  = ((m.ix - 1) * 1.5 * .Height) + m.lnBtwButtons
        .Left = 10
        lnButtonHeight = .Height
        If m.lnButtonWidth < .Width
          lnButtonWidth = .Width
        Endif
        .AutoSize = .F.
      Endwith
    Endfor
 
    For ix = 1 To lnRecCnt
      Thisform.cntMenuContainer.cmgMenuGroup.Buttons[m.ix].Width = lnButtonWidth  && Setting (same) width for all buttons
    Endfor
 
    *
    *  SET VALUES FOR COMMANDGROUP
    *
    With Thisform.cntMenuContainer.cmgMenuGroup  && CommandGroup
      .BackColor = m.lcCmgBackColor
      .Top = lnTopPart  && From container top
      .Left = 10    && From container left
      .Height = (.ButtonCount * lnButtonHeight) + ((.ButtonCount + 1) * lnBtwButtons)
      .Width = lnButtonWidth + 20
      .SetAll('Visible',.T.)
      .Visible = .T.
    Endwith
 
    *
    *  SET VALUES FOR CONTAINER, LABEL & LINE
    *
    With Thisform.cntMenuContainer  && Container
      .BackColor = m.lcCntBackColor
      .Top = lnContTop  && Container top
      .Left = lnContLeft    && Container left
      .Height = .cmgMenuGroup.Height + 75  && Container height
      .Width = .cmgMenuGroup.Width + 20  && Container width
      .Visible = .T.  && Container visible
      *
 
      With .lblMainmenu  && Label ("MAIN MENU")
        .Caption = 'MAIN MENU'
        .BackStyle = 0
        .ForeColor = m.lcLblForeColor
        .FontSize = 12
        .AutoSize = .T.
        .Top = (lnTopPart /2) - (.Height/2)
        .Left = (Thisform.cntMenuContainer.Width/2) - (.Width/2)
        .Alignment = 2
        .Visible = .T.
      Endwith
 
      *
      With .linMainmenu  && Line
        .Top = 50
        .Left = 0
        .Height = 0
        .Width = Thisform.cntMenuContainer.Width
        .Visible = .T.
      Endwith
    Endwith
 
 
    *
    * SETTING VALUES FOR FORM LABELS (2)
    *
 
    With Thisform.lblAppdescr
      .Caption = 'TERMINOLOGY WEB SEARCH'
      .BackStyle = 0
      .FontSize = 16
      .AutoSize = .T.
      .Top = lnContTop - 50
      .Left = lnContLeft + (Thisform.cntMenuContainer.Width/2) - (.Width/2)
      .Alignment = 2
      .Visible = .T.
    Endwith
 
    *
 
    With Thisform.lblCopyright
      .Caption = '© Copyright TransManage Software 2010'
      .BackStyle = 0
      .FontSize = 8
      .AutoSize = .T.
      .Top = lnContTop + Thisform.cntMenuContainer.Height + 50
      .Left = lnContLeft + (Thisform.cntMenuContainer.Width/2) - (.Width/2)
      .Alignment = 2
      .Visible = .T.
    Endwith
 
 
    Thisform.BackColor = m.lcFrmBackColor
  Endproc
Enddefine

34

Re: Creating form with objects on it programatically

Damn terrific, Cetin. Thank you! I'll report back.

Hans L

35

Re: Creating form with objects on it programatically

You could further instead of defining that command group in code, could visually create a Command Group class and set its properties there and keep in a vcx. Then you would simply drag&drop that command group class form on to form and see the end result during design. That is a better approach if you know the content at design time (BTW, VCX, SCX, ... are tables, so doing that visually is in fact a data driven approach).

36

Re: Creating form with objects on it programatically

I was drawn to the coding approach because I felt I had a better overview of what was going on than if I created a number of custom properties and methods in a form and wrote code in them all. I am sure I will have reason to revisit this approach later, when I know more about VFP.

Now, I have started trying to get a feel for the relationships between cursors, SELECT-SQL and tables, including buffering. My initial belief is that CREATE CURSOR is less vesatile than SELECT-SQL (which also creates a cursor, if I am not mistaken). The relationship between a cursor and a buffered table is at this moment not clear to me at all, but I have a few books and VFP Help to consult, so that is where I will begin. I have not used SELECT-SQL in practice (I looked at it a few years ago), but it is a good way to go, I understand. But that is for another day (probably Wednesday :-).

Hans L

37

Re: Creating form with objects on it programatically

Create Cursor - is versatile when you need to have a 'table' but have it only temporarily.

To make it easy, think that anything (table/cursor based including remote view, SQL pass through, CursorAdapter) in VFP is Cursor. When you have a table in use (whether buffered or not) you can say that you have a read write cursor. There are a few slight differences between a table and a cursor and within the type of cursors but they have 99% commonality. To tell it otherwise, a cursor is in-memory version of a table (well I am lying but not too much:)

38

Re: Creating form with objects on it programatically

Okay, thanks.

Hans L

39

Re: Creating form with objects on it programatically

And a form using that within a Set_Up_menu procedure (your code with some revisions, especially removing &:):

Cetin, I have started to update my code according to your corrections.

After the quoted text above, you have this code:

Visual Fox Pro
Clear All

Public oForm
oForm = Createobject('MainMenu')
oForm.Show()

This code indicates that you are creating a new form by code. That is fine, but since I already have a "manually" created form, I will delete it. However, when I do, the question becomes "Where do I place the code above and what follows it? (It was previously in my existing form method.)  In another prg?"

Regards,

Hans L

40

Re: Creating form with objects on it programatically

Then you don't need that code. It correspond to:

do form YourVisuallyDesignedForm

41

Re: Creating form with objects on it programatically

Thanks!

Hans L

42

Re: Creating form with objects on it programatically

After having made the first set of changes, it now works (yippee!!!). A few comments.

-  I put the second set of code in a new prg file, and called it from the main prg, and kept the "create form" code.

-   When I run the program, I get "C:\Users\"My name"\AppData\Local\Temp\MyClass.prg" already exists, overwrite it?"

Of course, I say "Yes" and it works. But it gives rise to two questions

~  Would it be better to keep MyClass.prg within the project (e.g., in D:\Databases\Database development\Projects under development\Terminology websearch\PROJECT\PROGS)?

~  I guess it is necessary to write code to delete MyClass.prg before it is being run . Would have to be, I guess, "If MyClass.prg exists, delete it!".

-  The form is height = 600 and width = 800. Is there any way to set the for to fill the screen (available space)?


Now, I will save this code and start reading your "Now what is wrong with this code though it works."

Regards,

Hans L

43

Re: Creating form with objects on it programatically

I went through the second set of codes, and I will use it for the future. It is easier to maintain.

Thanks,

Hans L