- Offizieller Beitrag
Hi,
da ich für meine Oberflächen auf Arbeit viel mit Datumsfeldern arbeite, habe ich mir jetzt mal eigene Datum-Inputs erstellt.
Der Nachteil beim GUICtrlCreateDate ist, dass man bei der Eingabe immer in einer der 3 Gruppen (TT, MM od. JJJJ) hängt und nicht fortlaufend schreiben kann.
Da ich den Date-Picker sowieso nie benutze, ist mir ein vorformatiertes Input lieber. Die Eingaben werden während des Schreibens auf Richtigkeit geprüft. Bei Eingabe eines falschen Wertes wird die Anzeige auf den Stand vor der Eingabe zurückgesetzt. Rein optisch bleibt der Cursor stehen. Beim Verlassen des Inputs wird nochmals validiert (falls unvollständige Eingabe). Liegt ein Fehler vor, bleibt der Fokus auf dem Input. Man kann das Input nur bei korrektem oder wieder gelöschtem Datum verlassen.
Überprüft wird der Datumszeitraum von 01.01.1900 bis 31.12.2999 (Da das Pattern bis 2099 unwesentlich kürzer als bis 2999 ist, habe ich den gesamten Zeitraum verwendet.). Löschen ist nicht mit Backspace möglich, sondern über: Markieren - Entfernen.
Zur Verwendung:
Die Inputs, wie im Bsp. erstellen und deren ID's im $arDateInput der Funktion MY_WM_COMMAND() hinterlegen.
Geschrieben werden kann nur, wenn ein Bereich markiert ist (also überschreibbar). Das ist gewollt, da immer der noch nicht geschriebene Teil des Datums markiert wird. Deshalb am Besten per TAB zu den Inputs bewegen, dann ist sofort alles markiert.
Edit: Oops, da hatte ich einen Fehler in die Validierungsfunktion reinkopiert... Ist nun behoben.
Spoiler anzeigen
#include <Editconstants.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
Global $GUI, $Input1, $Input2, $Input3, $Input4
$GUI = GUICreate('TEST')
$Input1 = GUICtrlCreateInput("__.__.____", 20, 50, 62, 21, $ES_NUMBER)
$Input2 = GUICtrlCreateInput("__.__.____", 20, 80, 62, 21, $ES_NUMBER)
$Input3 = GUICtrlCreateInput("__.__.____", 20, 110, 62, 21, $ES_NUMBER)
$Input4 = GUICtrlCreateInput("__.__.____", 20, 140, 62, 21, $ES_NUMBER)
GUISetState()
GUIRegisterMsg($WM_COMMAND, 'MY_WM_COMMAND')
While 1
$msg = GUIGetMsg()
Switch $msg
Case $GUI_EVENT_CLOSE
Exit
Case Else
; ...
EndSwitch
WEnd
Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
Local $nNotifyCode = BitShift($wParam, 16)
Local $hCtrl = $lParam
Local $arDateInput[4] = [$Input1,$Input2,$Input3,$Input4] ; Array mit den ID der zu prüfenden Inputs
If $nNotifyCode = 1024 Then
For $i = 0 To UBound($arDateInput) -1
If $hCtrl = GUICtrlGetHandle($arDateInput[$i]) Then
_CheckDateInput($hWnd, $arDateInput[$i])
ExitLoop
EndIf
Next
ElseIf $nNotifyCode = 512 Then
For $i = 0 To UBound($arDateInput) -1
If $hCtrl = GUICtrlGetHandle($arDateInput[$i]) Then
_CheckByFocusLost($hWnd, $arDateInput[$i])
ExitLoop
EndIf
Next
EndIf
Return $GUI_RUNDEFMSG
EndFunc
Func _CheckDateInput($hWnd, $ID)
Local $current = StringReplace(GUICtrlRead($ID),'.',''), $str = '__.__.____'
Local $num = StringRegExp($current, '\d', 3)
If @error Then Return GUICtrlSetData($ID, $str)
Local $ub = UBound($num)
Local $arPattern[8] = [ _
"[0-3]", "(0[1-9]|[12][0-9]|3[01])", "(0[1-9]|[12][0-9]|3[01])[0-1]", _
"(((0[1-9]|[12][0-9])02)|((0[1-9]|[12][0-9]|30)(0[469]|11))|(0[1-9]|[12][0-9]|3[01])(0[13578]|1[02]))", _
"(((0[1-9]|[12][0-9])02)|((0[1-9]|[12][0-9]|30)(0[469]|11))|(0[1-9]|[12][0-9]|3[01])(0[13578]|1[02]))[12]", _
"(((0[1-9]|[12][0-9])02)|((0[1-9]|[12][0-9]|30)(0[469]|11))|(0[1-9]|[12][0-9]|3[01])(0[13578]|1[02]))[12][09]", _
"(((0[1-9]|[12][0-9])02)|((0[1-9]|[12][0-9]|30)(0[469]|11))|(0[1-9]|[12][0-9]|3[01])(0[13578]|1[02]))[12][09]\d", _
"((((0[1-9]|1[0-9]|2[0-8])02)|((0[1-9]|[12][0-9]|30)(0[469]|11))|(0[1-9]|[12][0-9]|3[01])(0[13578]|1[02]))" & _
"((19|2[0-9])([02468][1235679]|[13579][01345789])|(19|2[1235679])00))|((((0[1-9]|1[0-9]|2[0-9])02)|((0[1-9]|[12][0-9]|30)" & _
"(0[469]|11))|(0[1-9]|[12][0-9]|3[01])(0[13578]|1[02]))((19|2[0-9])(04|08|[2468][048]|[13579][26])|(20|24|28)00))"]
If Not StringRegExp($current, $arPattern[$ub-1]) Then $ub -= 1
Switch $ub
Case 0
GUICtrlSetData($ID, $str)
Case 1
GUICtrlSetData($ID, $num[0] & StringRight($str, 9))
Case 2
GUICtrlSetData($ID, $num[0] & $num[1] & StringRight($str, 8))
Case 3
GUICtrlSetData($ID, $num[0] & $num[1] & '.' & $num[2] & StringRight($str, 6))
$ub += 1
Case 4
GUICtrlSetData($ID, $num[0] & $num[1] & '.' & $num[2] & $num[3] & StringRight($str, 5))
$ub += 1
Case 5 to 8
Local $sYear = ''
For $i = 4 To $ub -1
$sYear &= $num[$i]
Next
GUICtrlSetData($ID, $num[0] & $num[1] & '.' & $num[2] & $num[3] & '.' & $sYear & StringRight($str, 8 -$ub))
$ub += 2
EndSwitch
ControlSend($hWnd, '', $ID, '{END}{SHIFTDOWN}{HOME}{RIGHT ' & $ub & '}{SHIFTUP}')
EndFunc
Func _CheckByFocusLost($hWnd, $ID)
If StringLen(StringReplace(StringReplace(GUICtrlRead($ID),'.',''),'_','')) = 0 Then Return
If Not StringRegExp(StringReplace(StringReplace(GUICtrlRead($ID),'.',''),'_',''), "((((0[1-9]|1[0-9]|2[0-8])02)|((0[1-9]|[12][0-9]|30)(0[469]|11))|(0[1-9]|[12][0-9]|3[01])(0[13578]|1[02]))" & _
"((19|2[0-9])([02468][1235679]|[13579][01345789])|(19|2[1235679])00))|((((0[1-9]|1[0-9]|2[0-9])02)|((0[1-9]|[12][0-9]|30)" & _
"(0[469]|11))|(0[1-9]|[12][0-9]|3[01])(0[13578]|1[02]))((19|2[0-9])(04|08|[2468][048]|[13579][26])|(20|24|28)00))") Then _
ControlFocus($hWnd, '', $ID)
EndFunc