Page 1 of 2

Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 11:13 am
by Marc Venken
Hello,

I started converting my main program to 32 bit (FWH) actual version

I've read lots of posts last years, and in starting the conversion i will surely have some questions. I start this post since it will be mostly related to the conversion.
Global questions I will ask with other topics for global use.

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 11:14 am
by Marc Venken
Can we trace or see somewhere witch functions have been called since hitting a button or startup...

Ex. Before I see my startup screen, 10's of functions have been called. Can we see it somewhere ?

I would be easy than to see if called functions have to be updated.

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 1:03 pm
by Antonio Linares
A very simple way is to generate an error like this one:

x++

where x is not defined at all. At run time you will get an error and you will see the calls stack

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 2:11 pm
by Marc Venken
I was thinking more of a way that all processed functions are listed or so.

AT start, going to customers, some functions are processed with no error (lucky me :D ). So it would be handy if I could see witch one they have been.
I can look them up, and see of a update is needed (very ofthen, since my knowledge of FW has been much better now

I will no overlook the program flow(prg), and when a function is called, note it and see if it needs a update. Sequentially all functions will come sooner of later...

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 4:02 pm
by Otto
Hello Marc,
Maybe this is of some help to you. If you insert this into your program and SetKey( VK_F2, { || WhereAmI() } ) into the main function, then you can press F2 inside a function, and you get a info box to see where you are in your program.
Best regards,
Otto

Code: Select all

#include "FiveWin.ch"  
 
function Main()

   SetKey( VK_F2, { || WhereAmI() } ) 

   Another()
   
return nil    
 
function Another()        
 
   local oDlg, cTest := Space( 20 )        
 
   DEFINE DIALOG oDlg TITLE "Test"        

   @ 1.5, 5 GET cTest

   @ 3, 10 BUTTON "Ok"
 
   ACTIVATE DIALOG oDlg CENTERED  
 
return nil 

function WhereAmI()

   local oCtrl := oWndFromHwnd( GetFocus() )

   MsgInfo( "ProcName: " + ProcName( 11 ) + CRLF + ;
            "ProcLine: " + Str( ProcLine( 11 ) ) + CRLF + ;
            "Focused object: " + oCtrl:ClassName() + CRLF + ;
            "Dialog title: " + oCtrl:oWnd:GetText() )
   
return nil   



 

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 8:00 pm
by Marc Venken
Otto wrote:Hello Marc,
Maybe this is of some help to you. If you insert this into your program and SetKey( VK_F2, { || WhereAmI() } ) into the main function, then you can press F2 inside a function, and you get a info box to see where you are in your program.
Best regards,
Otto

Code: Select all

#include "FiveWin.ch"  
 
function Main()

   SetKey( VK_F2, { || WhereAmI() } ) 

   Another()
   
return nil    
 
function Another()        
 
   local oDlg, cTest := Space( 20 )        
 
   DEFINE DIALOG oDlg TITLE "Test"        

   @ 1.5, 5 GET cTest

   @ 3, 10 BUTTON "Ok"
 
   ACTIVATE DIALOG oDlg CENTERED  
 
return nil 

function WhereAmI()

   local oCtrl := oWndFromHwnd( GetFocus() )

   MsgInfo( "ProcName: " + ProcName( 11 ) + CRLF + ;
            "ProcLine: " + Str( ProcLine( 11 ) ) + CRLF + ;
            "Focused object: " + oCtrl:ClassName() + CRLF + ;
            "Dialog title: " + oCtrl:oWnd:GetText() )
   
return nil   



 
Ok, I use this now inside a Loop (1 to 20) to see more procline . You use the (11) but it is only as demostrated right ? It is not a specific value of last processed function.

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 8:35 pm
by Otto
Marc,
you can insert a
TRY CATCH.
Best regards,
Otto

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 8:43 pm
by Marc Venken
Otto wrote:Marc,
you can insert a
TRY CATCH.
Best regards,
Otto
I have to look into this... Never used and no idea what it is for.....

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 9:15 pm
by Marc Venken
Since I use Xbrowse almost all the time and then I have mostly data like

customer : all invoices
customer : all statisctis
products : who bought this product

so, 1 to many relations.

using relation, filters or scopes

The fact is that in any situation when the master browse moves position // bchange: the lookup for the detail will be searched for. In a network situation this slows down not ?

Is there a Xbrowse setting for this ?

There has been a post like this :

:bChange := { || nSecs := SECONDS() }

but that is not complete.

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 9:40 pm
by Otto
Marc, Are you happy with the speed on your local PC. If so, then everything fits, because with RDP you have exactly this speed.
Best regards,
Otto

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 10:11 pm
by Marc Venken
Otto wrote:Marc, Are you happy with the speed on your local PC. If so, then everything fits, because with RDP you have exactly this speed.
Best regards,
Otto
The speed is ok, but the issue I bring up seems to be bad programming from me. Maybe the movement in the browse can be delaided for executing the bChange
It's just some stuff that I wonder about. In Peer to Peer this could speed things up. even RDP could benifit from it.

Re: Marc : Conversion process and questions about it

Posted: Sun Dec 27, 2020 10:37 pm
by Marc Venken
I found the sample from mr. Rao

Code: Select all

#include "fivewin.ch"

// EXECUTE IN FWH\SAMPLES FOLDER

REQUEST DBFCDX

static nSecs      := 0
static nDelay     := 1  // seconds
static oTimer
//----------------------------------------------------------------------------//

function Main()

   field STATE,CODE
   local oDlg, oStates, oCust

   // OPEN DBF AND SET SCOPES
   USE STATES NEW VIA "DBFCDX"
   USE CUSTOMER NEW VIA "DBFCDX"
   INDEX ON STATE TAG STATEM TO TMP MEMORY
   SET ORDER TO TAG STATEM
   GO TOP
   SELECT STATES
   SET RELATION TO CODE INTO CUSTOMER SCOPED
   GO TOP

   //
   DEFINE DIALOG oDlg SIZE 900,600 PIXEL TRUEPIXEL

   @ 20,20 XBROWSE oStates SIZE 250,-20 PIXEL OF oDlg ;
      DATASOURCE "STATES" AUTOCOLS ;
      CELL LINES NOBORDER

   WITH OBJECT oStates
      :bChange    := { || nSecs := SECONDS() }
      :CreateFromCode()
   END

   @ 20,250 XBROWSE oCust SIZE -20,-20 PIXEL OF oDlg ;
      DATASOURCE "CUSTOMER" COLUMNS "STATE","CITY","SALARY" ;
      CELL LINES NOBORDER

   oCust:CreateFromCode()

   ACTIVATE DIALOG oDlg ON INIT DlgInit( oDlg, oCust )

   CLOSE DATA

return nil

//----------------------------------------------------------------------------//

static function DlgInit( oDlg, oCust )

   DEFINE TIMER oTimer INTERVAL 1000 OF oDlg ACTION CustScope( oCust )
   oTimer:Activate()

return nil

//----------------------------------------------------------------------------//

static function CustScope( oCust )

   if nSecs > 0
      if SECONDS() - nSecs >= nDelay
         oCust:GoTop()
         oCust:Refresh()
         nSecs    := 0
      endif
   endif

return nil

//----------------------------------------------------------------------------//
 
 

Re: Marc : Conversion process and questions about it

Posted: Wed Dec 30, 2020 10:28 am
by Marc Venken
Marc Venken wrote:Can we trace or see somewhere witch functions have been called since hitting a button or startup...

Ex. Before I see my startup screen, 10's of functions have been called. Can we see it somewhere ?

I would be easy than to see if called functions have to be updated.
I made a small function with Xbrowse to see somewhere what I wanted !

Now I noticed something and i'm not sure that this is intended to be so....

In starting my app. (hitting 1 button for customers) the program executed a filter function 7 TIMES !! before even the screen is opened or a customer is selected.
Looking into the code :

Folderex with 5 xbrowse (invoices, persons, orders, ...) folders AND Xbrowse for each.

These are the line I'm not sure off that I use or place them at the right position

  :bgotfocus     := { || oBrw[5]:maketotals(),set_factdet()} // Set_factdet = calling the filterfunction
   oBrw[5]:bChange := { |oBrw, uOlddata | set_factdet() }

second browse

filter("hist","histfac",str(facturen->factuur))

And at the end off all browsers I use

/// end xbrowses

filterupdate(oKlant,oBrw,oFld) // This will also filter some stuff
ACTIVATE DIALOG oDlg CENTERED

Do you prefer to use the filters on 1 location (all filtering inside this = filterupdate ) or filter on each xbrowse individually ?
Can we avoid the filters to executed without selecting a customer? It will speedup the process of the first sceen of customerdata in a Peer to peer network.

Again, Speed is not that big of a deal at our place, but I think it is not good programming technique, and It is one of the most things that happen (retrieving data's)

(






Code: Select all

 // 05 Facturen
      Public aVelden5:=  { ;
   { "Factuur"            , "Factuur" , NIL,  50 }, ; // 1
   { "Klantnum"            , "Klant" , NIL,  50 }, ; // 1
   { "Datum"              , "Datum" , NIL, 60 }, ; //
   { "vervaldat"          , "Verval" , NIL, 60 }, ; // 1
   { "basis"              , "Basis" , NIL, 70 }, ; // 1
   { "btw"              , "Btw" , NIL, 70 }, ; // 1
   { "Totaal"              , "Totaal" , NIL, 70 }, ; // 1
   { "margesom"              , "M_Som" , NIL, 70 }, ; // 1
   { "marge"             , "M_Per" , NIL, 70 }}   // 1

   @ 0,0 XBROWSE oBrw[5] size -1,200 PIXEL OF  oFld:aDialogs[ 4 ] font oFonts ;
      DATASOURCE "facturen" ;
      COLUMNS aVelden5;
      AUTOSORT CELL LINES NOBORDER FOOTERS



     WITH OBJECT oBrw[5]
      :nColDividerStyle := LINESTYLE_LIGHTGRAY
      :nRowDividerStyle := LINESTYLE_LIGHTGRAY
      :bClrRowFocus     := { || { CLR_BLACK, RGB(185,220,255) } }
      :nMarqueeStyle    := MARQSTYLE_HIGHLROWMS

      :aCols[1]:cSortOrder = "facturen"
      :aCols[1]:bLClickHeader:= {|| oBrw[5]:gotop(),oBrw[5]:refresh() }

      :aCols[02]:cSortOrder = "factkl"
      :aCols[02]:bLClickHeader:= {|| oBrw[5]:gotop(),oBrw[5]:refresh() }

      :lFooter          := .t.
      :bRecSelHeader    := { || "RowNo" }
      :bRecSelData      := { |o| o:KeyNo }
      :bRecSelFooter    := { |o| o:nLen }
      :oRecSelFont      := oFont  // optional
      :nRecSelWidth     := "999" // required size

      :basis:nFooterType  := AGGR_SUM
      :totaal:nFooterType  := AGGR_SUM
      :M_Som:nFooterType  := AGGR_SUM

      :MakeTotals()

      :bgotfocus     := { || oBrw[5]:maketotals(),set_factdet()}



     END


     oBrw[5]:SetChecks()
     oBrw[5]:nHeadStrAligns  := AL_CENTER

     oBrw[5]:bChange := { |oBrw, uOlddata | set_factdet() }

     oBrw[5]:bRClicked := { || XbrShowSizes( oBrw[5] )  }
     oBrw[5]:nStretchCol  := STRETCHCOL_WIDEST

     oBrw[5]:CreateFromCode()



   //Facturen historiek        TWEEDE BROWSE

   filter("hist","histfac",str(facturen->factuur))

   Public aVelden6:=  { ;
   { "levbon"            , "Levbon" , NIL,  50 }, ; // 1
   { "artikel"            , "Artikel" , NIL,  80 }, ; // 1
   { "Benaming"            , "Benaming" , NIL,  200 }, ; // 1
   { "Aantal"              , "Aantal" , NIL, 60 }, ; //
   { "eenh_prijs"          , "Prijs" , NIL, 60 }, ; // 1
   { "korting"              , "Kor" , NIL, 35 }, ; // 1
   { "aantal*(eenh_prijs - ( (eenh_prijs * korting) / 100))"    , "Totaal" , NIL, 60 }, ; // 1
   { "margesom"             , "M_Som" , NIL, 60 }, ; // 1
   { "marge"                , "M_Per" , NIL, 60 }}   // 1

   @ 210,0 XBROWSE oBrw[6] size -1,-1 PIXEL OF  oFld:aDialogs[ 4 ] font oFontS ;
      DATASOURCE "hist" ;
      COLUMNS aVelden6;
      AUTOSORT CELL LINES NOBORDER FOOTERS


     WITH OBJECT oBrw[6]
      :nColDividerStyle := LINESTYLE_LIGHTGRAY
      :nRowDividerStyle := LINESTYLE_LIGHTGRAY
      :bClrRowFocus     := { || { CLR_BLACK, RGB(185,220,255) } }
      :nMarqueeStyle    := MARQSTYLE_HIGHLROWMS

      //oBrw[6]:bChange   := { || oBrw[6]:MakeTotals() }


     END


     oBrw[6]:SetChecks()
     oBrw[6]:nHeadStrAligns := AL_CENTER
     oBrw[6]:bRClicked := { || XbrShowSizes( oBrw[6] )  }
     oBrw[6]:nStretchCol  := STRETCHCOL_WIDEST

      for each cCol in { "Totaal", "M_Som" }
         WITH OBJECT oBrw[6]:oCol( cCol )
            :nFooterType   := AGGR_SUM
         END
      next

     oBrw[6]:MakeTotals()

     oBrw[6]:CreateFromCode()

// Einde van Folders  =================================================

 

Re: Marc : Conversion process and questions about it

Posted: Sat Jan 02, 2021 7:22 pm
by James Bott
Marc,

Are you using filters or scopes?

Are you doing incremental searches on a Get as the user types?

Are you trying to update five browses for each keystroke the user types into a search field?

Many things we did when the exe and databases were on the same computer are not practical on a network.

Re: Marc : Conversion process and questions about it

Posted: Sat Jan 02, 2021 7:36 pm
by Marc Venken
James Bott wrote:Marc,

Are you using filters or scopes?

Are you doing incremental searches on a Get as the user types?

Are you trying to update five browses for each keystroke the user types into a search field?

Many things we did when the exe and databases were on the same computer are not practible on a network.
I use filters and scopes and set relations. Trying the best out of them.
Incremental yes, but the new version of FWH has a new option of get's that will search afther pressing enter.
The every keystroke search is not good in network, and therefore I ask for the 2 seconds delay function that Mr. Rao gave.

The new way seems to be to use remote controle (other topic off mine) where Mr. Otto has good experience with FW programs. No data is transferred over the network, and I'm looking serious into it.
But even with Remote controle, my program has functions that are not optimised for FWH newest versions.

Code: Select all

function filter(cAlias,cTag,cStart)
   local cOld_alias:=Alias(), NTag:= &cOld_alias->(indexord())
   default cStart:=""
   dbfsopen()  // IS ONLY HERE TO SEE HOW MANY TIMES IT IS PROCESSED (debugging Xbrowser)
   select &cAlias
   set order to tag &cTag
   if !empty(cTag)
      set scope to alltrim(cStart)
   endif
   &cAlias->(dbgotop())
   select &cOld_alias
   &cOld_alias->(dbsetorder(nTag))

return NIL

 
In my newer FWH program I'm using this to filter

Code: Select all

STATIC FUNCTION SET_SCOPE_3(oBrw3)
LOCAL cNName := alltrim(nofoto->Reflev)

DBSELECTAREA( "master" )
("master")->( ORDSCOPE(0, cNName ) )
("master")->(ORDSCOPE(1, cNName ) )
master->(dbgotop())

//oBrw3:Refresh()

RETURN NIL

 
I think they are almost the same.