Jump to content

Increase the hour range in Date/DTP control


Recommended Posts

Can I increase the hour limit in my Date control?

I have tried this:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiDateTimePicker.au3>
$Form1 = GUICreate("Form1", 400, 200)
Global $TheTime = GUICtrlCreateDate('02:00', 5, 5, 150, 21, $DTS_TIMEFORMAT)
_GUICtrlDTP_SetFormat(GUICtrlGetHandle($TheTime), "HH:mm '    Hour:minute'")
Global $aRange[14] = [True, 0, 1, 1, 00, 00, 00, True, 3000, 12, 31, 99, 99, 99]
_GUICtrlDTP_SetRange(GUICtrlGetHandle($TheTime), $aRange)
GUISetState(@SW_SHOW)
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

But it still goes only to 23/59 when I try to change hours/minutes, and I would like to change to 99:99 (max value)

Link to comment
Share on other sites

  • Moderators

dragan,

I think you are going to have to create a custom "control" with labels, inputs and updowns for that. It is not too difficult - I have done it several times and I will try to find an example later. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Hi Melba23,

I tried to make custom control, and this is closest to my idea. However, at the moment I'm limited by my autoit skills:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <Constants.au3>
#include <GuiEdit.au3>

Global $edittingNumber = 1

$Form1 = GUICreate("Form1", 400, 200)
$hEdit = GUICtrlCreateInput('02.00', 5, 5, 150, 21, $ES_NUMBER);, 0, 0)
GUICtrlSetLimit(-1, 5)
$hUpDown = GUICtrlCreateUpdown(-1)
$wProcHandle = DllCallbackRegister("_EditWindowProc", "ptr", "hwnd;uint;wparam;lparam")
$wProcOldLocal = _WinAPI_SetWindowLong(GUICtrlGetHandle($hEdit), $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle))
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
_WinAPI_SetWindowLong(GUICtrlGetHandle($hEdit), $GWL_WNDPROC, $wProcOldLocal)
DllCallbackFree($wProcHandle)

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch BitAND($wParam, 0xFFFF)
        Case $hEdit
            ConsoleWrite('- ' & $iCode & @CRLF)
            Return True
        Case $hUpDown
            ConsoleWrite('! ' & $iCode & @CRLF)
            Local $tStruct = DllStructCreate("hwnd;long;int;long;long", $lParam)
            If DllStructGetData($tStruct, 3) = 0xFFFFFD2E Then ; $UDN_DELTAPOS
                Local $divider = 1
                If $edittingNumber = 1 Then
                    $divider = 1
                Else
                    $divider = 100
                EndIf
                Local $calc = DllStructGetData($tStruct, 5)/$divider
                Local $readVal = Number(GUICtrlRead($hEdit))
                Local $newVal = $readVal + $calc
                If $newVal >= 100 then
                    $newVal = 0
                ElseIf $newVal < 0 then
                    $newVal = 99.99
                EndIf
                Local $theVal = StringFormat("%#.2f", $newVal)
                Local $splitVal = StringSplit($theVal, '.')
                Local $firstVal = StringFormat("%02d", $newVal)
                Local $finalVal = $firstVal & '.' & $splitVal[$splitVal[0]]
                Local $theDot = StringInStr($finalVal, '.')
                Local $iCount = StringLen($finalVal)
                GUICtrlSetData($hEdit, $finalVal)
                Return True
            EndIf
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _EditWindowProc($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Switch $hWnd
        case GUICtrlGetHandle($hEdit)
            Switch $iMsg
                Case $WM_GETDLGCODE
                    ConsoleWrite('-> ' & $wParam & @CRLF)
                    Local $curRead = GUICtrlRead($hEdit)
                    Local $iCount = StringLen($curRead)
                    Local $theDot = StringInStr($curRead, '.')
                    Switch $wParam
                        Case 110, 190 ;dot (.)
                            If NOT $theDot Then
                                If $curRead = '' Then
                                    GUICtrlSetData($hEdit, '00.')
                                Else
                                    GUICtrlSetData($hEdit,  StringFormat("%02d", $curRead) & '.')
                                EndIf
                            Else
                                _GUICtrlEdit_SetSel($hEdit, $theDot, $iCount)
                            EndIf
                            $edittingNumber = 2
                            Return True
                        Case 38 ;up
                            Local $splitVal = StringSplit($curRead, '.')
                            If $splitVal[0] < 2 then Return _WinAPI_CallWindowProc($wProcOldLocal, $hWnd, $iMsg, $wParam, $lParam)
                            Local $finalVal
                            If $edittingNumber = 1 Then
                                Local $newVal = $splitVal[1]+1
                                If $newVal >= 100 then $newVal = 0
                                $finalVal = StringFormat("%02d", $newVal) & '.' & StringFormat("%02d", $splitVal[2])
                            Else
                                Local $newVal = $splitVal[2]+1
                                If $newVal >= 100 then
                                    $newVal = 0
                                    $splitVal[1] += 1
                                    If $splitVal[1] >= 100 then $splitVal[1] = 0
                                EndIf
                                $finalVal = StringFormat("%02d", $splitVal[1]) & '.' & StringFormat("%02d", $newVal)
                            EndIf
                            GUICtrlSetData($hEdit, $finalVal)
                            Return True
                        Case 40 ;down
                            Local $splitVal = StringSplit($curRead, '.')
                            If $splitVal[0] < 2 then Return _WinAPI_CallWindowProc($wProcOldLocal, $hWnd, $iMsg, $wParam, $lParam)
                            Local $finalVal
                            If $edittingNumber = 1 Then
                                Local $newVal = $splitVal[1]-1
                                If $newVal < 0 then $newVal = 99
                                $finalVal = StringFormat("%02d", $newVal) & '.' & StringFormat("%02d", $splitVal[2])
                            Else
                                Local $newVal = $splitVal[2]-1
                                If $newVal < 0 then
                                    $newVal = 99
                                    $splitVal[1] -= 1
                                    If $splitVal[1] < 0 then $splitVal[1] = 99
                                EndIf
                                $finalVal = StringFormat("%02d", $splitVal[1]) & '.' & StringFormat("%02d", $newVal)
                            EndIf
                            GUICtrlSetData($hEdit, $finalVal)
                            Return True
                        Case 37 ;left
                            If $edittingNumber = 2 Then
                                $edittingNumber = 1
                                _GUICtrlEdit_SetSel($hEdit, 0, $theDot) ;<------- doesn't work
                                ConsoleWrite('>> ' & $edittingNumber & @CRLF)
                                Return True
                            EndIf
                        Case 39 ;right
                            If $edittingNumber = 1 Then
                                $edittingNumber = 2
                                _GUICtrlEdit_SetSel($hEdit, $theDot, $iCount+1) ;<------- doesn't work
                                ConsoleWrite('>> ' & $edittingNumber & @CRLF)
                                Return True
                            EndIf
                        Case 48 to 57
                            If $iCount >= 2 then
                                If NOT $theDot Then
                                    GUICtrlSetData($hEdit, $curRead & '.')
                                    _WinAPI_CallWindowProc($wProcOldLocal, $hWnd, $iMsg, $wParam, $lParam)
                                EndIf
                            EndIf
                    EndSwitch
                Case 513
                    ConsoleWrite('~~> ' & $edittingNumber & @CRLF)
                    Local $curRead = GUICtrlRead($hEdit)
                    Local $iCount = StringLen($curRead)
                    Local $theDot = StringInStr($curRead, '.')
                    If NOT $theDot Then
                    Else
                        _WinAPI_CallWindowProc($wProcOldLocal, $hWnd, $iMsg, $wParam, $lParam)
                        Local $iPos = _GUICtrlEdit_GetSel($hEdit)
                        If IsArray($iPos) Then
                            ConsoleWrite('+> ' & $iPos[0] & ', ' & $iPos[1] & ', ' & $theDot &  @CRLF)
                            If $iPos[0] < $theDot Then
                                $edittingNumber = 1
                                _GUICtrlEdit_SetSel($hEdit, 0, $theDot-1)
                            Else
                                $edittingNumber = 2
                                _GUICtrlEdit_SetSel($hEdit, $theDot, $iCount+1)
                            EndIf
                            ConsoleWrite('!> ' & $edittingNumber & @CRLF)
                            Return True
                        EndIf
                    EndIf
                Case $WM_GETDLGCODE
            EndSwitch
    EndSwitch
    Return _WinAPI_CallWindowProc($wProcOldLocal, $hWnd, $iMsg, $wParam, $lParam)
EndFunc

I do have some questions though, why is my script failing at the left/right keyboard clicks in the _EditWindowProc function? It's not failing, but it fails to select things I want it to select. Also, can I make Up/Down control to NOT select entire input after changing value, but select only left/right parts of the input.

Link to comment
Share on other sites

  • Moderators

dragan,

Sorry, I was dragged away to do something else and I forgot to look out my example code. It is a good bit simpler than yours: ;)

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <UpDownConstants.au3>
#include <StaticConstants.au3>
#include <EditConstants.au3>

$hGUI = GUICreate("Test", 500, 500)

; Create hours input
$cInput_Hour = GUICtrlCreateInput("0", 10, 50, 20, 20)
GUICtrlSetState(-1, $GUI_HIDE)
Local $cUpDown_Hour = GUICtrlCreateUpdown($cInput_Hour, $UDS_WRAP)
GUICtrlSetLimit($cUpDown_Hour, 99, 0)
$cInput_Min = GUICtrlCreateInput("0", 80, 50, 20, 20)
GUICtrlSetState(-1, $GUI_HIDE)
Local $cUpDown_Min = GUICtrlCreateUpdown($cInput_Min, $UDS_WRAP)
GUICtrlSetLimit($cUpDown_Min, 59, 0)
$cTimer_Label = GUICtrlCreateLabel("00:00", 30, 50, 50, 20, $SS_CENTER)
GUICtrlSetFont(-1, 12)

GUISetState()

GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

Func _WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam

    ; If it was an update message from the inputs
    If BitShift($wParam, 16) = $EN_CHANGE Then
        Switch BitAND($wParam, 0xFFFF)
            Case $cInput_Hour, $cInput_Min
                ; Set the label to the new total
                GUICtrlSetData($cTimer_Label, StringFormat("%02i", GUICtrlRead($cInput_Hour)) & ":" & StringFormat("%02i", GUICtrlRead($cInput_Min)))
        EndSwitch
    EndIf

EndFunc   ;==>_WM_COMMAND

Is that the sort of thing you were looking for? :huh:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Thanks Melba23, but I would like user to be able to type numbers manually as well, like he can with Data Control. And also to be able to use up/down/left/right buttons on keyboard to change values. I want pretty much ALL that Data Control can, but without the limit of 60 minutes and 24 hours. I realize I can just change your labels into Edits, but in my control, you can type a number, like 12 for example, and soon as you start typing next number (55 for example), the script will insert dot automatically. Though user can type dot if he pleases instead of the script doing that for him. Also the up/down control will increase/decrease number where you last clicked (whether it is left side, or the right side).

I do appreciate for the example script, but I am gonna stick with this custom edit control until I find something more useful. Thanks :)

Edited by dragan
Link to comment
Share on other sites

  • Moderators

dragan,

Fussy! :D

How does this do? :huh:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <UpDownConstants.au3>
#include <StaticConstants.au3>
#include <GUIEdit.au3>
#include <WinAPI.au3>

Global $sFocus

$hGUI = GUICreate("Test", 500, 500)

; Create hours input
$cInput_Hour = GUICtrlCreateInput("00", 10, 50, 40, 20)
$cUpDown_Hour = GUICtrlCreateUpdown($cInput_Hour, BitOR($UDS_WRAP, $UDS_ALIGNLEFT))
GUICtrlSetLimit($cUpDown_Hour, 99, 0)
$cInput_Min = GUICtrlCreateInput("00", 55, 50, 40, 20)
$cUpDown_Min = GUICtrlCreateUpdown($cInput_Min, $UDS_WRAP)
GUICtrlSetLimit($cUpDown_Min, 59, 0)
GUICtrlCreateLabel(":", 50, 50, 5, 20, $SS_CENTER)

$cButton = GUICtrlCreateButton("Read", 10, 100, 80, 30)
GUICtrlSetState(-1, $GUI_FOCUS)

$cUpDummy = GUICtrlCreateDummy()
$cDownDummy = GUICtrlCreateDummy()

GUISetState()

GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")

; Set GUIAccelerators
Local $aAccelKeys[2][2] = [["{UP}", $cUpDummy],["{DOWN}", $cDownDummy]]
GUISetAccelerators($aAccelKeys)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cButton
            $sTimer = GUICtrlRead($cInput_Hour) & ":" & GUICtrlRead($cInput_Min)
            MsgBox(0, "Timer", $sTimer)

        Case $cUpDummy
            Switch $sFocus
                Case "Hour"
                    $iHour = Number(GUICtrlRead($cInput_Hour))
                    If $iHour <> 99 Then
                        GUICtrlSetData($cInput_Hour, $iHour + 1)
                    Else
                        GUICtrlSetData($cInput_Hour, "00")
                    EndIf
                Case "Min"
                    $iMin = Number(GUICtrlRead($cInput_Min))
                    If $iMin <> 59 Then
                        GUICtrlSetData($cInput_Min, $iMin + 1)
                    Else
                        GUICtrlSetData($cInput_Min, "00")
                    EndIf
            EndSwitch
        Case $cDownDummy
            Switch $sFocus
                Case "Hour"
                    $iHour = Number(GUICtrlRead($cInput_Hour))
                    If $iHour <> 0 Then
                        GUICtrlSetData($cInput_Hour, $iHour - 1)
                    Else
                        GUICtrlSetData($cInput_Hour, "99")
                    EndIf
                Case "Min"
                    $iMin = Number(GUICtrlRead($cInput_Min))
                    If $iMin <> 0 Then
                        GUICtrlSetData($cInput_Min, $iMin - 1)
                    Else
                        GUICtrlSetData($cInput_Min, "59")
                    EndIf
            EndSwitch

    EndSwitch
WEnd

Func _WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam

    $iCID = BitAND($wParam, 0xFFFF)
    $iCode = BitShift($wParam, 16)

    Switch $iCode
        Case $EN_SETFOCUS
            Switch $iCID
                Case $cInput_Hour
                    $sFocus = "Hour"
                Case $cInput_Min
                    $sFocus = "Min"
            EndSwitch
            _GUICtrlEdit_SetSel($iCID, -1, -1)
        Case $EN_CHANGE
            Switch $iCID
                Case $cInput_Hour, $cInput_Min
                    $sContent = GUICtrlRead($iCID)
                    $aSel = _GUICtrlEdit_GetSel($iCID)
                    Switch StringLen($sContent)
                        Case 0 To 2
                            GUICtrlSetData($iCID, StringFormat("%02i", $sContent))
                        Case Else
                            GUICtrlSetData($iCID, StringLeft($sContent, 2))
                    EndSwitch
                    _GUICtrlEdit_SetSel($iCID, $aSel[0], $aSel[1])
            EndSwitch
    EndSwitch

EndFunc   ;==>_WM_COMMAND

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • Moderators

dragan,

Glad I could help. Please let us see the final result. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

This is my final custom control. The only thing that's not working as I wanted is documented in the code. And it's just a minor thing: selecting value after changing it via up/down controls. I know the script is big (~300 lines) only for one control, but at least I covered all things I needed. And like I said, I am limited by my AutoIt skills, I am sure someone could do all of this much more efficient and simple.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <Constants.au3>
#include <GuiEdit.au3>

Global $edittingNumber = 1
Global $inputHasFocus = True

Global $Form1 = GUICreate("Form1", 400, 200)
Global $theInputCtrl = GUICtrlCreateInput('02.00', 5, 5, 80, 21, BitOR($ES_NUMBER, $ES_LEFT, $ES_AUTOHSCROLL))
GUICtrlSetLimit(-1, 5)
Global $theUpDownCtrl = GUICtrlCreateUpdown(-1)
Global $wProcHandle = DllCallbackRegister("_EditWindowProc", "ptr", "hwnd;uint;wparam;lparam")
Global $wProcOldLocal = _WinAPI_SetWindowLong(GUICtrlGetHandle($theInputCtrl), $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle))
Global $cUpDummy = GUICtrlCreateDummy()
Global $cDownDummy = GUICtrlCreateDummy()
Global $cLeftDummy = GUICtrlCreateDummy()
Global $cRightDummy = GUICtrlCreateDummy()
Global $cDotDummy = GUICtrlCreateDummy()
Local $aAccelKeys[6][2] = [["{UP}", $cUpDummy],["{DOWN}", $cDownDummy], ["{LEFT}", $cLeftDummy], ["{RIGHT}", $cRightDummy], ["{.}", $cDotDummy], ["{NUMPADDOT}", $cDotDummy]]
GUISetAccelerators($aAccelKeys)
GUICtrlCreateButton('Loose focus from input', 5, 60, 200, 25)
GUISetState(@SW_SHOW, $Form1)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

_WinAPI_SetWindowLong(GUICtrlGetHandle($theInputCtrl), $GWL_WNDPROC, $wProcOldLocal)
DllCallbackFree($wProcHandle)

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch BitAND($wParam, 0xFFFF)
        Case $theUpDownCtrl
            Local $tStruct = DllStructCreate("hwnd;long;int;long;long", $lParam)
            If DllStructGetData($tStruct, 3) = 0xFFFFFD2E Then ; $UDN_DELTAPOS
                Local $divider = 1
                If $edittingNumber = 1 Then
                    $divider = 1
                Else
                    $divider = 100
                EndIf
                Local $calc = DllStructGetData($tStruct, 5)/$divider
                Local $readVal = Number(GUICtrlRead($theInputCtrl))
                Local $newVal = $readVal + $calc
                If $newVal >= 100 then
                    $newVal = 100-$newVal
                ElseIf $newVal < 0 then
                    $newVal = 100+$newVal
                EndIf
                Local $theVal = StringFormat("%#.2f", $newVal)
                Local $splitVal = StringSplit($theVal, '.')
                Local $firstVal = StringFormat("%02d", $newVal)
                Local $finalVal = $firstVal & '.' & $splitVal[$splitVal[0]]
                Local $theDot = StringInStr($finalVal, '.')
                Local $iCount = StringLen($finalVal)
                GUICtrlSetData($theInputCtrl, $finalVal)
                If $edittingNumber = 1 Then
                    _GUICtrlEdit_SetSel($theInputCtrl, 0, $theDot-1) ;<---- not overriding the original function...
                Else
                    _GUICtrlEdit_SetSel($theInputCtrl, $theDot, $iCount) ;<---- not overriding the original function...
                EndIf
                Return True ;<---- ...even with return value
            EndIf
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Local $nID = BitAND($iwParam, 0x0000FFFF)
    #forceref $hWnd, $iMsg, $iwParam, $ilParam
    $iCode = _WinAPI_HiWord($iwParam)
    Switch $nID
        Case $cDotDummy
            If NOT $inputHasFocus then Return $GUI_RUNDEFMSG
            Local $curRead = GUICtrlRead($theInputCtrl)
            Local $iCount = StringLen($curRead)
            Local $theDot = StringInStr($curRead, '.')
            If NOT $theDot Then
                If $curRead = '' Then
                    GUICtrlSetData($theInputCtrl, '00.')
                Else
                    Local $iPos = _GUICtrlEdit_GetSel($theInputCtrl)
                    If IsArray($iPos) Then
                        Local $finalVal = StringFormat("%02d", Number(StringLeft($curRead, $iPos[0]))) & '.' & StringTrimLeft($curRead, $iPos[0])
                        GUICtrlSetData($theInputCtrl, $finalVal)
                    EndIf
                EndIf
            Else
                Local $leftSide = StringFormat("%02d", Number(StringLeft($curRead, $theDot)))
                Local $rightSide = StringFormat("%02d", Number(StringTrimLeft($curRead, $theDot)))
                Local $finalVal = $leftSide & '.' & $rightSide
                GUICtrlSetData($theInputCtrl, $finalVal)
                $theDot = StringInStr($finalVal, '.')
                $iCount = StringLen($finalVal)
                _GUICtrlEdit_SetSel($theInputCtrl, $theDot, $iCount)
            EndIf
            $edittingNumber = 2
        Case $cUpDummy
            If NOT $inputHasFocus then Return $GUI_RUNDEFMSG
            _FixTheInput()
            Local $curRead = GUICtrlRead($theInputCtrl)
            Local $iCount = StringLen($curRead)
            Local $theDot = StringInStr($curRead, '.')
            Local $splitVal = StringSplit($curRead, '.')
            If $splitVal[0] < 2 then Return $GUI_RUNDEFMSG
            Local $finalVal
            If $edittingNumber = 1 Then
                Local $newVal = $splitVal[1]+1
                If $newVal >= 100 then $newVal = 100-$newVal
                $finalVal = StringFormat("%02d", $newVal) & '.' & StringFormat("%02d", Number($splitVal[2]))
                GUICtrlSetData($theInputCtrl, $finalVal)
                _GUICtrlEdit_SetSel($theInputCtrl, 0, $theDot-1)
            Else
                Local $newVal = $splitVal[2]+1
                If $newVal >= 100 then
                    $newVal = 100-$newVal
                    $splitVal[1] += 1
                    If $splitVal[1] >= 100 then $splitVal[1] = 100-$splitVal[1]
                EndIf
                $finalVal = StringFormat("%02d", $splitVal[1]) & '.' & StringFormat("%02d", Number($newVal))
                GUICtrlSetData($theInputCtrl, $finalVal)
                _GUICtrlEdit_SetSel($theInputCtrl, $theDot, $iCount)
            EndIf
            Return True
        Case $cDownDummy
            If NOT $inputHasFocus then Return $GUI_RUNDEFMSG
            _FixTheInput()
            Local $curRead = GUICtrlRead($theInputCtrl)
            Local $iCount = StringLen($curRead)
            Local $theDot = StringInStr($curRead, '.')
            Local $splitVal = StringSplit($curRead, '.')
            If $splitVal[0] < 2 then Return $GUI_RUNDEFMSG
            Local $finalVal
            If $edittingNumber = 1 Then
                Local $newVal = $splitVal[1]-1
                If $newVal < 0 then $newVal = 100+$newVal
                $finalVal = StringFormat("%02d", $newVal) & '.' & StringFormat("%02d", Number($splitVal[2]))
                GUICtrlSetData($theInputCtrl, $finalVal)
                _GUICtrlEdit_SetSel($theInputCtrl, 0, $theDot-1)
            Else
                Local $newVal = $splitVal[2]-1
                If $newVal < 0 then
                    $newVal = 100+$newVal
                    $splitVal[1] -= 1
                    If $splitVal[1] < 0 then $splitVal[1] = 100+$splitVal[1]
                EndIf
                $finalVal = StringFormat("%02d", $splitVal[1]) & '.' & StringFormat("%02d", Number($newVal))
                GUICtrlSetData($theInputCtrl, $finalVal)
                _GUICtrlEdit_SetSel($theInputCtrl, $theDot, $iCount)
            EndIf
            Return True
        Case $cLeftDummy
            If NOT $inputHasFocus then Return $GUI_RUNDEFMSG
            _FixTheInput()
            Local $curRead = GUICtrlRead($theInputCtrl)
            Local $iCount = StringLen($curRead)
            Local $theDot = StringInStr($curRead, '.')
            If $edittingNumber = 2 Then
                $edittingNumber = 1
            EndIf
            _GUICtrlEdit_SetSel($theInputCtrl, 0, $theDot-1)
            Return True
        Case $cRightDummy
            If NOT $inputHasFocus then Return $GUI_RUNDEFMSG
            _FixTheInput()
            Local $curRead = GUICtrlRead($theInputCtrl)
            Local $iCount = StringLen($curRead)
            Local $theDot = StringInStr($curRead, '.')
            If $edittingNumber = 1 Then
                $edittingNumber = 2
            EndIf
            _GUICtrlEdit_SetSel($theInputCtrl, $theDot, $iCount)
            Return True
        Case $theInputCtrl
            Switch $iCode
                Case $EN_SETFOCUS
                    $inputHasFocus = True
                Case $EN_KILLFOCUS
                    $inputHasFocus = False
                    _FixTheInput()
;~                 Case $EN_CHANGE ;I tried this too, but no luck...
;~                     Local $curRead = GUICtrlRead($theInputCtrl)
;~                     Local $iCount = StringLen($curRead)
;~                     Local $theDot = StringInStr($curRead, '.')
;~                     If $edittingNumber = 1 Then
;~                         _GUICtrlEdit_SetSel($theInputCtrl, 0, $theDot-1)
;~                     Else
;~                         _GUICtrlEdit_SetSel($theInputCtrl, $theDot, $iCount)
;~                     EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _FixTheInput()
    Local $curRead = GUICtrlRead($theInputCtrl)
    Local $iCount = StringLen($curRead)
    Local $theDot = StringInStr($curRead, '.')
    If NOT $theDot Then
        If $curRead = '' Then
            GUICtrlSetData($theInputCtrl, '00.00')
        Else
            If $iCount >= 3 then
                $curRead = StringFormat("%.2f", $curRead/((10^$iCount)/100))
            EndIf
            Local $firstNumber = StringFormat("%02d", $curRead)
            $theDot = StringInStr($curRead, '.')
            Local $secondNumber = '00'
            If $theDot then
                $secondNumber = Number(StringTrimLeft($curRead, $theDot))
                If StringLen($secondNumber) = 1 then $secondNumber &= '0'
            EndIf
            GUICtrlSetData($theInputCtrl, $firstNumber & '.' & $secondNumber)
        EndIf
    Else
        Local $firstNumber = StringFormat("%02d", Number(StringLeft($curRead, $theDot)))
        Local $secondNumber = Number(StringTrimLeft($curRead, $theDot))
        If StringLen($secondNumber) = 1 then $secondNumber &= '0'
        GUICtrlSetData($theInputCtrl, $firstNumber & '.' & $secondNumber)
    EndIf
EndFunc

Func _EditWindowProc($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Switch $hWnd
        case GUICtrlGetHandle($theInputCtrl)
            Switch $iMsg
                Case $WM_GETDLGCODE
                    Local $curRead = GUICtrlRead($theInputCtrl)
                    Local $iCount = StringLen($curRead)
                    Local $theDot = StringInStr($curRead, '.')
                    Switch $wParam
                        Case 48 to 57
                            If $iCount >= 2 then
                                If NOT $theDot Then
                                    Local $iPos = _GUICtrlEdit_GetSel($theInputCtrl)
                                    If IsArray($iPos) Then
                                        If $iPos[0] = 2 Then
                                            GUICtrlSetData($theInputCtrl, $curRead & '.')
                                            Return _WinAPI_CallWindowProc($wProcOldLocal, $hWnd, $iMsg, $wParam, $lParam)
                                        Else
                                            Local $finalVal = StringLeft($curRead, $iPos[0]) & ($wParam-48) & '.' & StringTrimLeft($curRead, $iPos[0])
                                            GUICtrlSetData($theInputCtrl, $finalVal)
                                            Return True
                                        EndIf
                                    EndIf
                                Else
                                    Local $iPos = _GUICtrlEdit_GetSel($theInputCtrl)
                                    If IsArray($iPos) Then
                                        Switch $iPos[0]
                                            Case 0
                                                _GUICtrlEdit_SetSel($theInputCtrl, 0, $theDot-1)
                                            Case 2
                                                _GUICtrlEdit_SetSel($theInputCtrl, $theDot, $iCount)
                                        EndSwitch
                                    EndIf
                                EndIf
                            EndIf
                    EndSwitch
                Case 533
                    Local $curRead = GUICtrlRead($theInputCtrl)
                    Local $iCount = StringLen($curRead)
                    Local $theDot = StringInStr($curRead, '.')
                    If NOT $theDot Then
                        If $curRead = '' Then
                            GUICtrlSetData($theInputCtrl, '00.00')
                        Else
                            Local $firstNumber = StringFormat("%02d", Number($curRead))
                            GUICtrlSetData($theInputCtrl, $firstNumber & '.00')
                        EndIf
                    Else
                        _WinAPI_CallWindowProc($wProcOldLocal, $hWnd, $iMsg, $wParam, $lParam)
                        Local $iPos = _GUICtrlEdit_GetSel($theInputCtrl)
                        If IsArray($iPos) Then
                            If $iPos[0] <> $iPos[1] then Return True
                            If $iPos[0] < $theDot Then
                                $edittingNumber = 1
                                _GUICtrlEdit_SetSel($theInputCtrl, 0, $theDot-1)
                            Else
                                $edittingNumber = 2
                                _GUICtrlEdit_SetSel($theInputCtrl, $theDot, $iCount)
                            EndIf
                            Return True
                        EndIf
                    EndIf
            EndSwitch
    EndSwitch
    Return _WinAPI_CallWindowProc($wProcOldLocal, $hWnd, $iMsg, $wParam, $lParam)
EndFunc

Features are:

- Auto-adding dot: You can type number like: 4567, but you will get: 45.67

- Detecting manual typed dot: If you type 5, then press dot, and type 33, you will get: 05.33

- you can press keyboard left/right to focus on that part of the number

- keyboard up/down to change value of the selected number part

- using UpDownControl you can change value of the selected number part (partially working like the one in Date control, because it's not selecting that part after changing it's value, but it's selecting entire input)

- Auto-configuring format style if the input control lost the focus (like Date control is using)

Edited by dragan
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...