Page 3 of 4

Posted: Sat Mar 21, 2009 11:01 pm
by thanos
When compiling the code with PureBasic 4.30 i received an error in line 132 'Syntax error'

Code: Select all

Procedure.s _xm_StripCharacters(xMask.__s_xMask_Main(), Text.s, IndexBegin.l)
What is wrong?
Regards

Thanos

Posted: Sun Mar 22, 2009 1:27 am
by srod

Code: Select all

Procedure.s _xm_StripCharacters(List xMask.__s_xMask_Main(), Text.s, IndexBegin.l) 
You need to declare linked lists and arrays when used as parameters now.

Posted: Sun Mar 22, 2009 9:48 am
by thanos
srod wrote:

Code: Select all

Procedure.s _xm_StripCharacters(List xMask.__s_xMask_Main(), Text.s, IndexBegin.l) 
You need to declare linked lists and arrays when used as parameters now.
Thanks srod!
It is working now.
Btw, congratulations about the ADOmate and COMate libraries.
Excellent work.
Regards.

Thanos

Posted: Mon Apr 20, 2009 11:01 am
by kinglestat
nice control Zombie
I might have a use for this you know

Re: xMask - A Masked Edit Gadget

Posted: Tue Mar 29, 2011 8:41 pm
by mx101
hi... Xombie

can you update the code to use in PB 4.51??


not work in PB 5.1 can you update the code?


thanks

Re: xMask - A Masked Edit Gadget

Posted: Tue Mar 29, 2011 10:38 pm
by netmaestro
Xombie hasn't posted in over six months. Let's give him a few days to respond and if none comes I'll update the code to the current version for you. You can also try to PM him, that might work.

Re: xMask - A Masked Edit Gadget

Posted: Wed Mar 30, 2011 7:27 am
by mx101
netmaestro wrote:Xombie hasn't posted in over six months. Let's give him a few days to respond and if none comes I'll update the code to the current version for you. You can also try to PM him, that might work.

oki netmaestro thank you very much :)

Re: xMask - A Masked Edit Gadget

Posted: Thu Mar 31, 2011 8:42 am
by Peyman
its updated and fixed some thing like work on x64 compiler and remove beep sound.
Update 1 Aprill 2011 :

Code: Select all

;=====================================================================
;  Program:            Masked String Gadget
;  Author:             Xombie, Updated By Peyman
;  Date:               April 1, 2011
;  Target OS:          Microsoft Windows All
;  Target Compiler:    PureBasic 4.xx X86/X64
;  License:            Free
;  Fixes :             Updating source to work with pb > 4.50 x86/x64 and many others fixes.
;=====================================================================
;
EnableExplicit

Declare SetGadgetMask(Gadget.i, TextMask.s, Text.s, PlaceHolder.b, RightToLeft.b = #False, SelectAllOnFocus.b = #False)
Declare RemoveGadgetMasks(Gadget.i)

Structure __s_xMask_Main
   ;
   Gadget.i
   ;
   Handle.i
   ;
   TextMask.s
   ;
   Text.s
   ;
   PlaceHolder.c
   ;
   RightToLeft.b
   ;
   OldCallback.i
   ;
   MaxLength.i
   ;
   SelectAllOnFocus.b
   ; If True, when the the xMask gadget is selected it will select the whole line.
   AdjustingText.b
   ; True if the callback is temporarily setting text.
EndStructure

Global NewList __xm_Main.__s_xMask_Main()

;- Internal Procedures
Procedure InsertCharacter(*HoldText.i, Index.i, Character.c)
   ;
   CompilerIf #PB_Compiler_Unicode = #True
      ;
      PokeC(*HoldText + (Index << 1), Character)
      ;
   CompilerElse
      ;
      PokeC(*HoldText + Index, Character)
      ;
   CompilerEndIf
   ;
EndProcedure

Procedure.i _xm_GetMaxLength(TextMask.s)
   ;
   Protected.Character *HoldChar
   ;
   Protected.b AllowAsNonFormatting
   ;
   Protected.i lResult
   ;
   *HoldChar = @TextMask
   ;
   While *HoldChar\c <> 0
      ;
      If AllowAsNonFormatting
         ;
         lResult + 1
         ;
         AllowAsNonFormatting = #False
         ;
      Else
         ;
         If *HoldChar\c = '0'
            ; This is a required number field.
            lResult + 1
            ;
         ElseIf *HoldChar\c = '9'
            ; This is a non-required number field.  Either a digit or a space is allowed here.
            lResult + 1
            ;
         ElseIf *HoldChar\c = 'L'
            ; A - Z, entry required
            lResult + 1
            ;
         ElseIf *HoldChar\c = '?'
            ; A - Z, entry optional.
            lResult + 1
            ;
         ElseIf *HoldChar\c = 'A'
            ; A - Z or 0 - 9, entry required.
            lResult + 1
            ;
         ElseIf *HoldChar\c = 'a'
            ; A - Z or 0 - 9, entry optional.
            lResult + 1
            ;
         ElseIf *HoldChar\c = '&'
            ; Any character or space, entry required.
            lResult + 1
            ;
         ElseIf *HoldChar\c = 'C'
            ; Any character or space, entry optional.
            lResult + 1
            ;
         ElseIf *HoldChar\c = ''
            ;
            ;
         ElseIf *HoldChar\c = ' '
            ;
            lResult + 1
            ;
         ElseIf *HoldChar\c = '\'
            ; The 'force non-formatting character' character.  Ignore this character and do not increase the maximum length.
            AllowAsNonFormatting = #True
            ; The following character will be included in the display no matter what it is.
         Else
            ; The character was a non-formating character.  Add it as-is.
            lResult + 1
            ; A display character always increases the length.
         EndIf
         ;
      EndIf
      ;
      CompilerIf #PB_Compiler_Unicode = #True : *HoldChar + 2 : CompilerElse : *HoldChar + 1 : CompilerEndIf
      ;
   Wend
   ;
   ProcedureReturn lResult
   ;
EndProcedure

Procedure.s _xm_StripCharacters(List xMask.__s_xMask_Main(), Text.s, IndexBegin.i)
   ; This procedure is used to to strip out unneeded characters in text being inserted into a mask.
   Protected.Character *HoldMask
   ;
   Protected.Character *HoldChar
   ;
   Protected.Character *OutText
   ;
   Protected.s HoldString
   ;
   Protected.b IsFormatting
   ;
   Protected.b FailedMask
   ;
   Protected.b ForceAdd
   ;
   *HoldChar = @Text
   ;
   *HoldMask = @xMask()\TextMask + (IndexBegin - 1)
   ;
   HoldString = Space(Len(Text))
   ;
   *OutText = @HoldString
   ;
   While *HoldMask\c And *HoldChar\c
      ;
      FailedMask = #True
      ;
      If *HoldMask\c = '0'
         ; Required numeric field (0-9).
         If *HoldChar\c > 47 And *HoldChar\c < 58 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = '9'
         ; Non-required numeric field.  A number (0-9) or a space is allowed.
         If (*HoldChar\c > 47 And *HoldChar\c < 58) Or *HoldChar\c = 32 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = 'L'
         ; A - Z, entry required.
         If (*HoldChar\c > 64 And *HoldChar\c < 91) Or (*HoldChar\c > 96 And *HoldChar\c < 123) : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = '?'
         ; A - Z, entry not required and may include spaces.
         If (*HoldChar\c > 64 And *HoldChar\c < 91) Or (*HoldChar\c > 96 And *HoldChar\c < 123) Or *HoldChar\c = 32 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = 'A'
         ; A - Z or 0 - 9, entry required.
         If (*HoldChar\c > 64 And *HoldChar\c < 91) Or (*HoldChar\c > 96 And *HoldChar\c < 123) Or (*HoldChar\c > 47 And *HoldChar\c < 58) : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = 'a'
         ; A - Z or 0 - 9, entry not required and may include spaces.
         If (*HoldChar\c > 64 And *HoldChar\c < 91) Or (*HoldChar\c > 96 And *HoldChar\c < 123) Or (*HoldChar\c > 47 And *HoldChar\c < 58) Or *HoldChar\c = 32 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = '&'
         ; Any character or space, entry required.
         If *HoldChar\c > 32 And *HoldChar\c < 256 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = 'C'
         ; Any character or space, entry not required and may include spaces.
         If (*HoldChar\c > 32 And *HoldChar\c < 256) Or *HoldChar\c = 32 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = '>'
         ; Capitalize the following character.
         IsFormatting = #True
         ;
      ElseIf *HoldMask\c = '<'
         ; Decapitalize the following character.
         IsFormatting = #True
         ;
      ElseIf *HoldMask\c = '\'
         ; Add the next character as-is.
         IsFormatting = #True
         ;
      Else
         ;
         ForceAdd = #True
         ;
         If *HoldMask\c = *HoldChar\c : FailedMask = #False : EndIf
         ;
      EndIf
      ;
      If IsFormatting = #False
         ;
         If FailedMask
            ;
            ProcedureReturn Text
            ;
         Else
            ;
            If ForceAdd = #False
               ;
               *OutText\c = *HoldChar\c
               ;
               CompilerIf #PB_Compiler_Unicode = #True : *OutText + 2 : CompilerElse : *OutText + 1 : CompilerEndIf
               ;
            EndIf
            ;
            CompilerIf #PB_Compiler_Unicode = #True : *HoldChar + 2 : CompilerElse : *HoldChar + 1 : CompilerEndIf
            ;
         EndIf
         ;
      EndIf
      ;
      ForceAdd = #False : IsFormatting = #False
      ;
      CompilerIf #PB_Compiler_Unicode = #True : *HoldMask + 2 : CompilerElse : *HoldMask + 1 : CompilerEndIf
      ;
   Wend
   ;
   ProcedureReturn Left(HoldString, *OutText - @HoldString)
   ;
EndProcedure

Procedure.c _xm_ReturnCharacter(List xMask.__s_xMask_Main(), Character.c, *Index.i, UsingPlaceholder.b = #False)
   ;
   Protected.Character *HoldMask
   ;
   Protected.b IsFormatting
   ;
   Protected.b FailedMask
   ;
   Protected.b ForceAdd
   ;
   Protected.i Position
   ;
   Protected.b DoUpper, DoLower, IsStatic
   ;
   Protected.i HoldIndex
   ;
   *HoldMask = @xMask()\TextMask
   ;
   While *HoldMask\c
      ;
      FailedMask = #True
      ;
      If ForceAdd
         ;
         IsStatic = #True
         ;
      Else
         ;
         If *HoldMask\c = '0'
            ; Required numeric field (0-9).
            If Character > 47 And Character < 58 : FailedMask = #False : EndIf
            ;
         ElseIf *HoldMask\c = '9'
            ; Non-required numeric field.  A number (0-9) or a space is allowed.
            If (Character > 47 And Character < 58) Or Character = 32 : FailedMask = #False : EndIf
            ;
         ElseIf *HoldMask\c = 'L'
            ; A - Z, entry required.
            If (Character > 64 And Character < 91) Or (Character > 96 And Character < 123) : FailedMask = #False : EndIf
            ;
         ElseIf *HoldMask\c = '?'
            ; A - Z, entry not required and may include spaces.
            If (Character > 64 And Character < 91) Or (Character > 96 And Character < 123) Or Character = 32 : FailedMask = #False : EndIf
            ;
         ElseIf *HoldMask\c = 'A'
            ; A - Z or 0 - 9, entry required.
            If (Character > 64 And Character < 91) Or (Character > 96 And Character < 123) Or (Character > 47 And Character < 58) : FailedMask = #False : EndIf
            ;
         ElseIf *HoldMask\c = 'a'
            ; A - Z or 0 - 9, entry not required and may include spaces.
            If (Character > 64 And Character < 91) Or (Character > 96 And Character < 123) Or (Character > 47 And Character < 58) Or Character = 32 : FailedMask = #False : EndIf
            ;
         ElseIf *HoldMask\c = '&'
            ; Any character or space, entry required.
            If Character > 32 And Character < 256 : FailedMask = #False : EndIf
            ;
         ElseIf *HoldMask\c = 'C'
            ; Any character or space, entry not required and may include spaces.
            If (Character > 32 And Character < 256) Or Character = 32 : FailedMask = #False : EndIf
            ;
         ElseIf *HoldMask\c = '>'
            ; Capitalize the following character.
            IsFormatting = #True
            ;
            DoUpper = #True
            ;
         ElseIf *HoldMask\c = '<'
            ; Decapitalize the following character.
            IsFormatting = #True
            ;
            DoLower = #True
            ;
         ElseIf *HoldMask\c = '\'
            ; Add the next character as-is.
            IsFormatting = #True
            ;
            ForceAdd = #True
            ;
         Else
            ;
            IsStatic = #True
            ;
         EndIf
         ;
      EndIf
      ;
      ; If IsStatic And UsingPlaceholder : FailedMask = #True : Else : FailedMask = #False : EndIf
      If UsingPlaceholder : FailedMask = IsStatic : EndIf
      ;
      If IsFormatting = #False
         ;
         HoldIndex + 1
         ;
         If IsStatic = #False
            ;
            If Position = PeekL(*Index)
               ;
               PokeL(*Index, HoldIndex - 1)
               ;
               If FailedMask
                  ;
                  ProcedureReturn 0
                  ;
               Else
                  ;
                  If UsingPlaceholder
                     ;
                     ProcedureReturn xMask()\PlaceHolder
                     ;
                  ElseIf DoUpper
                     ;
                     If Character > 96 And Character < 123 : ProcedureReturn Character - 32 : Else : ProcedureReturn Character : EndIf
                     ;
                  ElseIf DoLower
                     ;
                     If Character > 64 And Character < 91 : ProcedureReturn Character + 32 : Else : ProcedureReturn Character : EndIf
                     ;
                  Else
                     ;
                     ProcedureReturn Character
                     ;
                  EndIf
                  ;
               EndIf
               ;
            EndIf
            ;
            Position + 1
            ;
         Else
            ;
            If UsingPlaceholder
               ;
               If Position = PeekL(*Index)
                  ;
                  PokeL(*Index, HoldIndex - 1)
                  ;
                  ProcedureReturn 0
                  ;
               EndIf
               ;
            EndIf
            ;
            If Position < PeekL(*Index) : Position + 1 : EndIf
            ;
         EndIf
         ;
         DoUpper = #False : DoLower = #False
         ;
      EndIf
      ;
      ForceAdd = #False : IsFormatting = #False : IsStatic = #False
      ;
      CompilerIf #PB_Compiler_Unicode = #True : *HoldMask + 2 : CompilerElse : *HoldMask + 1 : CompilerEndIf
      ;
   Wend
   ;
   ProcedureReturn 0
   ;
EndProcedure

Procedure.s _xm_MaskToText(List xMask.__s_xMask_Main(), Text.s, ForcePlaceHolder.b = #False)
   ; Inserts the mask into a string gadget with the placeholder character - replacing with Text as
   ; possible.  If ForcePlaceHolder is true, the returned string will just be the placeholder.
   Protected.Character *HoldChar
   ;
   Protected.Character *HoldMask
   ;
   Protected.Character *OutText
   ;
   Protected.s HoldString
   ;
   Protected.b IgnoreMask
   ; True if the last character was '\' - the next character is treated as an output character.
   Protected.b FailedMask
   ; True if the mask conditions are failed when inserting text.
   Protected.b IsFormatting
   ;
   Protected.b DoUpper, DoLower, ForceAdd
   ;
   *HoldMask = @xMask()\TextMask
   ;
   *HoldChar = @Text
   ;
   HoldString = Space(xMask()\MaxLength)
   ;
   *OutText = @HoldString
   ;
   While *HoldMask\c
      ; Loop until the end-of-line character is located.
      FailedMask = #True
      ; The mask fails by default.
      IsFormatting = #False
      ; A formatting character is the '>' or '<' or '\' character.
      If *HoldMask\c = '0'
         ; Required numeric field (0-9).
         If *HoldChar\c > 47 And *HoldChar\c < 58 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = '9'
         ; Non-required numeric field.  A number (0-9) or a space is allowed.
         If (*HoldChar\c > 47 And *HoldChar\c < 58) Or *HoldChar\c = 32 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = 'L'
         ; A - Z, entry required.
         If (*HoldChar\c > 64 And *HoldChar\c < 91) Or (*HoldChar\c > 96 And *HoldChar\c < 123) : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = '?'
         ; A - Z, entry not required and may include spaces.
         If (*HoldChar\c > 64 And *HoldChar\c < 91) Or (*HoldChar\c > 96 And *HoldChar\c < 123) Or *HoldChar\c = 32 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = 'A'
         ; A - Z or 0 - 9, entry required.
         If (*HoldChar\c > 64 And *HoldChar\c < 91) Or (*HoldChar\c > 96 And *HoldChar\c < 123) Or (*HoldChar\c > 47 And *HoldChar\c < 58) : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = 'a'
         ; A - Z or 0 - 9, entry not required and may include spaces.
         If (*HoldChar\c > 64 And *HoldChar\c < 91) Or (*HoldChar\c > 96 And *HoldChar\c < 123) Or (*HoldChar\c > 47 And *HoldChar\c < 58) Or *HoldChar\c = 32 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = '&'
         ; Any character or space, entry required.
         If *HoldChar\c > 32 And *HoldChar\c < 256 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = 'C'
         ; Any character or space, entry not required and may include spaces.
         If (*HoldChar\c > 32 And *HoldChar\c < 256) Or *HoldChar\c = 32 : FailedMask = #False : EndIf
         ;
      ElseIf *HoldMask\c = '>'
         ; Capitalize the following character.
         IsFormatting = #True
         ;
         DoUpper = #True
         ;
      ElseIf *HoldMask\c = '<'
         ; Decapitalize the following character.
         IsFormatting = #True
         ;
         DoLower = #True
         ;
      ElseIf *HoldMask\c = '\'
         ; Add the next character as-is.
         IsFormatting = #True
         ;
         ForceAdd = #True
         ;
      Else
         ;
         ForceAdd = #True
         ;
         FailedMask = #False
         ;
      EndIf
      ;
      If IsFormatting = #False Or ForcePlaceHolder
         ;
         If ForcePlaceHolder Or *HoldChar\c = 0 : FailedMask = #False : EndIf
         ;
         If FailedMask
            ; The text does not match the mask.
            ProcedureReturn ""
            ; Return an empty string.
         Else
            ;
            If ForceAdd
               ;
               *OutText\c = *HoldMask\c
               ;
            ElseIf ForcePlaceHolder Or *HoldChar\c = 0
               ;
               *OutText\c = xMask()\PlaceHolder
               ;
            Else
               ;
               If DoUpper
                  ;
                  *OutText\c = Asc(UCase(Mid(Text, *HoldChar - @Text + 1, 1)))
                  ;
               ElseIf DoLower
                  ;
                  *OutText\c = Asc(LCase(Mid(Text, *HoldChar - @Text + 1, 1)))
                  ;
               Else
                  ;
                  *OutText\c = *HoldChar\c
                  ; Store the current character.
               EndIf
               ;
               CompilerIf #PB_Compiler_Unicode = #True : *HoldChar + 2 : CompilerElse : *HoldChar + 1 : CompilerEndIf
               ;
            EndIf
            ;
            CompilerIf #PB_Compiler_Unicode = #True : *OutText + 2 : CompilerElse : *OutText + 1 : CompilerEndIf
            ; Point to the next available space.
         EndIf
         ;
         DoUpper = #False : DoLower = #False : ForceAdd = #False
         ;
      EndIf
      ;
      CompilerIf #PB_Compiler_Unicode = #True : *HoldMask + 2 : CompilerElse : *HoldMask + 1 : CompilerEndIf
      ;
   Wend
   ;
   ProcedureReturn Left(HoldString, *OutText - @HoldString)
   ;
EndProcedure

Procedure _xm_ClearText(List xMask.__s_xMask_Main(), OnlyHighlighted = #False)
   ;
   Protected.c Character
   ;
   Protected.s HoldString
   ;
   Protected.i iLoop, HoldIndex
   ;
   Protected.POINT HoldSelect
   ;
   SendMessage_(xMask()\Handle, #EM_GETSEL, @HoldSelect\X, @HoldSelect\Y)
   ; Retrieve the start and end selection values.  We'll use this when replacing characters.
   If OnlyHighlighted And HoldSelect\X = HoldSelect\Y : ProcedureReturn : EndIf
   ;
   If HoldSelect\X < xMask()\MaxLength
      ;
      If HoldSelect\X < HoldSelect\Y : HoldSelect\Y - 1 : EndIf
      ;
      HoldString = GetGadgetText(xMask()\Gadget)
      ;
      For iLoop = HoldSelect\X To HoldSelect\Y
         ;
         HoldIndex = iLoop
         ;
         Character = _xm_ReturnCharacter(xMask(), 0, @HoldIndex, #True)
         ;
         If Character : InsertCharacter(@HoldString, HoldIndex, Character) : EndIf
         ;
      Next iLoop
      ;
      xMask()\AdjustingText = #True
      ;
      SetGadgetText(xMask()\Gadget, HoldString)
      ;
      xMask()\AdjustingText = #False
      ;
      SendMessage_(xMask()\Handle, #EM_SETSEL, HoldSelect\X, HoldSelect\X)
      ;
   EndIf
   ;
EndProcedure

Procedure.b _xm_CheckStatic(List xMask.__s_xMask_Main(), Index.i, Text.s) ;By Peyman
  Protected.Character *HoldMask

  *HoldMask = @xMask()\TextMask
  *HoldMask + Index
   
  Select *HoldMask\c
    Case '0', '9', 'L', '?', 'A', 'a', '&', 'C', '>', '<', '\'
      ProcedureReturn #False
      
    Default
      If *HoldMask\c = Asc(Text)
        ProcedureReturn #True
      Else
        ProcedureReturn #False
      EndIf
      
  EndSelect
 
EndProcedure


Procedure _xm_EditCallback(HandleWindow.i, message.i, wParam.i, lParam.i)
   ; This is a custom callback function used by our xMask gadget.  We'll use this to check
   ; for various events and handle them in the appropriate manner.
   Protected.b CaughtMatch
   ;
   Protected.i iLoop
   ;
   Protected.i lResult
   ;
   Protected.i HoldStyle
   ;
   Protected.s HoldString, HoldText
   ;
   Protected.POINT HoldSelect
   ;
   Protected.c Character
   ;
   Protected.i HoldIndex
   ;
   ResetList(__xm_Main())
   While NextElement(__xm_Main())
      ;
      If __xm_Main()\Handle = HandleWindow : CaughtMatch = #True : Break : EndIf
      ;
   Wend
   ;
   If CaughtMatch = #False : ProcedureReturn : EndIf
   ; This should never happen but exit if the string gadget is not on the list.
   HoldStyle = GetWindowLongPtr_(__xm_Main()\Handle, #GWL_STYLE)
   ; Get the style of the string gadget.
   If HoldStyle & #ES_READONLY = 0
      ; Ensure the string gadget is not read only.
      If message = #WM_SETTEXT
         ;{ Text is changing via a 'SetGadgetText()' call.
         If __xm_Main()\AdjustingText = #False
            ;
            HoldString = _xm_MaskToText(__xm_Main(), _xm_StripCharacters(__xm_Main(), PeekS(lParam), 1), #False)
            ; Check the text against the mask and store the result.  lParam is the pointer to the updating text.
            If HoldString <> ""
               ;
               __xm_Main()\AdjustingText = #True
               ;
               SetGadgetText(__xm_Main()\Gadget, HoldString)
               ; Update the text in the control.
               __xm_Main()\AdjustingText = #False
               ;
            EndIf
            ;
            message = 0
            ; Clear the message - the text is handled internally.
         EndIf
         ;}
      ElseIf message = #WM_SETFOCUS
        ; The edit control received focus.
        If __xm_Main()\SelectAllOnFocus
          SendMessage_(__xm_Main()\Handle, #EM_SETSEL, #Null, -1)
        EndIf
         ; Select all text in the edit control.
      ElseIf message = #WM_CHAR
         ;{
         If wParam = #VK_BACK
           ;
            SendMessage_(__xm_Main()\Handle, #EM_GETSEL, @HoldSelect\X, @HoldSelect\Y)
            ; Retrieve the start and end selection values.  We'll use this when replacing characters.
            If HoldSelect\X
               ;
               If HoldSelect\X = HoldSelect\Y : HoldSelect\X - 1 : HoldSelect\Y - 1 : EndIf
               ;
               HoldString = GetGadgetText(__xm_Main()\Gadget)
               ;
               For iLoop = HoldSelect\X To HoldSelect\Y
                  ;
                  HoldIndex = iLoop
                  ;
                  Character = _xm_ReturnCharacter(__xm_Main(), wParam, @HoldIndex, #True)
                  ;
                  If Character : InsertCharacter(@HoldString, HoldIndex, Character) : EndIf
                  ;
               Next iLoop
               ;
               __xm_Main()\AdjustingText = #True
               ;
               SetGadgetText(__xm_Main()\Gadget, HoldString)
               ;
               __xm_Main()\AdjustingText = #False
               ;
               SendMessage_(__xm_Main()\Handle, #EM_SETSEL, HoldSelect\X, HoldSelect\X)
               
               ;By Peyman
               If _xm_CheckStatic(__xm_Main(), HoldSelect\X - 1, Mid(HoldString, HoldSelect\X, 1))
                 SendMessage_(__xm_Main()\Handle, #EM_SETSEL, HoldSelect\X - 1, HoldSelect\X - 1)
               EndIf
               ;
               ;
               
            EndIf
            ;
         Else
           ;
           
            SendMessage_(__xm_Main()\Handle, #EM_GETSEL, @HoldSelect\X, @HoldSelect\Y)
            ; Retrieve the start and end selection values.  We'll use this when replacing characters.
            If HoldSelect\X <= __xm_Main()\MaxLength
               ; Do not allow any text past the maximum length.
               HoldIndex = HoldSelect\X
               ;
               Character = _xm_ReturnCharacter(__xm_Main(), wParam, @HoldSelect\X)
               ;
               If Character
                  ;
                  HoldString = GetGadgetText(__xm_Main()\Gadget)
                  ;
                  InsertCharacter(@HoldString, HoldSelect\X, Character)
                  ;
                  __xm_Main()\AdjustingText = #True
                  ;
                  SetGadgetText(__xm_Main()\Gadget, HoldString)
                  ;
                  __xm_Main()\AdjustingText = #False
                  ;
                  HoldSelect\X + 1
                  SendMessage_(__xm_Main()\Handle, #EM_SETSEL, HoldSelect\X, HoldSelect\X) ; HoldSelect\y + (HoldSelect\x - HoldIndex) + 1)
                  
                  ;By Peyman
                  If _xm_CheckStatic(__xm_Main(), HoldSelect\X, Mid(HoldString, HoldSelect\X + 1, 1))
                    SendMessage_(__xm_Main()\Handle, #EM_SETSEL, HoldSelect\X + 1, HoldSelect\X + 1)
                  EndIf
                  
                  ;
               EndIf
               ;
            EndIf
            ;
         EndIf
         ;
         ; Flush the charcter And prevent program from say beep ;-)
         message = 0
         
         ;}
      ElseIf message = #WM_KEYDOWN
         ;{ A key is down.  This event will fire along with #WM_CHAR.  wParam returns the virtual key code.
         If wParam = #VK_DELETE
           ;
            _xm_ClearText(__xm_Main()) : wParam = 0
            ;
         EndIf
         
         ;By Peyman
         If wParam = #VK_RIGHT
           ;
           SendMessage_(__xm_Main()\Handle, #EM_GETSEL, @HoldSelect\X, @HoldSelect\Y)
           HoldString = GetGadgetText(__xm_Main()\Gadget)
           
           HoldSelect\X + 1
           
           If _xm_CheckStatic(__xm_Main(), HoldSelect\X, Mid(HoldString, HoldSelect\X + 1, 1))
            SendMessage_(__xm_Main()\Handle, #EM_SETSEL, HoldSelect\X, HoldSelect\X)
           EndIf
            ;
         EndIf
         
         ;By Peyman
         If wParam = #VK_LEFT
           ;
           SendMessage_(__xm_Main()\Handle, #EM_GETSEL, @HoldSelect\X, @HoldSelect\Y)
           If HoldSelect\X = HoldSelect\Y : HoldSelect\X - 1 : HoldSelect\Y - 1 : EndIf
           HoldString = GetGadgetText(__xm_Main()\Gadget)
           
           If _xm_CheckStatic(__xm_Main(), HoldSelect\X - 1, Mid(HoldString, HoldSelect\X, 1))
            SendMessage_(__xm_Main()\Handle, #EM_SETSEL, HoldSelect\X, HoldSelect\X)
           EndIf
            ;
         EndIf
          
         ;}
      ElseIf message = #WM_CLEAR
         ;{ The delete submenu from the right-click menu is called.
         _xm_ClearText(__xm_Main(), #True) : message = 0
         ;
         ;}
      ElseIf message = #WM_CUT
         ;{ The cut submenu from the right-click menu is called.
         SendMessage_(__xm_Main()\Handle, #EM_GETSEL, @HoldSelect\X, @HoldSelect\Y)
         ; Retrieve the start and end selection values.  We'll use this when replacing characters.
         If HoldSelect\X = HoldSelect\Y : ProcedureReturn : EndIf
         ;
         HoldString = Mid(GetGadgetText(__xm_Main()\Gadget), HoldSelect\X + 1, HoldSelect\Y - HoldSelect\X)
         ;
         SetClipboardText(HoldString)
         ;
         _xm_ClearText(__xm_Main(), #True) : message = 0
         ;
         ;}
      ElseIf message = #WM_PASTE
         ;{ The paste submenu from the right-click menu is called.
         SendMessage_(__xm_Main()\Handle, #EM_GETSEL, @HoldSelect\X, @HoldSelect\Y)
         ; Retrieve the start and end selection values.  We'll use this when replacing characters.
         If HoldSelect\X = HoldSelect\Y : ProcedureReturn : EndIf
         ;
         HoldString = GetGadgetText(__xm_Main()\Gadget)
         ;
         HoldText = _xm_StripCharacters(__xm_Main(), GetClipboardText(), HoldSelect\X + 1)
         ;
         HoldIndex = 1
         ;
         For iLoop = HoldSelect\X To HoldSelect\Y
            ;
            Character = _xm_ReturnCharacter(__xm_Main(), Asc(Mid(HoldText, HoldIndex, 1)), @iLoop, #False)
            ;
            If Character : InsertCharacter(@HoldString, iLoop, Character) : EndIf
            ;
            HoldIndex + 1
            ;
         Next iLoop
         ;
         __xm_Main()\AdjustingText = #True
         ;
         SetGadgetText(__xm_Main()\Gadget, HoldString)
         ; Update the text in the control.
         __xm_Main()\AdjustingText = #False
         ;
         SendMessage_(__xm_Main()\Handle, #EM_SETSEL, HoldSelect\Y, HoldSelect\Y)
         ;
         message = 0
         ;
         ;}
      EndIf
      ;
   EndIf
   ;
   lResult = CallWindowProc_(__xm_Main()\OldCallback, HandleWindow, message, wParam, lParam)
   ; Call the original edit control's callback function for any messages not handled.
   ProcedureReturn lResult
   ;
EndProcedure

;- Main Procedures
Procedure.s xm_GetRawData(Gadget.i)
  ;
  ResetList(__xm_Main())
  While NextElement(__xm_Main())
    ;
    If __xm_Main()\Gadget = Gadget
      ;
      ProcedureReturn _xm_StripCharacters(__xm_Main(), GetGadgetText(__xm_Main()\Gadget), 1)
      ;
    EndIf
    ;
  Wend
  ;
  ProcedureReturn ""
  ;
EndProcedure

Procedure RemoveGadgetMasks(Gadget.i) ; Use 0 to remove all masks.
  ;
  ResetList(__xm_Main())
  While NextElement(__xm_Main())
    ;
    If Not Gadget Or Gadget = __xm_Main()\Gadget
      ;
      SetWindowLongPtr_(__xm_Main()\Handle, #GWLP_WNDPROC, __xm_Main()\OldCallback)
      ; Now set the custom callback to use for the new xMask gadget.
      DeleteElement(__xm_Main())
      ;
    EndIf
    ;
  Wend
  ;
EndProcedure

Procedure SetGadgetMask(Gadget.i, TextMask.s, Text.s, PlaceHolder.b, RightToLeft.b = #False, SelectAllOnFocus.b = #False)
  ; Modifies a string gadget to only accept certain characters based on a mask.
  Protected.s HoldString
  ; The handle of the gadget.
  Protected.i Handle
   
  Handle = GadgetID(Gadget)
  ; Truncate the string based on the number of characters copied.
  If GadgetType(Gadget) = #PB_GadgetType_String
    ; Only edit controls may be masked.
    ResetList(__xm_Main())
    While NextElement(__xm_Main())
      ;
      If __xm_Main()\Gadget = Gadget
        ProcedureReturn
      EndIf
      ; Do not allow duplicates.
    Wend
    ;
    AddElement(__xm_Main())
    ; Add a new xMask control.
    With __xm_Main()
      ;
      \Gadget = Gadget
      \Handle = Handle
      ;
      \TextMask = TextMask
      \Text = Text
      ;
      \PlaceHolder = PlaceHolder
      \RightToLeft = RightToLeft
      ;
      \MaxLength = _xm_GetMaxLength(TextMask)
      ; Get the maximum allowed length of the edit control.
      \SelectAllOnFocus = SelectAllOnFocus
      ;
    EndWith
    ;
    HoldString = _xm_MaskToText(__xm_Main(), Text, #False)
    ;
    If HoldString = ""
      HoldString = _xm_MaskToText(__xm_Main(), HoldString, #True)
    EndIf
    ;
    SetGadgetText(Gadget, HoldString)
    ;
    SendMessage_(Handle, #EM_LIMITTEXT, __xm_Main()\MaxLength, #Null)
    ; Set the maximum number of allowed characters.
    ; Store the original callback procedure address for the Edit control and set the custom callback to use for the new xMask gadget.
    __xm_Main()\OldCallback = SetWindowLongPtr_(__xm_Main()\Handle, #GWLP_WNDPROC, @_xm_EditCallback())
  EndIf
  ;
EndProcedure

;- Test Program
;{ Create Test Window
If OpenWindow(0, 0, 0, 400, 300, "Test", #PB_Window_TitleBar | #PB_Window_SystemMenu)
  StringGadget(0, 10, 10, 120, 20, "")
  SetGadgetMask(0, "999-99-9999", "123456789", '*', #False, #True)
  ButtonGadget(1, 80, 150, 50, 50,  "")
EndIf
;
Define.b DoQuit
;
Define.i HoldID
;
While DoQuit = #False
   ;
   HoldID = WaitWindowEvent()
   ;
   If HoldID = #PB_Event_CloseWindow
      ; Close the program.
      DoQuit = #True
      ;
   EndIf
   ;
Wend
;}
RemoveGadgetMasks(0)
End

Re: xMask - A Masked Edit Gadget

Posted: Thu Mar 31, 2011 10:55 am
by netmaestro
Thanks peyman! Please restore xombie's original header for the code and add a couple of lines identifying who updated the code, when and why.

Re: xMask - A Masked Edit Gadget

Posted: Thu Mar 31, 2011 3:22 pm
by mx101
Peyman and netmaestro thank you very much to both :D


How can i remove the beep sound ??

Re: xMask - A Masked Edit Gadget

Posted: Thu Mar 31, 2011 3:58 pm
by Peyman
@netmaestro:
thanks netmaestro, i cant find xombie's original header for the code so i write one.

@mx101 :
see my last post, its updated.

Re: xMask - A Masked Edit Gadget

Posted: Thu Mar 31, 2011 4:06 pm
by mx101
Peyman wrote:@netmaestro:
thanks netmaestro, i cant find xombie's original header for the code so i write one.

@mx101 :
see my last post, its updated.

thank you Peyman you save my day :D

thank you very much

Re: xMask - A Masked Edit Gadget

Posted: Thu Mar 31, 2011 7:11 pm
by ebs
Peyman,

Can you suggest a code change that would move the caret (text cursor) past any literal characters in the mask?
I would like it to move to the next character input position, because I think that makes it clearer where the next
character entered will go.

For example, using the example in the code, the mask is "999-99-9999".
If I enter "123", the StringGadget looks like this:

Code: Select all

123|-**-****
where "|" represents the caret.

I would like it to move past the "-" and look like this:

Code: Select all

123-|**-****
Thanks for your help!

Regards,
Eric

Re: xMask - A Masked Edit Gadget

Posted: Fri Apr 01, 2011 4:07 pm
by Peyman
ebs wrote:Peyman,

Can you suggest a code change that would move the caret (text cursor) past any literal characters in the mask?
I would like it to move to the next character input position, because I think that makes it clearer where the next
character entered will go.

For example, using the example in the code, the mask is "999-99-9999".
If I enter "123", the StringGadget looks like this:

Code: Select all

123|-**-****
where "|" represents the caret.

I would like it to move past the "-" and look like this:

Code: Select all

123-|**-****
Thanks for your help!

Regards,
Eric
i add _xm_CheckStatic procedure for do this, check my post i repost the updated code. 8)

Re: xMask - A Masked Edit Gadget

Posted: Fri Apr 01, 2011 4:55 pm
by ebs
Peyman wrote:i add _xm_CheckStatic procedure for do this, check my post i repost the updated code. 8)
Thank you - it works great! :P