afan 发表于 2010-1-3 16:16:54

回复 15# ceoguang


    双字节字符

pusofalse 发表于 2010-1-3 18:00:36

#include <Misc.au3>
#include <GUIEdit.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Local $wValidKey_8 = 0
For $i = 48 To 57
        Assign("wValidKey_" & $i, 0)
Next

Local $fIsReading = 0, $fIsWriting = 0
$hEC = DllCallbackRegister("_EditProcedure", "int", "hWnd;uint;wparam;lparam")
$pEC = DllCallbackGetPtr($hEC)

$hGUI = GUICreate("Test", 150, 80)

$iiTest = GUICtrlCreateInput("", 20, 20, 110, 20)
$hOEC = _WinAPI_SetWindowLong(GUICtrlGetHandle(-1), -4, $pEC)

GUISetState()

Do
Until GUIGetMsg() = -3
GUIDelete($hGUI)
DllCallbackFree($hEC)

Func _EditProcedure($hWnd, $iMsg, $iwParam, $ilParam)
        Local $sString, $sVal, $iX, $iY, $iPosition, $aSel

        Switch $iMsg
        Case $WM_PASTE ; 粘贴时发送的消息。
                Return 0 ; 返回任意值,以切断消息的继续传递。

        Case $WM_CUT ; 剪切时发送的消息。
                Return 0 ; 返回任意值,以切断消息的继续传递。

        Case $WM_SETTEXT ; ControlSetText、GUICtrlSetData发送的消息。
                ; 判断是否是GUICtrlSetData发送,否则切断消息传递。
                If $fIsWriting = 0 Then Return 0

        Case $WM_GETTEXT ; ControlGetText 、GUICtrlRead发送的消息。
                ; 判断此消息是否由GUICtrlRead发送,否则返回任意值以切断消息传递。
                If $fIsReading = 0 Then Return 0

        Case $WM_CHAR ; ControlSend、Send、以及由人手物理输入时发送的消息。
                ; WM_CHAR消息中, $iwParam 参数设为按下的键的ASCII码。
                ; 用Chr($iwParam) 可以将ASCII转换为实际输入的字符。

                ; 判断是否是输入了数字或者退格符。
                If Not IsDeclared("wValidKey_" & $iwParam) Then Return 0

                ; 判断按键是否处于按下状态,若是则可以说明是通过物理输入的。
                ; 否则,可以断定此消息是由ControlSend、Send发送。
                If (_IsPressed(Hex($iwParam, 2)) Or _IsPressed(Hex($iwParam + 0x30, 2))) = 0 Then
                       Return 0
                EndIf

                ; 获取插入符在input框的位置。
                _GetCaretPos($iX, $iY)
                $iPosition = _GUICtrlEdit_CharFromPos($hWnd, $iX, $iY)
                $iPosition = $iPosition

                $fIsReading = 1 ; 设置为1,表示$WM_GETTEXT消息是由GUICtrlRead发送的。
                $sString = GUICtrlRead($iiTest) ; 读取input框中现有的内容,不包含此时输入的字符。
                $fIsReading = 0 ; $fIsReading为0时,表示$WM_GETTEXT是由其他外在程序发送的。

                $aSel = _GUICtrlEdit_GetSel($hWnd)
                If $iwParam = 8 Then ; 判断按键是否为退格。
                        If ($aSel - $aSel) Then
                                $sVal = StringLeft($sString, $aSel) & StringRight($sString, StringLen($sString) - $aSel)
                        Else
                                $sVal &= StringLeft($sString, $iPosition - 1)
                                $sVal &= StringRight($sString, StringLen($sString) - $iPosition)
                        EndIf
                Else
                        If ($aSel - $aSel) Then
                                $sString = StringLeft($sString, $aSel) & StringRight($sString, StringLen($sString) - $aSel)
                        EndIf

                        $sVal &= StringLeft($sString, $iPosition) & Chr($iwParam)
                        $sVal &= StringRight($sString, StringLen($sString) - $iPosition)
                EndIf

                ; 此时$sVal的值为 input框中现有的内容,另加,此时输入的字符。
                ; 如果input框现有内容为12,插入符在1与2之间,此时按下的键为3,$sVal的值为132。


                ; 判断首位是否为0。
                If StringRegExp($sVal, "^0+") Then
                        $sVal = StringRegExpReplace($sVal, "^0+", "")
                        $fIsWriting = 1
                        GUICtrlSetData($iiTest, $sVal)
                        $fIsWriting = 0
                        _GUICtrlEdit_SetSel($hWnd, 0, 0)
;                        _EditProcedure($hWnd, $WM_CHAR, 8, 0)
                        Return 0
                EndIf

                ; 判断是否在1-50之间。
                If ($sVal <> "") And (Number($sVal) < 1 Or Number($sVal) > 50) Then Return 0
        EndSwitch

        ; 继续消息的传递。
        Return _WinAPI_CallWindowProc($hOEC, $hWnd, $iMsg, $iwParam, $ilParam)
EndFunc        ;==>_EditProcedure

Func _GetCaretPos(ByRef $iX, ByRef $iY)
        Local $tXY
        $tXY = DllStructCreate("long X;long Y")
        DllCall("User32.dll", "int", "GetCaretPos", "ptr", DllStructGetPtr($tXY))
        $iX = DllStructGetData($tXY, "X")
        $iY = DllStructGetData($tXY, "Y")
        $tXY = 0
EndFunc        ;==>_GetCaretPos

ceoguang 发表于 2010-1-3 18:07:21

奇怪,楼上的代码为什么不能用小键盘输入?

pusofalse 发表于 2010-1-3 18:15:55

回复 18# ceoguang


    原来如此,因为我是在笔记本上测试的(小键盘在笔记本上不会被经常用到),所以忽略了这一点,在_IsPressed那里出了问题。感谢你的测试。

ceoguang 发表于 2010-1-3 18:32:20

本帖最后由 ceoguang 于 2010-1-3 18:35 编辑

小键盘上的0-9代码是多少?
自问自答,是60-69

pusofalse 发表于 2010-1-3 18:33:33

小键盘上的虚拟键代码范围是0x60-0x69。
已经修改,感谢测试。

afan 发表于 2010-1-3 18:39:49

回复 17# pusofalse


    要是能够在选中状态下输入就完美了,呵呵~

ceoguang 发表于 2010-1-3 18:45:01

再问,如果要允许粘贴该怎么改?
ClipGet()的内容怎么确定是指定的数字?用正则又怎么表达?

pcbar 发表于 2010-1-3 20:21:56

回复 23# ceoguang


   Case $WM_PASTE ; 粘贴时发送的消息。
if not StringRegExp(ClipGet(),"^$|^\d$|^50$",0) ThenReturn 0 ; 返回任意值,以切断消息的继续传递。

hackbase 发表于 2010-1-4 06:56:18

回复 7# pusofalse


    楼上的代码真的可以吗??我用了怎么感觉还是不怎么好呢,请在给一个好的

lchl0588 发表于 2010-1-4 13:58:52

回复ceoguang


   Case $WM_PASTE ; 粘贴时发送的消息。
if not StringRegExp(ClipGet(),"^ ...
pcbar 发表于 2010-1-3 20:21 http://www.autoitx.com/images/common/back.gif

貌似是鼠标粘贴,而不是快捷粘贴吧!

jybb001 发表于 2010-1-4 18:34:39

本帖最后由 jybb001 于 2010-1-4 20:35 编辑

不知道为什么我测试几次之后CPU就会狂飙到100%,程序点X关闭后任务管理器还有好多AUTOIT3.EXE
同时打开倒没事,就是在关闭之后CPU才会狂飙到100%,打开几个就有几个AUTOIT3.EXE在管理器中,结束后正常,不知何故,也有可以是我的电脑的问题,不知道别人有没有遇到?

我刚刚换了几台机子测试了还是一样的
具体情况是这样的,
先打开几个pusofalse17#的例子
然后关掉,
开四一上再关掉 CPU就会100%卡死。

lchl0588 发表于 2010-1-4 19:12:48

回复 27# jybb001

经多测试,没有出现你所述的症状!!!,我这输入任何数值时,CPU与内存没有变动!!!!
是不是版本的问题!!!!偶用的是v3.3.1.1 (beta)

jybb001 发表于 2010-1-4 20:33:59

本帖最后由 jybb001 于 2010-1-5 09:33 编辑

回复 28# lchl0588
不是输入数值,而是运行它,再关闭,
多运行几个,再关闭 然后就会,CPU跑100%
也可能是版本的问题,

pusofalse 发表于 2010-1-8 18:47:25

回复 27# jybb001


    你的测试方法有问题,或者,你的AU3版本问题。十分肯定。
页: 1 [2] 3
查看完整版本: 练习002 - 使Input控件只能输入特定范围内的数字