Link to home
Start Free TrialLog in
Avatar of rharissa
rharissaFlag for Canada

asked on

Mask Editor

I'm using the mask editor to mask a input of a real or a double datatype. Some times I need that the user enter a number consisting of 5 max digits numbers and two decimals, so I assigned a mask to my control like that "99999.99", So If the user has to enter a number like 2.89 he has to enter "space space space space 2 8 9" and he gets the good result. Unfortunately that way is not comfortable. My question is:
Is there another way to make a mask, so the user can enter directly 2.89 instead of "space space space space 2 8 9" or instead of "0000289".
Thanks for helping
Robert
Avatar of KDivad
KDivad

Never used the masked edit control, but if it works like the format command, I think you can use "@@@@@.@@" instead of "99999.99". With the format command, "9" means a number, while "@" means a number or nothing.
Oops. Had it wrong. "@" is for letters (letters or nothing). "#" is for numbers.

Later,
Use textbox.
Avatar of hes
As KDivad, and ameba suggested, use a text box instead of the mask edit. On leaving the textbox use the isnumeric command to verify number, then the format command to format the entered data and re-display it in the text box.
use "00000.00"  very simple, not really worth 100 points
Hi Robert.

Create a new project.

To this project add a class (that you will name clsNumeric) and copy this code to it:

Option Explicit

Public WithEvents gctlTextBox As TextBox

Private mblnNegatif As Boolean
Private mbytNumericLongueur As Byte
Private mbytNumericDecimal As Byte

'Convertit en majuscule au besoin
Private Sub gctlTextBox_KeyPress(KeyAscii As Integer)
    Call ValiderChampNombre(KeyAscii)
End Sub

'S'assure que le format est respecté
Private Sub gctlTextBox_Validate(Cancel As Boolean)
Dim blnNegatif As Boolean
Dim intPosSepDec As Integer

    '===============================================================
    'Recherche la position du séparateur de décimales
    '===============================================================
    intPosSepDec = InStr(gctlTextBox.Text, ".")

    '===============================================================
    'Détecte le symbole négatif
    '===============================================================
    blnNegatif = InStr(gctlTextBox.Text, "-")

    'Si pas de séparateur de décimales
    If intPosSepDec = 0 Then
        If Len(gctlTextBox.Text) - IIf(blnNegatif, 1, 0) > mbytNumericLongueur Then GoTo Invalide
    'Si séparateur de décimales
    Else
        If Len(gctlTextBox.Text) - intPosSepDec > mbytNumericDecimal Then GoTo Invalide
        If Len(gctlTextBox.Text) - Len(Mid$(gctlTextBox.Text, intPosSepDec)) - IIf(blnNegatif, 1, 0) > mbytNumericLongueur Then GoTo Invalide
    End If

    Exit Sub

Invalide:
    Cancel = True
    Beep
End Sub

'Initialise la longueur d'un champ numérique
Public Sub InitChampNombre(ByVal pbytLong As Byte, _
                           ByVal pbytDec As Byte, _
                           Optional ByVal pblnNegatif As Boolean = False)
    mbytNumericLongueur = pbytLong
    mbytNumericDecimal = pbytDec
    mblnNegatif = pblnNegatif
End Sub

Private Sub ValiderChampNombre(ByRef KeyAscii As Integer)
Dim blnNegatif As Boolean
Dim intPosSepDec As Integer

    '===============================================================
    'Si BackSpace = OK
    '===============================================================
    If KeyAscii = 8 Then Exit Sub

    '===============================================================
    'Valide si le caractère est légal (séparateur de décimales, -, 0 à 9)
    '===============================================================
    If Not (Chr$(KeyAscii) = "." Or _
       Chr$(KeyAscii) = "-" Or _
       IsNumeric(Chr$(KeyAscii)) Or _
       KeyAscii = 0) _
    Then GoTo Invalide
   
    '===============================================================
    'Si c'est le signe négatif
    '===============================================================
    If Chr$(KeyAscii) = "-" Then
        'Si ce n'est pas permis
        If Not mblnNegatif Then GoTo Invalide
       
        'Si ce n'est pas au début
        If gctlTextBox.SelStart > 0 Then GoTo Invalide
        'If Len(gctlTextBox.Text) <> 0 Then GoTo Invalide
    End If
   
    '===============================================================
    'Recherche la position du séparateur de décimales
    '===============================================================
    intPosSepDec = InStr(gctlTextBox.Text, ".")
   
    '===============================================================
    'Détecte le symbole négatif
    '===============================================================
    blnNegatif = InStr(gctlTextBox.Text, "-")
   
    '===============================================================
    'Si séparateur de décimales
    '===============================================================
    If Chr$(KeyAscii) = "." Then
        'Si ce n'est pas permis
        If mbytNumericDecimal = 0 Then GoTo Invalide
   
        'Si il y a déjà un séparateur de décimales
        If intPosSepDec <> 0 Then GoTo Invalide
       
        'Ne pas dépasser le nombre de décimales
        If Len(gctlTextBox.Text) - gctlTextBox.SelStart > mbytNumericDecimal Then GoTo Invalide
   
        'Ne pas dépasser le nombre d'entiers
        If gctlTextBox.SelStart - IIf(blnNegatif, 1, 0) > mbytNumericLongueur Then GoTo Invalide
    End If

    '===============================================================
    ' Le reste
    '===============================================================
    'Si pas de séparateur de décimales
    If intPosSepDec = 0 Then
        If Len(gctlTextBox.Text) - gctlTextBox.SelLength - IIf(blnNegatif, 1, 0) >= mbytNumericLongueur Then
            If Not (Chr$(KeyAscii) = "." Or Chr$(KeyAscii) = "-") Then GoTo Invalide
        End If
    'Si séparateur de décimales
    Else
        If intPosSepDec > 0 And gctlTextBox.SelStart >= intPosSepDec Then
            If Len(gctlTextBox.Text) - intPosSepDec >= mbytNumericDecimal Then GoTo Invalide
        Else
            If Len(gctlTextBox.Text) - Len(Mid$(gctlTextBox.Text, intPosSepDec)) - IIf(blnNegatif, 1, 0) >= mbytNumericLongueur Then
                If Not (Chr$(KeyAscii) = ".") Then GoTo Invalide
            End If
        End If
    End If
   
    Exit Sub
   
Invalide:
    KeyAscii = 0
    Beep
End Sub


Then, on the form, place a textbox (without changing any properties) and copy this code:

Option Explicit

Private MyNumericTextBox As clsNumeric

Private Sub Form_Load()
    Text1.Text = ""
    Set MyNumericTextBox = New clsNumeric
    With MyNumericTextBox
        Set .gctlTextBox = Text1
        .InitChampNombre 5, 2
    End With
End Sub
emoreau, yes, thats the best way. I also use this 'control wrappers' cwNumeric, cwSimpleText, cwMemo ...
I would not consider using over 100 lines of code "the best way", when you can accomplish the same result with one.  There is nothing wrong with using the masked edit box, if you know how to use it.
BeedleGuis,

Where do you put that "00000.00"? In the Mask property? In the Format property? I tried them to no good results! Maybe did you forgot another property! I would really like to know to replace my 100 lines!
>I would not consider using over 100 lines of code "the best way"
Put the class in the ActiveX DLL and you won't see that code.
You'll only see few lines in Form code.
MaskEdBox1.Format = "00000.00"

What results did you get?
enter 123 in the MaskEdBox and it formats it to 00123.00 not 00001.23
Avatar of rharissa

ASKER

Hi Everybody,
Thank you for all your comments regarding my question. Yesterday I wanted to conceal the question since I found the good answer somewhere in a article speaking about this problem.
Now I found that Emorneau worked hard, and for that work he deserve the 100 points, but if you want I can share with you the answer that I got. It's very simple and some line could resolve the problem. Then if you want, let me know.
>I found the good answer somewhere in a article speaking about this problem.

What did you found? It can be great for us too!
Here is My Answer:

HOWTO: Use the MaskedEdit Control for Currency Format

--------------------------------------------------------------------------------
The information in this article applies to:

Microsoft Visual Basic Professional Edition for Windows, version 3.0

--------------------------------------------------------------------------------


SUMMARY
The maskededit control requires that you enter a number for each of the pound sign (#) character place holders and enter a space for each of the ampersand (&) place holders. The control tests each character you enter to make sure it matches the specified mask. This is inconvenient for currency format. For example, if the mask is #####.##, you'd have to enter 00012.25; and if the Mask is &&&&#.##, you'd have to enter four spaces and then 12.25 (as in " 12.25").

This article shows by example how to gain the flexibility of entering any number. The application uses the period (.) to define the decimal point, and right aligns the number to the decimal point. Then you can enter the pennies.



MORE INFORMATION

Step-by-Step Example
Start a new project in Visual Basic (ALT, F, N). Form1 is created by default.


Add two Masked Edit controls (MaskedEdit1 and MaskedEdit2) to Form1, and assign these properties:


   Default Name    Mask       Format      PromptChar
   -------------------------------------------------
   MaskedEdit1     #####.##   $####0.00   (Space)
   MaskedEdit2     #####.##   $####0.00   (Space)
 
Add the following code to the GotFocus event of MaskedEdit1:


   Sub MaskedEdit1_GotFocus ()
      maskededit1.SelStart = 0
      maskededit1.SelLength = Len(maskededit1)
   End Sub
Add the following code to the KeyPress event of MaskedEdit1:


   Sub MaskedEdit1_KeyPress (keyascii As Integer)
      Call Masked_Key_Press(MaskedEdit1, keyascii)
      If keyascii = 13 Then SendKeys "{tab}"
   End Sub
Add the following code to the GotFocus event of MaskedEdit2:


   Sub MaskedEdit2_GotFocus ()
      maskededit2.SelStart = 0
      maskededit2.SelLength = Len(MaskedEdit2)
   End Sub
Add the following code to the Keypress event of MaskedEdit2:


   Sub MaskedEdit2_KeyPress (keyascii As Integer)
      Call Masked_Key_Press(MaskedEdit2, keyascii)
      If keyascii = 13 Then SendKeys "{tab}"
   End Sub
Add the following Sub procedure to the general declarations section of the form:


   Sub Masked_Key_Press (MskEdit As MaskEdBox, keyascii As Integer)

      ' Calculate the location of the decimal point in the mask:
      mask_cents_pos = InStr(MskEdit.Mask, ".")
      mask_dollars = mask_cents_pos - 1

      ' Check for period keypress:
      If keyascii = 46 And MskEdit.SelStart < 6 Then
         tlen = MskEdit.SelStart + 1       ' Store current location.
         MskEdit.SelStart = 0
         MskEdit.SelLength = tlen          ' Highlight up to the current
         tempo = MskEdit.SelText           ' position & save selected text.
         MskEdit.SelLength = mask_dollars
         MskEdit.SelText = ""              ' Clear to the left of decimal.
         MskEdit.SelStart = mask_cents_pos - tlen
         MskEdit.SelLength = tlen           ' Reposition caret
         MskEdit.SelText = tempo            ' and paste copied data.
         MskEdit.SelStart = mask_cents_pos  ' Position caret after cents.
      End If
   End Sub
Press the F5 key to run the program. Enter numbers, and observe the result when you press the period (decimal point) key.

This code shows a single method for handling various numeric input into the masked edit box. You may want to use this as a starting point and add additional code for special cases.

Additional query words:

Keywords : kbVBp kbVBp300 kbDSupport
Version : WINDOWS:3.0
Platform : WINDOWS
Issue type : kbhowto
 


Last Reviewed: July 20, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.
 

 

Article ID: Q126676

Last Reviewed:
July 20, 1999

Provided by Microsoft Product Support Services.

I'm happy to see that it is another 100 lines solution!
if you include the Sub Masked_Key_Press to your code it will be enough to make your control work. it's scarcely 10 lignes.
Is it me or when I try the code that Robert pasted here rings bell sound each time the dot is pressed?

And what do you use as mask if you want to allow negative numbers?

I really think that I will stay with my class. Think of it, a class can offer other features (such as a minimum and a maximum value).

>>Is it me or when I try the code that Robert pasted here rings bell sound each time the dot is pressed?<<

In the "If KeyAscii = 46 ..." block add a line that reads "KeyAscii = 0".
ASKER CERTIFIED SOLUTION
Avatar of Éric Moreau
Éric Moreau
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial