XBROWSE exclude or control ARROW keys in edit mode

XBROWSE exclude or control ARROW keys in edit mode

Postby avista » Mon Nov 17, 2014 10:50 am

Hi,

Please i need help how can i exclude or control UP and DOWN arrow keys in xbrowse when some column is in edit mode.
I have problems if column is validated and in valid statement i call function which replace column value, if user dont confirm editing but press UP or DOWN arrow key ... collumn in previous or next row is replaced with new value.

Best rehards.
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby Antonio Linares » Mon Nov 17, 2014 4:51 pm

Please try to disable the xbrowse meanwhile you are in edit mode:

oXBrowse:Disable()

later on enable it:

oXBrowse:Enable()

We will modify FWH to control this undesired behavior. Many thanks for your feedback
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41314
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby nageswaragunupudi » Wed Nov 19, 2014 9:22 pm

avista wrote:Hi,

Please i need help how can i exclude or control UP and DOWN arrow keys in xbrowse when some column is in edit mode.
I have problems if column is validated and in valid statement i call function which replace column value, if user dont confirm editing but press UP or DOWN arrow key ... collumn in previous or next row is replaced with new value.

Best rehards.

If this is happening, there must be something wrong with the program logic. Up and down arrow keys do not work during execution of oCol:bEditValid. Up/Down keys work only after validation is completed and browse is refreshed.

It is desirable not to write inside a valid function but to keep its functionality limited to return valid status. If we want to change the user's input we may use oGet:VarPut() or oGet:cText := ...

example:

oCol:bEditValid := { |oGet| MyValidFunc( oGet ) }

func MyValidFunc( oGet )

if oGet:oGet:VarGet() ....
oGet:cText := <replace>
endif

return .t.

If we want to modify another field consequent on a user input in a column we may use oCol:bOnChange

oCol:bOnChange := { |oCol,uOldValue| OnColChange( oCol, uOldValue ) }

func OnColChange( oCol, uOldValue )

FIELD->PASSED := oCol:Value > 50

return nil
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10248
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby avista » Thu Nov 20, 2014 1:21 am

Hi
Thanks for reply.

Please try this sample
Start editing first column ... dont confirm with ENTER but press DOWN arrow key
(or UP arrow key if pointer is not on the fistr row)
After that remove line
oBrw:nMoveType := 0
and try it again ... pointer is going down on the next row in any cases
I have try to rename XBROWSE object ... the same result
The same result is even if valid function return .f.
Pointer is going down or up, before validation function is finished.

PLEASE for solution

Code: Select all  Expand view
#include 'fivewin.ch'
#include 'xbrowse.ch'


function main()

   local oDlg, oBrw, oCol

   use customer

   DEFINE DIALOG oDlg FROM  0,0 TO 500,400 PIXEL TITLE "Test"

   @ 0,0 XBROWSE oBrw ;
         SIZE 200,250 PIXEL ;
         OF oDlg ;
         LINES CELL FASTEDIT

   ADD oCol TO oBrw DATA customer->Age ;
       HEADER "Age" ;
       EDITABLE ;
       VALID { | oGet | MyValidFunc(oGet,oBrw) } ;

   ADD oCol TO oBrw DATA customer->First ;
       HEADER "First"

   ADD oCol TO oBrw DATA customer->Last ;
       HEADER "Last"

   oBrw:nMoveType := 0

   oBrw:CreateFromCode()

   ACTIVATE DIALOG oDlg CENTERED

return nil

// ----------------------
Function MyValidFunc(oGet,oBrw)

Local nValue := ChooseValue( nValue )

customer->Age := nValue

oBrw:Refresh()

Return .t.

// -------------------------
Function ChooseValue(nValue)

Local oDlg, oBrw, oCol, oBtn
Local aValues := {1,2,3,4,5}
Local nReturn := 1

DEFINE DIALOG oDlg FROM  0,0 TO 250,100 PIXEL TITLE "Choose"

@ 0,0 XBROWSE oBrw ;
      SIZE  50,100  PIXEL ;
      ARRAY aValues ;
      OF oDlg ;
      LINES CELL FOOTERS ;
      ON CHANGE nReturn := aValues[oBrw:KeyNo]

     ADD oCol TO oBrw DATA ARRAY ELEMENT 1 HEADER "Age"

     oBrw:CreateFromCode()

     @ 110,10 BUTTON oBtn PROMPT "&Ok" OF oDlg SIZE 35,12 PIXEL ;
              ACTION oDlg:End()

ACTIVATE DIALOG oDlg CENTERED

Return nReturn


EVEN in case oBrw is disabled

Code: Select all  Expand view
// ----------------------
Function MyValidFunc(oGet,oBrw)

Local nValue

oBrw:Disable()

nValue := ChooseValue( nValue )

oBrw:Enable()

customer->Age := nValue

oBrw:Refresh()

Return .f.
 


Best regards,
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby avista » Sun Nov 23, 2014 6:19 pm

Please
I need help

Best regards,
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby Antonio Linares » Mon Nov 24, 2014 4:37 am

A quick workaround:

Code: Select all  Expand view
Function MyValidFunc(oGet,oBrw)

Local nValue

oBrw:GoUp()

nValue := ChooseValue( nValue )

customer->Age := nValue

oBrw:Refresh()

Return .t.


Also this line in Choosevalue() will help you to close the valid dialog pressing return:

Code: Select all  Expand view
Function ChooseValue(nValue)

Local oDlg, oBrw, oCol, oBtn
Local aValues := {1,2,3,4,5}
Local nReturn := 1

DEFINE DIALOG oDlg FROM  0,0 TO 250,100 PIXEL TITLE "Choose"

@ 0,0 XBROWSE oBrw ;
      SIZE  50,100  PIXEL ;
      ARRAY aValues ;
      OF oDlg ;
      LINES CELL FOOTERS ;
      ON CHANGE nReturn := aValues[oBrw:KeyNo]

     ADD oCol TO oBrw DATA ARRAY ELEMENT 1 HEADER "Age"

     oBrw:bKeyDown = { | nKey  | If( nKey == VK_RETURN, oDlg:End(),) }   // New !!!

     oBrw:CreateFromCode()

     @ 110,10 BUTTON oBtn PROMPT "&Ok" OF oDlg SIZE 35,12 PIXEL ;
              ACTION oDlg:End()

ACTIVATE DIALOG oDlg CENTERED

Return nReturn
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41314
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby Antonio Linares » Mon Nov 24, 2014 4:47 am

To control both up and down:

Code: Select all  Expand view
Function MyValidFunc(oGet,oBrw)

Local nValue

if oGet:oWnd:nLastKey == VK_UP
   oBrw:GoDown()
endif  

if oGet:oWnd:nLastKey == VK_DOWN
   oBrw:GoUp()
endif  

nValue := ChooseValue( nValue )

customer->Age := nValue

oBrw:Refresh()

Return .t.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41314
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby nageswaragunupudi » Mon Nov 24, 2014 4:13 pm

We can not create dialogs/user messages inside bEditWhen and bEditValid of xbrowse.
As I suggested earlier, let us use these codeblocks to only for the purpose they are intended/designed.

When a columns EditGet is in focus, any attempt to change the focus to any other window/dialog/control, either programatically or by the user, "cancels" the edit itself. In the above case, the moment the dialog in ChooseValue() function is activated, the EditGet got "cancelled" without changing the value of the cell and xbrowse proceeded with its next actions.

The purpose of the bEditValid is to return whether the value entered by the user is valid of not. You may replace the value by oGet:oGet:VarPut or oGet:cText. It is desirable not to direcly write to database here because that may have unexpecte side-effects like this.

It is agreed that in some situations we need to provided guided/controlled dataentry and for that purpose, xbrowse specifically provides
EDIT_LISTBOX, EDIT_GET_LISTBOX, EDIT_BUTTON, EDIT_GET_BUTTON.

The same purpose that was intended in the sample provided can be achieved by EDIT_LISTBOX or EDIT_BUTTON. XBrowe provided these facilities for such purposes specifically. In particula EDIT_BUTTON offers the greatest flexibility.

The following example achieves the same purpose as intended in the above sample without any side effects and in lesser yet safer code:
Code: Select all  Expand view

#include 'fivewin.ch'
#include 'xbrowse.ch'

request DBFCDX

function main()

   local oDlg, oBrw, oCol

   USE CUSTOMER SHARED VIA "DBFCDX"

   DEFINE DIALOG oDlg SIZE 500,400 PIXEL
   @ 10,10 XBROWSE oBrw SIZE -10,-10 PIXEL OF oDlg ;
      DATASOURCE "CUSTOMER" ;         // COMPULSORY
      COLUMNS "Age", "First", "Last" ;
      CELL LINES FASTEDIT NOBORDER

   oBrw:Age:nEditType     := EDIT_BUTTON
   oBrw:Age:bEditBlock    := { |nRow,nCol,oCol,nKey| ChooseValue( oCol:Value ) }
   oBrw:CreateFromCode()

   ACTIVATE DIALOG oDlg CENTERED

return nil

function ChooseValue( nValue )

Local oDlg, oBrw
Local aValues := {1,2,3,4,5}
Local nReturn := nil

   DEFINE DIALOG oDlg SIZE 100,300 PIXEL TITLE "Choose"

   @ 0,0 XBROWSE oBrw SIZE  0,-50  PIXEL OF oDlg ;
      ARRAY aValues COLUMNS 1 HEADERS "Age" LINES CELL NOBORDER

     oBrw:CreateFromCode()

     @ 110,10 BUTTON "&Ok" OF oDlg SIZE 30,12 PIXEL ;
              ACTION ( nReturn := aValues[ oBrw:KeyNo ], oDlg:End() )

     @ 130,10 BUTTON "&Cancel" OF oDlg SIZE 30,12 PIXEL ;
              ACTION oDlg:End()

   ACTIVATE DIALOG oDlg CENTERED

Return nReturn
 


XBrowse replaces the value in the cell with the value "returned" by the bEditBlock. If the return value is NIL, the cell value is not changed. Returning NIL indicates that the user decided not to change the value.

In the above case, we can also use EDIT_LISTBOX. We can use EDIT_LISTBOX even if the data is not character type.
Code: Select all  Expand view

#include 'fivewin.ch'
#include 'xbrowse.ch'

request DBFCDX

function main()

   local oDlg, oBrw, oCol, aList := Array( 80 )

   AEval( aList, { |u,i| aList[ i ] := { i, Str( i, 2 ) } } )

   USE CUSTOMER SHARED VIA "DBFCDX"

   DEFINE DIALOG oDlg SIZE 500,400 PIXEL
   @ 10,10 XBROWSE oBrw SIZE -10,-10 PIXEL OF oDlg ;
      DATASOURCE "CUSTOMER" ;         // COMPULSORY
      COLUMNS "Age", "First", "Last" ;
      CELL LINES FASTEDIT NOBORDER

   oBrw:Age:nEditType      := EDIT_LISTBOX
   oBrw:Age:aEditListTxt   := aList
   oBrw:CreateFromCode()

   ACTIVATE DIALOG oDlg CENTERED

return nil
 

Using the recent versions of FWH it needs only 2 lines of code to do this. The same can be done even with older versions but it requires just a few more lines of code.

Some more clarifications may be useful. There can be cases where when user modifies the value of a column, some other column's value may need to be changed based on some calculation.

oCol:bOnChange codeblock is intended for this purpose.

Example usage:

oBrw:Quantity:bOnChange := { |oCol, uOldVal| oBrw:Sales:VarPut( oCol:Value * oBrw:Price:Value )]
if we need to change a field which is not shown in the browse:
oBrw:Quantiry:bOnChange := { |oCol,uOldVal| (oBrw:cAlias)->SALES := oCol:Value * oBrw:Price:Value ) }
( XBrowse already locked the row and is holding the lock)

Some advices:
1) Please indicate the DATASOURCE ( alias/array/etc) "compulsorily" in the @ r,c, XBROWSE command (a) to gain ALL the benefits and features of xbrowse and (b) avoid unexpected side-effects.

2) The commands XBROWSE ... FIELDS and ADD TO oBrw DATA were created years back "only" with the intention to facilitate easier migration from WBrowse and TCBrowse.
But we always recommend using the native XBROWSE ... COLUMNS command. This is the only way to harness full power of xbrowse.

I can only say that the difference is phenomenal.

Here I am giving the same sample posted above with minimal changes required to achieve the same objective safely using EDIT_BUTTON:
Code: Select all  Expand view
#include 'fivewin.ch'
#include 'xbrowse.ch'


function main()

   local oDlg, oBrw, oCol

   use customer

   DEFINE DIALOG oDlg FROM  0,0 TO 500,400 PIXEL TITLE "Test"

   @ 0,0 XBROWSE oBrw ;
         SIZE 200,250 PIXEL ;
         OF oDlg ;
         DATASOURCE "CUSTOMER" ;  // Added
         LINES CELL FASTEDIT

   ADD oCol TO oBrw DATA customer->Age ;
       HEADER "Age" ;
       EDITABLE ;
       ON EDIT { |o,x,k| If( k == VK_ESCAPE .or. x == nil, nil, customer->age := x ) }  // Added

//       VALID { | oGet | MyValidFunc(oGet,oBrw) }  // Removed

   oCol:nEditType    := EDIT_BUTTON                                 // Added
   oCol:bEditBlock   := { |r,c,o,k| ChooseValue( o:Value ) }  // Added
 

   ADD oCol TO oBrw DATA customer->First ;
       HEADER "First"

   ADD oCol TO oBrw DATA customer->Last ;
       HEADER "Last"

//   oBrw:nMoveType := 0    // Removed

   oBrw:CreateFromCode()

   ACTIVATE DIALOG oDlg CENTERED

return nil

// ----------------------
/*
  // Function Removed

Function MyValidFunc(oGet,oBrw)

Local nValue := ChooseValue( nValue )

customer->Age := nValue

oBrw:Refresh()

Return .t.
*/


// -------------------------
Function ChooseValue(nValue)

Local oDlg, oBrw, oCol, oBtn
Local aValues := {1,2,3,4,5}
Local nReturn := nil    // 1   Changed

DEFINE DIALOG oDlg FROM  0,0 TO 250,100 PIXEL TITLE "Choose"

@ 0,0 XBROWSE oBrw ;
      SIZE  50,100  PIXEL ;
      ARRAY aValues ;
      OF oDlg ;
      LINES CELL FOOTERS

//      ON CHANGE nReturn := aValues[oBrw:KeyNo]  // removed

     ADD oCol TO oBrw DATA ARRAY ELEMENT 1 HEADER "Age"

     oBrw:CreateFromCode()

     @ 110,10 BUTTON oBtn PROMPT "&Ok" OF oDlg SIZE 35,12 PIXEL ;
              ACTION ( nReturn := oCol:Value, oDlg:End() ) // Changed

ACTIVATE DIALOG oDlg CENTERED

Return nReturn
 
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10248
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby avista » Wed Nov 26, 2014 10:52 am

Hi Rao
Many thanks for nice sugestions.

But that dont solve my problem.

In the program for sale i use 2 .DBF files

Sale.dbf with fields
ProductID N 7 0
ProductNam C 25 0
Quantity N 11 3
Price N 11 3
TAxCd C 1 0

Products.dbf with fields (Indexed on ProductID)
ProductID N 7 0
ProductNam C 25 0
Price N 11 3
TAxCd C 1 0

I have xBrowse using Sale.dbf
Sale.dbf is empty for each sale
I need user to enter ProductID and after that in validation function
program to seek that value in Products.dbf
If it is FOUND to replace
Sale->ProductID with Products->ProductID
Sale->ProductNam with Products->ProductNam
Sale->Price with Products->Price
Sale->TaxCd with Products->TaxCd
and after that user to enter Quantity

If it is NOT FOUND
to open other dialog with xBrowse of Products.dbf so user can search Product which want to sale
(he must choose one of the existing products)
After that values in Sale.dbf to be replaced from Products.dbf like above

So probably i can NOT use EDIT_BUTTON or EDIT_LISTBOX

I strongly please for help

Best regards and thanks again.
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby nageswaragunupudi » Wed Nov 26, 2014 11:13 am

I shall try to make a sample program for this.
Meanwhile can you give me an idea as to
(a) what would the approximate size of products dbf ( max possible records)
(b) after entering product id, should the user move to quantity column and enter quantity?
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10248
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby avista » Wed Nov 26, 2014 1:18 pm

Hi Mr.Rao

(a) what would the approximate size of products dbf ( max possible records)


Usual 5000-10000
In bigger companies i hope not more than 50000

(b) after entering product id, should the user move to quantity column and enter quantity?

Yes ... other columns dont need to be EDITABLE

Best regards,
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby nageswaragunupudi » Wed Nov 26, 2014 1:23 pm

Forgot to ask. What is the FWH version you are using? So that I do not use any later improvements.
I shall work on this tomorrow
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10248
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby avista » Thu Nov 27, 2014 8:05 am

HI,

xHarbour (Build 20140725)
FWH Usualy 13.02 or for working versions 13.11
Borland C++ 5.82

Regards,
User avatar
avista
 
Posts: 301
Joined: Fri Jun 01, 2007 9:07 am
Location: Macedonia

Re: XBROWSE exclude or control ARROW keys in edit mode

Postby nageswaragunupudi » Sat Nov 29, 2014 7:38 am

We can use EDIT_BUTTON. In that case user can not enter productcode himsel. Only way to enter data is by choosing from the Help Dialog. Alternatively we can use EDIT_GET_BUTTON. In this case the user has the choice of either entering the value directly or click on the button to select from the products dialog. If the user input fails validation, he needs to cancel the edit and then press the button for help. Control is in the hands of the user but not the programmer.

As of now, it is not possible to programmatically invoke the help dialog automatically if the validation fails. This is the feature you are looking for. I too feel there should be a way to do it.

Here we modified xbrowse.prg to provide this feature. I request you to make these changes in your xbrowse.prg in all your versions.

1) Create a New DATA in class TXBrwColumn
Code: Select all  Expand view

DATA lRunBtnAction
 


2) Please locate this function in xbrowse.prg "static function EditGetLostFocus( oGet, hWndFocus, oBrw, oEditGet, oCol )"
In the body of this function locate these lines:
Code: Select all  Expand view

   if oEditGet != nil .and. !oEditGet:lValidating
      oCol:PostEdit()
   endif

return nil
 

Pleae replace the above code with the following code:
Code: Select all  Expand view

   if oEditGet != nil .and. !oEditGet:lValidating
      if oCol:lRunBtnAction == .t. .and. ;
         ( ! Empty( oCol:bEditBlock ) .or. ! Empty( oCol:aEditListTxt ) )
            oCol:lRunBtnAction := nil

         oCol:oEditGet:End()
         oCol:oEditGet  := nil
         oBrw:lEditMode  := .f.
         oCol:RunBtnAction()

      else
         oCol:PostEdit()
      endif
   endif

return nil
 


We set the nEditType of the column to EDIT_GET_BUTTON.
oCol:bEditBlock is assigned with the help dialog function. If the user selects a product, return the producitid. If the user cancels the operation, return nil.

Edit validations function is like this:
function valid ...( oGet, oCol )

if oGet:VarGet() is not valid
oGet:cText := oCol:Value // restore the original value
oCol:lBtnActopm := .t. // Indiacate to xbrowse to automaticall run help dialog
endif

return .t. // always return valid.

Now I give you a sample program including all actions you wanted.
Code: Select all  Expand view

#include "FiveWin.Ch"
#include "ord.ch"
#include "xbrowse.ch"

REQUEST DBFCDX

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

function Main()

   CreateTestDBF()

   USE PRODUCTS NEW SHARED ALIAS PRD
   SET ORDER TO TAG PRODUCTID
   GO TOP

   do while NewSale()
   enddo

   CLOSE DATA

return (0)

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

static function NewSale()

   local oDlg, oBrw, oFont
   local nNewRec     := 0
   local lNext       := .f.

   if SELECT( "SALE" ) > 0
      SELECT SALE
      ZAP
   else
      CreateSaleDbf()
   endif

   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-14
   DEFINE DIALOG oDlg SIZE 900,450 PIXEL FONT oFont

   @ 10,10 XBROWSE oBrw SIZE -10,-30 PIXEL OF oDlg ;
      DATASOURCE "SALE" ;
      COLUMNS "ProductID", "ProductNam", "Price", "Quantity", "TaxCd", "Amount" ;
      HEADERS "ProdID", "ProductName" ;
      CELL LINES NOBORDER FOOTERS FASTEDIT

   WITH OBJECT oBrw
      WITH OBJECT :oCol( 1 )
         :nEditType     := EDIT_GET_BUTTON
         :bEditValid    := { |oGet| ValidProdID( oGet, oBrw:oCol( 1 ) ) }
         :bEditBlock    := { |r,c,oCol| ProductSelect( oCol:Value ) }
         :bOnChange     := { |oCol,uOldVal| ;
                                 PRD->( DBSEEK( oCol:Value ) ), ;
                                 oBrw:ProductName:VarPut( PRD->PRODUCTNAM ), ;
                                 oBrw:Price:VarPut( PRD->PRICE ), ;
                                 oBrw:TaxCd:VarPut( PRD->TAXCD ), ;
                                 CalcRow( oBrw ) }

      ENDWITH
      WITH OBJECT :Quantity
         :nEditType     := EDIT_GET
         :bEditValid    := { |oGet| oGet:VarGet() > 0 }
         :bOnChange     := { |oCol| CalcRow( oBrw ) }
      END
      WITH OBJECT :Amount
         :nFooterType   := AGGR_SUM
         :bOnChange     := { |oCol| If( oCol:Value > 0, nNewRec := 0, nil ) }
      END
      :bPastEof         := { || If( nNewRec == 0, SALE->( DBAPPEND(), nNewRec := RECNO(), oBrw:Refresh() ), nil ) }
      :bKeyDown         := { |nKey| If( nkey == VK_DELETE, ;
                                      ( If( SALE->(RECNO()) == nNewRec, nNewRec := 0, nil ) , ;
                                        SALE->( DBDELETE() ), ;
                                        oBrw:Refresh(), ;
                                        oBrw:MakeTotals(), ;
                                        oBrw:RefreshFooters() ), nil ) }
      :bChange          := { || If( nNewRec > 0, ( SALE->( DBGOTO( nNewRec ), ;
                                                           DBDELETE(), ;
                                                           DBGOBOTTOM() ), ;
                                                   oBrw:Refresh(), ;
                                                   nNewRec := 0 ) , nil ) }
      //
      :nStretchCol      := 2
      :MakeTotals()
      :CreateFromCode()
   END

   @ 205,350 BUTTON "Close"    SIZE 40,14 PIXEL OF oDlg ACTION oDlg:End()
   @ 205,400 BUTTON "NextSale" SIZE 40,14 PIXEL OF oDlg ACTION ( lNext := .t., oDlg:End() )

   ACTIVATE DIALOG oDlg CENTERED ON INIT ( oBrw:GoDown() )
   RELEASE FONT oFont

   if nNewRec > 0
      SALE->( DBGOTO( nNewRec ), DBDELETE() )
   endif

   XBROWSER "SALE"

return lNext

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

static function CalcRow( oBrw )

   oBrw:Amount:VarPut( oBrw:Quantity:Value * oBrw:Price:Value )

return nil

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

static function ValidProdID( oGet, oCol )

   local nVal     := oGet:VarGet()

   if .not. PRD->( DBSEEK( nVal ) )
      PRD->( DBSEEK( nVal, .t. ) )
      oGet:cText           := oCol:Value
      oCol:lRunBtnAction   := .t.
   endif

return .t.

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

static function ProductSelect( nCode )

   local nSelect
   local oDlg, oBrw, oFont

   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-14
   DEFINE DIALOG oDlg SIZE 400,500 PIXEL FONT oFont TITLE "PRODUCTS"

   @ 30,10 XBROWSE oBrw SIZE -10,-30 PIXEL OF oDlg ;
      DATASOURCE "PRD" ;
      COLUMNS "ProductID", "ProductNam" ;
      CELL LINES NOBORDER AUTOSORT

   WITH OBJECT oBrw
      :bLDblClick    := { || nSelect := PRD->PRODUCTID, oDlg:End() }
      :bKeyChar      := { |nKey| If( nKey == VK_RETURN, ;
               ( nSelect := PRD->PRODUCTID, oDlg:End() ), nil ) }
      //

      :CreateFromCode()
   END

   @ 10,10 SAY oBrw:oSeek PROMPT oBrw:cseek SIZE 180,10 PIXEL ;
      OF oDlg COLOR CLR_HRED,CLR_YELLOW

   @ 230,150 BUTTON "Select" SIZE 40,14 PIXEL OF oDlg ;
      ACTION ( nSelect := PRD->PRODUCTID, oDlg:End() )

   ACTIVATE DIALOG oDlg CENTERED
   RELEASE FONT oFont

   PRD->( OrdSetFocus( "PRODUCTID" ) )

return nSelect

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

static function CreateSaleDbf()

   DBCREATE( "SALE.DBF", { ;
      { "PRODUCTID",    'N',  7, 0  }, ;
      { "PRODUCTNAM",   'C', 25, 0  }, ;
      { "PRICE",        'N', 11, 3  }, ;
      { "QUANTITY",     'N', 11, 3  }, ;
      { "TAXCD",        'C',  1, 0  }, ;
      { "AMOUNT",       'N', 12, 2  } }, ;
      "DBFCDX", .t., "SALE" )
   SET FILTER TO !DELETED()

return nil

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

static function CreateTestDbf()

   field PRODUCTID, PRODUCTNAM

   USE CUSTOMER NEW SHARED ALIAS CUST
   DBCREATE( "PRODUCTS.DBF", { ;
      { "PRODUCTID",    'N',  7, 0  }, ;
      { "PRODUCTNAM",   'C', 25, 0  }, ;
      { "PRICE",        'N', 11, 3  }, ;
      { "TAXCD",        'C',  1, 0  }  }, ;
      "DBFCDX", .t., "PROD" )

   do while ! cust->( eof() )
      APPEND BLANK
      PROD->PRODUCTID      := RECNO() * 7 + 3000
      PROD->PRODUCTNAM     := CUST->FIRST-CUST->LAST
      PROD->PRICE          := HB_Random( 100, 900 )
      PROD->TAXCD          := CHR( 64 + HB_RandomInt( 1, 3 ) )
      cust->( dbskip( 1 ) )
   enddo

   INDEX ON PRODUCTID  TAG PRODUCTID
   INDEX ON UPPER(PRODUCTNAM) TAG PRODUCTNAM

   CLOSE DATA

return nil

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

init procedure PrgInit

   SET DATE ITALIAN
   SET CENTURY ON
   SET TIME FORMAT TO "HH:MM:SS"
   SET EPOCH TO YEAR(DATE())-50

   SET DELETED ON
   SET EXCLUSIVE OFF

   RDDSETDEFAULT( "DBFCDX" )

   XbrNumFormat( 'A', .t. )
   SetKinetic( .f. )
   SetGetColorFocus()
   SetBalloon( .t. )

return

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

Please link the modified xbrowse.prg with this. Keep the exe in fwh\samples folder and run.
I hope this meets all requirements you specified above.
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10248
Joined: Sun Nov 19, 2006 5:22 am
Location: India


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot], Otto and 64 guests