[VB6] Invoer textbox controleren

Pagina: 1
Acties:
  • 744 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

Anoniem: 85525

Topicstarter
Ik ben bezig de invoer in een textbox direct te controleren op numerieke waarde, dus als een toets wordt gedrukt, wordt deze al dan niet toegestaan, afhankelijk van de ingedrukte toets en positie van de cursor. Zo kan een punt niet in het begin staan en kan er maar een punt voorkomen, etc.

Als ik controleer op invoer van een punt, dan zie ik dat de KeyAscii code hierbij 46 is, wat dezefde code is als vbKeyDelete. chr(KeyAscii) werkt dan andersom niet; er wordt een punt van een delete gemaakt. Een minteken wordt verward met insert.

Weet iemand hoe dit komt en anders hoe de invoer beter gecontroleerd kan worden? Ajb geen masked control maar gewoon een textbox.

Acties:
  • 0 Henk 'm!

  • GigaDave56
  • Registratie: Juni 2001
  • Laatst online: 12:05
Je kan het gewoon de KeyAscii waarde vergelijken (in de gebeurtenis '_keypress'). Hieronder een voorbeeld waarin alleen cijfers ingevoerd kunnen worden.


QBasic:
1
2
3
4
5
6
7
8
    'Check for valid input keys
    If KeyAscii <> 8 Then
        If KeyAscii <> 44 And KeyAscii <> 46 Then
            If KeyAscii < 48 Or KeyAscii > 57 Then
                KeyAscii = 0
            End If
        End If
    End If

Zie in regel 3 de afvanging van de punt en komma (44 en 46) :)
Succes

[ Voor 21% gewijzigd door GigaDave56 op 22-03-2004 14:46 . Reden: spelfauts ]

Not so Giga One
> I'd sell my soul for you, babe
> For money to burn, for you
> I'd give you all and have none, babe
> Just to, just to, to have you here by me... [Scooter - Rebel yell]


Acties:
  • 0 Henk 'm!

  • Tukk
  • Registratie: Januari 2002
  • Laatst online: 21-06 13:46

Tukk

De α-man met het ẞ-brein

Wat ook kan is een functie zoals onderstaande gebruiken na elke toetsaanslag.

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function isNumber(asVal) as boolean

  isNumber = true

 on Error goto lError:

   debug.print Cdec(asVal)

   end function

 lErrorHandler:
   if err.number = 13 then
      isNumber = false
   else 
      ' andere foutmelding genereren.
   end if 

end function

[ Voor 11% gewijzigd door Tukk op 22-03-2004 14:56 ]

Q: How many geeks does it take to ruin a joke? A: You mean nerd, not geek. And not joke, but riddle. Proceed.


Acties:
  • 0 Henk 'm!

Anoniem: 106551

Tukk schreef op 22 maart 2004 @ 14:49:
Wat ook kan is een functie zoals onderstaande gebruiken na elke toetsaanslag.

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function isNumber(asVal) as boolean

  isNumber = true

 on Error goto lError:

   debug.print Cdec(asVal)

   end function

 lErrorHandler:
   if err.number = 13 then
      isNumber = false
   else 
      ' andere foutmelding genereren.
   end if 

end function
vb heeft zelf al de functie IsNumeric.....is dat niet handiger ?

Acties:
  • 0 Henk 'm!

  • Tukk
  • Registratie: Januari 2002
  • Laatst online: 21-06 13:46

Tukk

De α-man met het ẞ-brein

Anoniem: 106551 schreef op 22 maart 2004 @ 15:24:
[...]

vb heeft zelf al de functie IsNumeric.....is dat niet handiger ?
euh, |:(

Syntaxis, ik zocht hem bij IsNumber of IsNan, toen die niet bleek te bestaan dacht ik snel dat het niet bestond.

@ playroll: gebruik IsNumeric op de OnChange en zet de oude waarde terug indien IsNumeric een false geeft.

Q: How many geeks does it take to ruin a joke? A: You mean nerd, not geek. And not joke, but riddle. Proceed.


Acties:
  • 0 Henk 'm!

Anoniem: 85525

Topicstarter
Het controleren op een numerieke waarde lukt wel, maar ik zit met de invoer van max. een punt en een minteken. KeyAscii=46 is een punt. Maar vbKeyDelete heeft waarde 0x2D, wat 46 is. Er is dan dus geen mogelijkheid om een onderscheid te maken tussen punt en de delete toets was mijn probleem.

Ik controleer nu op chr(KeyAscii) = ".", wat wel goed gaat in tegenstelling tot wat ik in de OT postte, dus ik gebruik deze voortaan wel. De delete en backspace wordt standaard al verzorgd dus hoeft niets voor geschreven te worden.

Acties:
  • 0 Henk 'm!

Anoniem: 106551

Is het misschien niet handiger om de controle pas te doen bij het verlaten van het veld ( Onlostfocus ) ?

Dan hoef je alleen maar een isnumeric te gebruiken. Wil je alles namelijk afvangen in de OnChange, dan moet je met zoveel situaties rekening houden ( alleen cijfers, punten en mintekens, maximaal 1 punt, maximaal 1 minteken EN die moet vooraan staan etc. )

De mooiste oplossing is natuurlijk een gespecialiseerd component orvoor op de kop tikken, maar ik weet niet of die gratis te vinden zijn.

[edit] typo

Acties:
  • 0 Henk 'm!

Anoniem: 30225

Anoniem: 106551 schreef op 22 maart 2004 @ 15:24:
[...]

vb heeft zelf al de functie IsNumeric.....is dat niet handiger ?
Nee, doe maar eens testen met verschillende waarden

IsNumeric("")
IsNumeric("a")
IsNumeric("0")
IsNumeric("0a")
IsNumeric("0,0")
IsNumeric("0,1")
IsNumeric("6,7")
IsNumeric("0.1")
IsNumeric("3.78")
IsNumeric(".9")
IsNumeric("8.5")
IsNumeric("6.7e")
IsNumeric("-65")
IsNumeric("787868767656475436548967")

[ Voor 21% gewijzigd door Anoniem: 30225 op 23-03-2004 00:50 ]


Acties:
  • 0 Henk 'm!

  • Flard
  • Registratie: Februari 2001
  • Laatst online: 18-06 14:58
Ik heb toevallig laatst iemand proberen te helpen met hetzelfde probleem, alleen toen in Pascal voor DOS.

Wat bleek: Als men daar op een 'speciale toets' drukte (dus Delete, Insert, ...) dan werd er eerst een 0 gestuurd, en daarna het betreffende nummer.
Ik weet niet of het ook zo bij VB is, maar mocht het daar zo zijn dan wordt er dus bij een punt maar één keer de OnKey Event aangeroepen: met KeyAscii = 46.
Druk je op Delete zou je dus twee keer die Event krijgen, met eerst een keer KeyAscii = 0 en daarna KeyAscii = 46.

Maar goed, ik weet niet zeker of het zo ook in VB is.

Verder kun je natuurlijk ook altijd met een OnChange Event werken, en dan de tekst bijvoorbeeld rood kleuren (ForeColor = vbRed) als hij niet numeriek is, en anders zwart, en OnLostFocus dan eventueel nog een MsgBox met een waarschuwing bij foute invoer.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Anoniem: 106551 schreef op 23 maart 2004 @ 00:13:
Is het misschien niet handiger om de controle pas te doen bij het verlaten van het veld ( Onlostfocus ) ?

Dan hoef je alleen maar een isnumeric te gebruiken. Wil je alles namelijk afvangen in de OnChange, dan moet je met zoveel situaties rekening houden ( alleen cijfers, punten en mintekens, maximaal 1 punt, maximaal 1 minteken EN die moet vooraan staan etc. )

De mooiste oplossing is natuurlijk een gespecialiseerd component orvoor op de kop tikken, maar ik weet niet of die gratis te vinden zijn.

[edit] typo
Onder VB6 is het _Validate event daarvoor bedoeld.
Wat ik meestal gebruik is het volgende:

code:
1
2
3
4
5
6
7
8
9
10
11
Private Sub Text1_Validate(Cancel As Boolean)
    Text1.Text = ParseLong(Text1.Text, 0)
End Sub

Private Function ParseLong(vVal As String, Optional lDef As Long = 0) As Long
    On Error GoTo errParse
    ParseLong = CLng(vVal)
    Exit Function
errParse:
    ParseLong = lDef
End Function


Dit gebruik ik in het geval ik een Long wil hebben (en als het fout gaat een optionele "default" waarde). Natuurlijk kun je ParseLong redelijk makkelijk omschrijven naar een currency bijvoorbeeld:

code:
1
2
3
4
5
6
7
Private Function ParseCur(vVal As String, Optional cDef As Long = 0) As Currency
    On Error GoTo errParse
    ParseCur = CCur(vVal)
    Exit Function
errParse:
    ParseCur = cDef
End Function


Andere functies mag je zelf maken, die zijn niet zo moeilijk.

Denk er wel aan dat als je bijvoorbeeld een default button hebt, dat je in het _click event effe me.validatecontrols aanroept om alle velden te valideren (anders komt het wel eens voor dat het validate event te laat wordt aangeroepen).

Tot slot nog een tipje: Als je in het validate event Cancel op True zet op het moment dat er ongeldige data wordt aangetroffen blijft de focus op de betreffende textbox. Dit geldt natuurlijk voor een boel andere controls die een _validate event hebben ook.

Mijn uitgangspunt is dan ook meestal: Laat de gebruiker invoeren wat 'ie wil (met misschien alleen een .maxlength) en controleer pas NA de invoer of dit correct is. Er is niet zo irritant als dingen proberen te typen welke niet op je scherm (willen) verschijnen. Dat het "ongeldige" tekens zijn blijkt naderhand ook wel (en het programma laat tevens ook nog enige vorm van "intelligentie" zien door correcties uit te voeren waar mogelijk).

...En nog iets: Als je met currencies e.d. gaat werken, denk dan even aan LOCALES. In Nederland scheiden we decimalen met een komma en duizendtallen met een punt. Hoewel dit soms verwarrend is als je op een numeriek toetsenbord bezig bent, dien je dit correct af te handelen. Een mooi voorbeeldje is Excel, welke punten van het numerieke gedeelte automatisch (en dan dus wel tijdens het typen...) vervangt. Denk eraan dat als je je applicatie Internationale-aware wil maken dat je dit soort geintjes goed afvangt. In de VS gebruiken ze namelijk weer wél een punt als decimaal scheidingsteken en een komma om de duizendtallen te scheiden. Ook dd-mm-jjjj or mm/dd/yyyy geintjes vallen daar onder. Mijn advies: Gebruik de CCur, CLng, CDate, CInt enzovoorts en ga niet prutsen met Val, Instr$, Mid$ en andere flauwekul. Laat het afhandelen door VB zelf.

Wil je toch invoer blocken, probeer dan dit eens, lekker kort en krachtig:
code:
1
2
3
Private Sub Text1_KeyPress(KeyAscii As Integer)
    KeyAscii = IIf(InStr("0123456789", Chr(KeyAscii)), KeyAscii, 0)
End Sub


En met een kleine uitbreiding heb je dit zo aangepast dat 'ie ook decimalen vreet e.d.:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Private Sub Text1_KeyPress(KeyAscii As Integer)
    KeyAscii = ValidKey(KeyAscii)
End Sub

Private Sub Text2_KeyPress(KeyAscii As Integer)
    KeyAscii = ValidKey(KeyAscii, "abc")
End Sub

Private Sub Text3_KeyPress(KeyAscii As Integer)
    KeyAscii = ValidKey(KeyAscii, "1234567890.-")
End Sub

Private Function ValidKey(KeyAscii As Integer, _
                Optional strValidChars As String = "0123456789") As Integer
    ValidKey = IIf(InStr(strValidChars, Chr(KeyAscii)), KeyAscii, 0)
End Function


In dit voorbeeld kun je in text1 alleen 0 t/m 9 invoeren, in text2 alleen de letters a,b en c en in text 3 alle cijfers en een punt en een minus (denk aan negatieve getallen!)

Sim-pel ;)

edit:

En om nog even terug te komen op FFrenzy: Hier ga je dus geen component voor downloaden he? Dit is makkelijk zelf te maken, waarom dan afhankelijk zijn van derden (met alle mogelijke bugs e.d. -die je dus niet zelf kunt fixen- van dien). Als het nou een complete grid was, of een mailcomponent, dan is het iets anders (hoewel ook een mailcomponent weinig moeite is), maar voor zo iets simpels ga ik geen OCX gebruiken (en distribueeren!)

[ Voor 30% gewijzigd door RobIII op 23-03-2004 01:35 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1