Page 1 of 1

Modification for TEdit

Posted: Fri Jul 03, 2015 1:36 pm
by AntoninoP
Hello,

I tried to use TEdit in my application, because I want an empty edit Box with unlimited text input, and it is not possible with TGet.
The problems I saw are:
  1. The font is not setted, it is only if you create the TEdit between Init Dialog and Activate Dialog as the example does, but with TWindow or using on Init it is not.
  2. There is no bUpdate/bChange support
  3. It works only with text, it is very minor.
  4. It is not possilbe use PIXEL coordinate, It is minor too.
The 1,3 and 4 are easily resolvible, the point 2 is a little more difficult,
To maintain compatibility with TGet I split the bChange in 2 notifications, 1 is bChange that can be used for accept/discard a character, and bUpdate that is called after the value updates.

So, Here the edit.prg modified:

Code: Select all

// Class TEdit for two characters support (Chinesse, etc.)

#include "FiveWin.ch"
#include "constant.ch"

#define DEFAULT_GUI_FONT   17

#define EM_SETSEL          177
#define EM_LIMITTEXT       197
#define EM_SETCUEBANNER 0x1501

//#define EN_SETFOCUS         0x0100
//#define EN_KILLFOCUS        0x0200
//#define EN_CHANGE           0x0300
#define EN_UPDATE           0x0400
//#define EN_ERRSPACE         0x0500
//#define EN_MAXTEXT          0x0501
#define EN_HSCROLL          0x0601
//#define EN_VSCROLL          0x0602

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

CLASS TEdit FROM TControl
   DATA cPicture, cType
   DATA bHScroll, bUpdate
   
   METHOD New( nRow, nCol, bSetGet, oWnd, nWidth, nHeight, lPixel, oFont, cPicture, ;
                  bChanged, bUpdate, bHScroll) CONSTRUCTOR

   METHOD ReDefine( nId, oWnd, bSetGet, cPicture, bChanged, bUpdate, bHScroll ) CONSTRUCTOR
      
   METHOD cToChar() INLINE ::Super:cToChar( "EDIT" )
   
   METHOD Initiate( hDlg )
   
   METHOD MouseMove() VIRTUAL
   
   METHOD LostFocus( hWndGetFocus )
   
   METHOD GotFocus() INLINE ::SelectAll(), ::Super:GotFocus()

   METHOD SelectAll() INLINE ::SetSel( 0, -1 )
   
   METHOD SetSel( nStart, nEnd ) INLINE ;
                  nStart := If( nStart == nil, 1, nStart ),;
                  nEnd   := If( nEnd == nil, nStart, nEnd ),;
                  SendMessage( ::hWnd, EM_SETSEL, nStart, nEnd )                
                  
   METHOD Refresh() INLINE ::SetText( If( Empty( ::cPicture ), ;
                                             cValToChar( Eval( ::bSetGet ) ),;
                                             Transform( Eval( ::bSetGet ), ::cPicture ) ) ) 
   
   METHOD Read()
   
   METHOD SetLimitText(n) INLINE SendMessage( ::hWnd, EM_LIMITTEXT, if(valtype(n)="N",n,0), 0 )
   METHOD SetCueBanner( lOnFocus, cText ) INLINE SendMessage( ::hWnd, EM_SETCUEBANNER, lOnFocus, AnsiToWide( cText ) )
   
   METHOD KeyChar( nKey, nFlags )
   METHOD Command( nWParam, nLParam )
ENDCLASS

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

METHOD New( nRow, nCol, bSetGet, oWnd, nWidth, nHeight, lPixel, oFont, cPicture,;
               bChanged, bUpdate, bHScroll ) CLASS TEdit
   LOCAL startVal := Eval(bSetGet)
   LOCAL cType :=ValType(startVal)
   
   DEFAULT nRow := 0, nCol := 0, oWnd := GetWndDefault(), nWidth := 80,;
           nHeight := 20, lPixel := .F.

   if oFont == nil
      oFont := TFont():New()
      oFont:hFont := GetStockObject( DEFAULT_GUI_FONT )
   endif

   ::oWnd    = oWnd
   ::nId     = ::GetNewId()
   ::nStyle  = nOR( WS_CHILD, WS_VISIBLE, WS_BORDER, WS_TABSTOP, ES_AUTOHSCROLL )
   ::nTop    = if( lPixel, nRow, nRow * GET_CHARPIX_H    )
   ::nLeft   = if( lPixel, nCol, nCol * GET_CHARPIX_W    )
   ::nBottom = ::nTop + nHeight - 1
   ::nRight  = ::nLeft + nWidth
   ::lDrag   = .F.                
   ::bSetGet = bSetGet
   ::cPicture = cPicture
   ::cType = cType
   ::oFont = oFont
   ::bChange = bChanged
   ::bUpdate = bUpdate
   ::bHScroll = bHScroll

   ::cCaption  = If( Empty( cPicture ), cValToChar( startVal ),;
                     Transform( startVal, cPicture ) )

   if ! Empty( oWnd:hWnd )
      ::Create( "EDIT" )
      if ::oFont != nil
         ::SetFont( ::oFont )
      else
         ::GetFont()
      endif
      oWnd:AddControl( Self )
   else
      oWnd:DefControl( Self )
   endif
   
return Self

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

METHOD ReDefine( nId, oWnd, bSetGet, cPicture, bChanged, bUpdate, bHScroll ) CLASS TEdit

   DEFAULT oWnd := GetWndDefault()

   ::nId     = nId
   ::oWnd    = oWnd
   ::bSetGet = bSetGet
   ::cPicture = cPicture
   ::bChange = bChanged
   ::bUpdate = bUpdate
   ::bHScroll = bHScroll

   oWnd:DefControl( Self )
   ::Refresh()
   
return Self

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

METHOD Initiate( hDlg ) CLASS TEdit

   ::Super:Initiate( hDlg )
   
   ::Refresh()
   
return nil     

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

METHOD LostFocus( hWndGetFocus ) CLASS TEdit

   ::Super:LostFocus( hWndGetFocus )
   ::Read()
   
return nil 

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

METHOD Read() CLASS TEdit
   
   if Empty( ::bSetGet )
      return nil
   endif
   
   if ::cType == "C"
      Eval( ::bSetGet, ::GetText() )
   elseif ::cType == "N"
      Eval( ::bSetGet, Val(::GetText()) )
   elseif ::cType == "D"
      Eval( ::bSetGet, CToD(::GetText()) )
   endif
   
return nil

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

METHOD KeyChar( nKey, nFlags ) CLASS TEdit
   LOCAL lAccept
   
   if ::cType == "N"
      if .not. (( nKey>=asc('0') .and. nKey<=asc('9')) .or. ;
                  nKey==asc('-') .or. nKey==asc('.') .or. nKey<32)
         return 0
      endif
   endif

  if ::bChange != nil
     lAccept = Eval( ::bChange, nKey, nFlags, Self )
     if ValType( lAccept ) == "L" .and. ! lAccept
        return 0
      endif
  endif

return ::Super:KeyChar( nKey, nFlags )

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

METHOD Command( nWParam, nLParam ) CLASS TEdit
   local nCode := nHiWord( nWParam )

   if nCode == EN_UPDATE .and. ::bUpdate != nil
      ::Read()
      Eval( ::bUpdate, Self )
   endif
   
   if nCode == EN_HSCROLL .and. ::bHScroll != nil
      Eval( ::bHScroll, Self )
   endif
   
return nil

//----------------------------------------------------------------------------//
to use this is necessary change the METHOD Command of TDialog and TWindow adding this case:

Code: Select all

      case GetClassName( hWndCtl ) == "Edit" 
           oCtrl :=oWndFromHwnd( hWndCtl )
           if oCtrl!=nil .and. oCtrl:ClassName() == "TEDIT"
               oCtrl:Command( nWParam, nLParam )
               return nil
           endif
 
IMHO, as user, with these modification the TEdit is usable, and the cue banner works!

some comments?

Regards,
Antonino

Re: Modification for TEdit

Posted: Fri Jul 03, 2015 2:37 pm
by Antonio Linares
Antonino,

Many thanks for your contribution, it looks very well :-)

Do you have a little example to test the new TEdit features ? thanks!

Re: Modification for TEdit

Posted: Tue Jul 07, 2015 4:41 am
by bpd2000
Antonio Linares wrote:Antonino,

Many thanks for your contribution, it looks very well :-)

Do you have a little example to test the new TEdit features ? thanks!
+1

Re: Modification for TEdit

Posted: Tue Jul 07, 2015 7:32 am
by AntoninoP
Here an example:

Code: Select all

#include "FiveWin.ch"

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

function Main()

   local oDlg
   
   DEFINE DIALOG oDlg SIZE 500, 250
   ACTIVATE DIALOG oDlg CENTERED ON INIT init(oDlg)

return nil

PROC init(oDlg)
   local oSay1,oSay2,oSay3,oSay4
   local oEdit1,oEdit2,oEdit3,oEdit4
   local cFirst := "Start value", cLast := ""
   LOCAl nVal1 := VAL("0"), nVal2 := 3.1415000
   
   @ 8, 10 EDIT oEdit1 VAR cFirst OF oDlg SIZE 160, 20 PIXEL ON UPDATE oSay1:Refresh()
   @ 40,10 SAY oSay1 VAR cFirst OF oDlg SIZE 160, 20 PIXEL 
   oEdit1:SetCueBanner(.T.,"Write here")
   @ 72, 10 EDIT oEdit2 VAR cLast OF oDlg SIZE 160, 20 PIXEL ON UPDATE oSay2:Refresh() ON CHANGE if(nKey==asc('a'),.F.,.T.)
   @ 104,10 SAY oSay2 VAR cLast OF oDlg SIZE 160, 20 PIXEL 
   oEdit2:SetCueBanner(.T.,"No 'a' allowed here")

   @ 8, 200 EDIT nVal1 OF oDlg SIZE 160, 20 PIXEL
   @ 72, 200 EDIT nVal2 OF oDlg SIZE 160, 20 PIXEL
   
   @ 136, 110 BUTTON "Ok"  PIXEL SIZE 80,32;
      ACTION MsgInfo( cFirst + ", " + cLast+ ":" +Transform(nVal1,"@E") + "; "+Transform(nVal2,"@E") )

   @ 136, 210 BUTTON "Cancel" ACTION oDlg:End() PIXEL  SIZE 80,32

return
//----------------------------------------------------------------------------//
In this example you can see the "on update" and "on change" at work.
If you link with common control v.6 you can see the cue banner also, they can not work on TGet because it is never empty.

To compile, need to change the macro in fivewin.ch in this way:

Code: Select all

/*----------------------------------------------------------------------------//
!short: EDIT  */

#command @ <nRow>, <nCol> EDIT [ <oEdit> VAR ] <uVar> ;
            [ <dlg: OF, WINDOW, DIALOG> <oWnd> ] ;
            [ SIZE <nWidth>, <nHeight> ] ;
            [ <lPixel: PIXEL, PIXELS > ] ;
            [ FONT <oFont> ]  ;
            [ <pict: PICT, PICTURE> <cPict> ] ;
            [ ON CHANGE <uChange> ] ;
            [ ON UPDATE <uUpdate> ] ;
            [ ON SCROLL <uScroll> ] ;
       => ;
          [ <oEdit> := ] TEdit():New( <nRow>, <nCol>, bSETGET(<uVar>),;
            [<oWnd>], <nWidth>, <nHeight>, <.lPixel.>, <oFont>, <cPict>,;
            [\{|nKey, nFlags, Self| <uChange>\}],;
            [\{|Self| <uUpdate>\}],;
            [\{|Self| <uScroll>\}],)

#xcommand REDEFINE EDIT [ <oEdit> VAR ] <uVar> ;
            [ ID <nId> ] ;
            [ <dlg: OF, WINDOW, DIALOG> <oWnd> ] ;
            [ <pict: PICT, PICTURE> <cPict> ] ;
            [ ON CHANGE <uChange> ] ;
            [ ON UPDATE <uUpdate> ] ;
            [ ON SCROLL <uScroll> ] ;
       => ;
          [ <oEdit> := ] TEdit():Redefine( <nId>, [<oWnd>],;
                                           bSETGET(<uVar>), <cPict>,;
            [\{|nKey, nFlags, Self| <uChange>\}],;
            [\{|Self| <uUpdate>\}],;
            [\{|Self| <uScroll>\}],)
Image

Re: Modification for TEdit

Posted: Tue Jul 07, 2015 7:53 am
by Antonio Linares
Antonino,

many thanks! Added for next FWH version.

> If you link with common control v.6 you can see the cue banner also

Could you explain how to do it ? thanks

Re: Modification for TEdit

Posted: Tue Jul 07, 2015 8:08 am
by AntoninoP
Antonio Linares wrote:> If you link with common control v.6 you can see the cue banner also

Could you explain how to do it ? thanks
It is when you add a manifest in the resources with this dependency:

Code: Select all

<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="X86"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
see: "Common controls" version "6".

How do you explain it?

Re: Modification for TEdit

Posted: Tue Jul 07, 2015 8:17 am
by Antonio Linares
many thanks! :-)