找回密码
 加入
搜索
楼主: pusofalse

[系统综合] 练习002 - 使Input控件只能输入特定范围内的数字

 火... [复制链接]
发表于 2010-1-3 16:16:54 | 显示全部楼层
回复 15# ceoguang


    双字节字符
 楼主| 发表于 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[0]

                $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[1] - $aSel[0]) Then
                                $sVal = StringLeft($sString, $aSel[0]) & StringRight($sString, StringLen($sString) - $aSel[1])
                        Else
                                $sVal &= StringLeft($sString, $iPosition - 1)
                                $sVal &= StringRight($sString, StringLen($sString) - $iPosition)
                        EndIf
                Else
                        If ($aSel[1] - $aSel[0]) Then
                                $sString = StringLeft($sString, $aSel[0]) & StringRight($sString, StringLen($sString) - $aSel[1])
                        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

评分

参与人数 2金钱 +51 收起 理由
zldfsz + 31 发现个问题,就是关闭后程序进程并没有退出 ...
nmgwddj + 20 牛。的确看不明白。但是做到了你题目所说的 ...

查看全部评分

发表于 2010-1-3 18:07:21 | 显示全部楼层
奇怪,楼上的代码为什么不能用小键盘输入?

评分

参与人数 1金钱 +10 收起 理由
pusofalse + 10 感谢测试。

查看全部评分

 楼主| 发表于 2010-1-3 18:15:55 | 显示全部楼层
回复 18# ceoguang


    原来如此,因为我是在笔记本上测试的(小键盘在笔记本上不会被经常用到),所以忽略了这一点,在_IsPressed那里出了问题。感谢你的测试。
发表于 2010-1-3 18:32:20 | 显示全部楼层
本帖最后由 ceoguang 于 2010-1-3 18:35 编辑

小键盘上的0-9代码是多少?
自问自答,是60-69
 楼主| 发表于 2010-1-3 18:33:33 | 显示全部楼层
小键盘上的虚拟键代码范围是0x60-0x69。
已经修改,感谢测试。
发表于 2010-1-3 18:39:49 | 显示全部楼层
回复 17# pusofalse


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

评分

参与人数 1金钱 +10 收起 理由
pusofalse + 10 好建议

查看全部评分

发表于 2010-1-3 18:45:01 | 显示全部楼层
再问,如果要允许粘贴该怎么改?
ClipGet()的内容怎么确定是指定的数字?用正则又怎么表达?
发表于 2010-1-3 20:21:56 | 显示全部楼层
回复 23# ceoguang


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

评分

参与人数 1金钱 +10 收起 理由
pusofalse + 10 学习了

查看全部评分

发表于 2010-1-4 06:56:18 | 显示全部楼层
回复 7# pusofalse


    楼上的代码真的可以吗??我用了怎么感觉还是不怎么好呢,请在给一个好的
发表于 2010-1-4 13:58:52 | 显示全部楼层
回复  ceoguang


     Case $WM_PASTE ; 粘贴时发送的消息。
if not StringRegExp(ClipGet(),"^[1-9] ...
pcbar 发表于 2010-1-3 20:21


貌似是鼠标粘贴,而不是快捷粘贴吧!
发表于 2010-1-4 18:34:39 | 显示全部楼层
本帖最后由 jybb001 于 2010-1-4 20:35 编辑

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

我刚刚换了几台机子测试了还是一样的
具体情况是这样的,
先打开几个pusofalse  17#的例子
然后关掉,
开四一上再关掉 CPU就会100%卡死
发表于 2010-1-4 19:12:48 | 显示全部楼层
回复 27# jybb001

经多测试,没有出现你所述的症状!!!,我这输入任何数值时,CPU与内存没有变动!!!!
是不是版本的问题!!!!偶用的是v3.3.1.1 (beta)
发表于 2010-1-4 20:33:59 | 显示全部楼层
本帖最后由 jybb001 于 2010-1-5 09:33 编辑

回复 28# lchl0588
不是输入数值,而是运行它,再关闭,
多运行几个,再关闭 然后就会,CPU跑100%
也可能是版本的问题,
 楼主| 发表于 2010-1-8 18:47:25 | 显示全部楼层
回复 27# jybb001


    你的测试方法有问题,或者,你的AU3版本问题。十分肯定。

评分

参与人数 1金钱 +10 贡献 +2 收起 理由
zldfsz + 10 + 2 我也遇到,后来加一句DllCallbackFree($hEC ...

查看全部评分

您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-18 18:34 , Processed in 0.075874 second(s), 15 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表