its updated and fixed some thing like work on x64 compiler and remove beep sound.
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