Adding a real time character count to a memo field dialog bx

Post Reply
User avatar
Rick Lipkin
Posts: 2397
Joined: Fri Oct 07, 2005 1:50 pm
Location: Columbia, South Carolina USA

Adding a real time character count to a memo field dialog bx

Post by Rick Lipkin »

To All

I would like to be able to show a "real time" character count when you start typing a memo field .. I have some long string text fields that I have to make sure the character count does not exceed the maximum table field length .. The reason I want to enforce a strict field limit is the text will eventually fit into an program generated e-mail. I do not want someone writing a 1000 char message that I have to format in a limited space to fit into an e-mail .. hence why I use a fixed length char() field.

Here is my code .. the Table field is a Sql char(200) or char(400) text field ( nlen parameter ) .. again, I do not want an unlimited Sql "Text" field ..

Code: Select all

DEFINE DIALOG oUSERS RESOURCE "MEMO" ;
       TITLE cTITLE              ;

cSay1 := "Maximum "+alltrim(str(nLen))+" Charactors"
REDEFINE SAY oSay1 var cSay1 ID 195 of oUsers UPDATE
oSay1:SetColor(nRgb(7,7,224))

IF cMODE = "E" .or. cMode = "P"

   REDEFINE GET oMEMO      VAR cMEMO MEMO ID 130 of oUSERS UPDATE

ELSE     // view

   REDEFINE GET oMEMO      VAR cMEMO MEMO ID 130 of oUSERS COLOR CLR_BLACK, 16053492 READONLY

ENDIF


          oMemo:bGotFocus = { || oMemo:SetSel( 0, 0 ),;
                         oMemo:Goto( oMemo:GetLineCount() ),;
                         __Keyboard( Chr( VK_HOME ) ) }
   
REDEFINE BTNBMP oButt1 ID 111 ;     // ok
         RESOURCE "Ok" ;
         PROMPT "Save" LEFT 2007;
         ACTION (lOK := _Doit1(oRsTrav, @cMEMO, nLEN, oMEMO, cMODE, cButton ), ;
                 IF( lOK = .T., ( oUSERS:END(), oBtn1:Enable() ) ,)  );      
         GRADIENT GreyButtonGrad()

REDEFINE BTNBMP oButt2 ID 112 ;     // cancel
         RESOURCE "CANCEL" ;
         PROMPT "Cancel" LEFT 2007;
         ACTION oUSERS:END();
         GRADIENT GreyButtonGrad()

ACTIVATE DIALOG oUSERS ;
         ON INIT (If( cMode = "V", oButt1:Disable(), )) ;
         VALID (!GETKEYSTATE( 27 ))  // do not allow esc key here

If cMode = "V"
Else

   oBtn1:Enable()
   cDesignation := cMemo

   SysReFresh()

Endif


oBtn2:Enable()
oBtn3:Enable()

RETURN( NIL )

//-----------------------------
// this function counts the number of characters in the memo string and warns if the length is >= to nLen

Static FUNC _Doit1( oRs, cMEMO, nLEN, oMEMO, cMODE, cButton )

LOCAL SAYING, nLENGTH, nSel

IF cMODE = 'V'
   RETURN(.T.)
ENDIF

cMEMO    := ALLTRIM( cMEMO )
nLENGTH  := LEN( cMEMO )

IF xWRITE = "Y" .or. xSUPER = "Y" .or. xADMIN = 'Y'

   IF nLENGTH > nLEN

      StandardGrad()

      SAYING := "WARNING .. your text is "+alltrim(STR(nLENGTH))+" charactors"+CRLF
      SAYING += "and the Database Table will only hold "+alltrim(str(nLen))+" charactors"+CRLF

      nSel := Alert( Saying ,;
                    { "Return and Make Changes", "Truncate Text to "+alltrim(STR(nLEN))+" Charactors" })

      Do Case
      Case nSel = 1
         oMemo:Setfocus()
         SysReFresh()

         Return(.f.)
      Case nSel = 2
         cMEMO := SUBSTR( cMEMO,1,nLEN )
         oMemo:ReFresh()
         oMemo:SetFocus()
         SysReFresh()
         Return(.f.)
      OtherWIse
         cMEMO := SUBSTR( cMEMO,1,nLEN )
         oMemo:ReFresh()
         oMemo:SetFocus()
         SysReFresh()
         Return(.f.)
      ENdCase

   ENDIF

ENDIF

RETURN(.T.)

 


What I would like to do is add a counter field to the diablg box to show the number of characters being typed in real time ??

Thanks
Rick Lipkin
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Re: Adding a real time character count to a memo field dialog bx

Post by Enrico Maria Giordano »

This is a sample with counter and limited text to 100 chars:

Code: Select all

#include "Fivewin.ch"


#define EM_LIMITTEXT 197


FUNCTION MAIN()

    LOCAL oDlg

    LOCAL oGet, cVar := ""

    LOCAL oSay

    DEFINE DIALOG oDlg

    @ 1, 1 GET oGet VAR cVar MEMO;
           SIZE 100, 30

    oGet:bKeyDown = { || SysRefresh(), oSay:Refresh( .F. ) }

    @ 3, 1 BUTTON "&Close" ACTION oDlg:End()

    @ 3, 10 SAY oSay PROMPT STR( LEN( cVar ) )

    ACTIVATE DIALOG oDlg;
             ON INIT oGet:SendMsg( EM_LIMITTEXT, 100, 0 );
             CENTER

    RETURN NIL
EMG
Horizon
Posts: 997
Joined: Fri May 23, 2008 1:33 pm

Re: Adding a real time character count to a memo field dialog bx

Post by Horizon »

Maybe like this.

Code: Select all

    @ 50,10 SAY oSay PROMPT "Mesaj" OF oDlg PIXEL 
    @ 48,40 GET oGovde VAR Govde OF oDlg PIXEL SIZE 110,10 UPDATE MEMO ;
            ON CHANGE (oSayac:VarPut("("+NTRIM(LEN(oGovde:GetText()))+")"),;
                oSayac:Refresh())
    
    @ 62,10 SAY oSayac PROMPT "(Boş)" OF oDlg PIXEL SIZE 30,10
   
Regards,

Hakan ONEMLI

Harbour & VS 2019 & FWH 20.12
User avatar
Rick Lipkin
Posts: 2397
Joined: Fri Oct 07, 2005 1:50 pm
Location: Columbia, South Carolina USA

Re: Adding a real time character count to a memo field dialog bx

Post by Rick Lipkin »

Enrico

Thank you for your responce .. been a while since we had a chance to chat ... I am having difficulty translating your code into using resources ..

this is my current code .. I can get it to initially come up but when I click on the get field .. the code blows up ..

Code: Select all

//------------------------------------
Static FUNC _ViewMemo4( cMODE, oRsTrav, cTABLENAME, oBtn1,oBtn2,oBtn3,oBtn4,oBtn5,cButton,cBenefits,nLen,cPrevAppr )       // benefits button

#define EM_LIMITTEXT 197

LOCAL SAYING, oUSERS, cTITLE, oMEMO, cMEMO
LOCAL lOK, oButt1,oButt2

Local oSay1,cSay1
Local oSay

IF EMPTY( cMODE )
   cMODE := "V"
ENDIF

IF xWRITE = "Y" .or. xSUPER = "Y" .or. xADMIN = 'Y'
ELSE
   cMODE := "V"
ENDIF

IF oRsTrav:eof
   SAYING := "SORRY ... Before you can Write a Memo "
   SAYING += "a Record must Already Exist"
   MsgInfo( SAYING )
   RETURN( .F. )
ENDIF

oBtn1:Disable()
oBtn2:Disable()
oBtn3:Disable()

LightGreyGrad()

DO CASE
CASE cMODE = "A"
   cTitle := cTABLENAME+" Table Memo for     'Purpose or Benefits Text'     ADD"
   cMEMO := space(nlen)    // 200

CASE cMODE = "E"
   cTitle := cTABLENAME+" Table Memo for     'Purpose or Benefits Text'     EDIT"
   cMemo := cBenefits

CASE cMODE = "V"
   cTitle := cTABLENAME+" Table Memo for     'Purpose or Benefits Text'     VIEW"
   cMEMO := oRsTrav:Fields("Benefits"):Value

CASE cMODE = "P"
   cTITLE := cTABLENAME+" Table Memo     Approval Info VIEW"
   cMEMO := oRsTrav:Fields("Benefits"):Value

ENDCASE

DEFINE DIALOG oUSERS RESOURCE "MEMO" ;
       TITLE cTITLE              ;

     cSay1 := "Maximum "+alltrim(str(nLen))+" Charactors"
     REDEFINE SAY oSay1 var cSay1 ID 195 of oUsers UPDATE
     oSay1:SetColor(nRgb(7,7,224))

     REDEFINE SAY oSay PROMPT Str(len(cMemo)) ID 196 of oUsers //UPDATE

     IF cMODE = "E" .or. cMode = "P"

        REDEFINE GET oMEMO      VAR cMEMO MEMO ID 130 of oUSERS UPDATE

     ELSE     // view

        REDEFINE GET oMEMO      VAR cMEMO MEMO ID 130 of oUSERS COLOR CLR_BLACK, 16053492 READONLY

    ENDIF

  *  oMemo:bGotFocus = { || oMemo:SetSel( 0, 0 ),;                           // blows up had to rem'd out
  *                        oMemo:Goto( oMemo:GetLineCount() ),;
  *                       __Keyboard( Chr( VK_HOME ) ) }

    oMemo:bKeyDown = { SysReFresh(), oSay:ReFresh() } // .f. ) }


    REDEFINE BTNBMP oButt1 ID 111 ;     // ok
         RESOURCE "Ok" ;
         PROMPT "Save" LEFT 2007;
         ACTION (lOK := _Doit1(oRsTrav, @cMEMO, nLEN, oMEMO, cMODE, cButton ), ;
                 IF( lOK = .T., ( oUSERS:END(), oBtn1:Enable() ) ,)  );
         GRADIENT GreyButtonGrad()

    REDEFINE BTNBMP oButt2 ID 112 ;     // cancel
         RESOURCE "CANCEL" ;
         PROMPT "Cancel" LEFT 2007;
         ACTION oUSERS:END();
         GRADIENT GreyButtonGrad()

ACTIVATE DIALOG oUSERS ;
         ON INIT (oMemo:SendMsg( EM_LIMITTEXT,100,0 ),If( cMode = "V", oButt1:Disable(), )) ;
         VALID (!GETKEYSTATE( 27 ))  // do not allow esc key here

If cMode = "V"
Else

   oBtn1:Enable()
   cBenefits := cMemo

   SysReFresh()

Endif


oBtn2:Enable()
oBtn3:Enable()

RETURN( NIL )

 
Here is Memo.rc

Code: Select all

// Generated by ResEdit 1.6.6
// Copyright (C) 2006-2015
// http://www.resedit.net

#include <windows.h>
#include <commctrl.h>
//#include "resource.h"

#ifndef WC_STATIC
#define WC_STATIC L"Static"
#endif

#ifndef MONTHCAL_CLASS
#define MONTHCAL_CLASS "SysMonthCal32"
#endif

#ifndef DATETIMEPICK_CLASS
#define DATETIMEPICK_CLASS "SysDateTimePick32"
#endif

//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
MEMO DIALOG 150, 47, 353, 135
STYLE DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_POPUP
FONT 6, "MS Sans Serif"
{
    EDITTEXT        196, 107, 102, 25, 12, WS_DISABLED, WS_EX_LEFT
    LTEXT           "Max 400 char", 195, 4, 103, 95, 9, SS_LEFT | SS_NOPREFIX, WS_EX_LEFT
    EDITTEXT        130, 40, 8, 307, 80, WS_VSCROLL | ES_MULTILINE | ES_WANTRETURN, WS_EX_LEFT
    CONTROL         "Ok", 111, "TBtnBmp", 0x50010020, 247, 100, 45, 24, 0x00000000
    LTEXT           "Memo", 194, 3, 11, 35, 9, SS_LEFT | SS_NOPREFIX, WS_EX_LEFT
    CONTROL         "Cancel", 112, "TBtnBmp", 0x50010020, 300, 100, 45, 24, 0x00000000
}

 
Passing the variable cBenefits which I initializes cMemo .. from there I have tried to interpret your code and failed ..

Code: Select all

Application
===========
   Path and name: C:\Fox\DOI\LeavTrav\LeaveW32.Exe (32 bits)
   Size: 6,641,664 bytes
   Compiler version: xHarbour 1.2.3 Intl. (SimpLex) (Build 20200311)
   FiveWin  version: FWH 20.06
   C compiler version: Borland/Embarcadero C++ 7.4 (32-bit)
   Windows version: 6.2, Build 9200 

   Time from start: 0 hours 0 mins 14 secs 
   Error occurred at: 07/20/2020, 14:09:54
   Error description: Error BASE/1004  Class: 'ARRAY' has no exported method: EVAL
   Args:
     [   1] = A   { ... } length: 2
     [   2] = N   75
     [   3] = N   2424833
     [   4] = O   TMULTIGET

Stack Calls
===========
   Called from:  => EVAL( 0 )
   Called from: .\source\classes\WINDOW.PRG => TWINDOW:KEYDOWN( 2867 )
   Called from: .\source\classes\CONTROL.PRG => TCONTROL:KEYDOWN( 1114 )
   Called from: .\source\classes\MGET.PRG => TMULTIGET:KEYDOWN( 661 )
   Called from:  => TWINDOW:HANDLEEVENT( 0 )
   Called from: .\source\classes\CONTROL.PRG => TMULTIGET:HANDLEEVENT( 1827 )
   Called from: .\source\classes\WINDOW.PRG => _FWH( 3559 )
   Called from:  => DIALOGBOX( 0 )
   Called from: .\source\classes\DIALOG.PRG => TDIALOG:ACTIVATE( 304 )
   Called from: REQUEST.PRG => _VIEWMEMO4( 4035 )
   Called from: REQUEST.PRG => (b)_REQUEST( 1447 )
 
Appreciate any suggestions ...

Thanks
Rick Lipkin
User avatar
Rick Lipkin
Posts: 2397
Joined: Fri Oct 07, 2005 1:50 pm
Location: Columbia, South Carolina USA

Re: Adding a real time character count to a memo field dialog bx

Post by Rick Lipkin »

Enrico

Try this code ... I get an initial value .. of 179 .. but the len of cMemo is not updated as you type in more charactors ..

Thanks
Rick

Code: Select all

#include "Fivewin.ch"
#define EM_LIMITTEXT 197


FUNCTION MAIN()

LOCAL oDlg
LOCAL cMemo, oMemo, cTitle
LOCAL oSay,cSay



cMemo := "Many years experience with and a good understanding of IP networking, IP printing, SMTP "
cMemo += "routing for multi-function printers, scanners, copiers and general configurations of Cisco "

cTITLE := "Request Table Memo for     'Travel Rejection Text'    EDIT"
cSay   := "Number of Charactors Typed"


DEFINE DIALOG oDlg RESOURCE "MEMO" ;
       TITLE cTITLE

       REDEFINE GET oMemo VAR cMEMO MEMO ID 130 of oDlg UPDATE

       oMemo:bGotFocus = { || oMemo:SetSel( 0, 0 ),;
                         oMemo:Goto( oMemo:GetLineCount() ),;
                         __Keyboard( Chr( VK_HOME ) ) }

       REDEFINE SAY oSay VAR str(len(cMemo)) ID 196 of oDlg UPDATE

       REDEFINE BTNBMP oButt1 ID 111 ;     // ok
         RESOURCE "Ok" ;
         PROMPT "Save" LEFT 2007;
         ACTION ( oDlg:End() )

       REDEFINE BTNBMP oButt2 ID 112 ;     // cancel
         RESOURCE "CANCEL" ;
         PROMPT "Cancel" LEFT 2007;
         ACTION oDLg:ENd()


ACTIVATE DIALOG oDlg ;
         ON INIT oMemo:SendMsg( EM_LIMITTEXT,500,0);
         VALID (!GETKEYSTATE( 27 ))  // do not allow esc key here

Return(nil)
 
Here is the Memo.rc

Code: Select all

// Generated by ResEdit 1.6.6
// Copyright (C) 2006-2015
// http://www.resedit.net

#include <windows.h>
#include <commctrl.h>
//#include "resource.h"

#ifndef WC_STATIC
#define WC_STATIC L"Static"
#endif

#ifndef MONTHCAL_CLASS
#define MONTHCAL_CLASS "SysMonthCal32"
#endif

#ifndef DATETIMEPICK_CLASS
#define DATETIMEPICK_CLASS "SysDateTimePick32"
#endif

//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
MEMO DIALOG 150, 47, 353, 135
STYLE DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_POPUP
FONT 6, "MS Sans Serif"
{
    EDITTEXT        196, 107, 102, 45, 12, WS_DISABLED | NOT WS_TABSTOP, WS_EX_LEFT
    LTEXT           "Max 400 char", 195, 4, 103, 95, 9, SS_LEFT | SS_NOPREFIX, WS_EX_LEFT
    EDITTEXT        130, 40, 8, 307, 80, WS_VSCROLL | ES_MULTILINE | ES_WANTRETURN, WS_EX_LEFT
    CONTROL         "Ok", 111, "TBtnBmp", 0x50010020, 247, 100, 45, 24, 0x00000000
    LTEXT           "Memo", 194, 3, 11, 35, 9, SS_LEFT | SS_NOPREFIX, WS_EX_LEFT
    CONTROL         "Cancel", 112, "TBtnBmp", 0x50010020, 300, 100, 45, 24, 0x00000000
}
 
Horizon
Posts: 997
Joined: Fri May 23, 2008 1:33 pm

Re: Adding a real time character count to a memo field dialog bx

Post by Horizon »

Rick,

Change this.

Code: Select all

       REDEFINE GET oMemo VAR cMEMO MEMO ID 130 of oDlg UPDATE ;
                    ON CHANGE (oSay:VarPut(ALLTRIM(str(LEN(oMemo:GetText())))),;
                oSay:Refresh())
Regards,

Hakan ONEMLI

Harbour & VS 2019 & FWH 20.12
User avatar
Rick Lipkin
Posts: 2397
Joined: Fri Oct 07, 2005 1:50 pm
Location: Columbia, South Carolina USA

Re: Adding a real time character count to a memo field dialog bx

Post by Rick Lipkin »

Hakan

Thank you VERY much for your input and nicely done.. works perfectly .. Enrico .. again that you very much for your help!!

Rick Lipkin
Post Reply