发现_GUICtrlListView_FindText搜索有个BUG,不支持中文完全匹配(已解决)
本帖最后由 txm888 于 2014-4-1 07:28 编辑近期问题多多,又发现_GUICtrlListView_FindText搜索中文有个严重问题,如果搜索关键字含中文,而控件里又没找到的话,是返回的0,而帮助文里说搜索不到返回-1
其次,搜索关键字若包含中文,搜索只能模糊匹配第一项,不能完全匹配,不管$fPartialOK = True是设置False还是True都不行,相反,搜索英文和数字是很好精确的,支持模糊和完全匹配
有没有哪位遇到这问题的啊?
_GUICtrlListView_FindText
--------------------------------------------------------------------------------
用指定文本搜索项目
#Include <GuiListView.au3>
_GUICtrlListView_FindText($hWnd, $sText[, $iStart = -1[, $fPartialOK = True[, $fWrapOK = True]]])
参数
$hWnd 控件句柄
$sText 匹配的文本
$iStart 开始搜索的基于 0 的项目索引 或设置为 -1, 从开始进行. 指定项目自身排除在外.
$fPartialOK 如果为真, 且项目文本已搜索文本开始,视为匹配
$fWrapOK 如果为真, 且未找到匹配项, 搜索将从第一项继续
返回值
成功: 基于 0 的项目索引失败: -1
备注
搜索大小写不敏感. 搜索仅对项目进行. 如果想搜索子项使用 _GUICtrlListView_FindInText.#AutoIt3Wrapper_au3check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
Opt('MustDeclareVars', 1)
$Debug_LV = False ; 检查传递给函数的类名, 设置为真并使用另一控件句柄观察其工作
_Main()
Func _Main()
Global $iI, $hListView
; 创建界面
GUICreate("ListView Find Text", 400, 300)
$hListView = GUICtrlCreateListView("", 2, 2, 394, 268)
GUISetState()
; 添加列
_GUICtrlListView_AddColumn($hListView, "Items", 100)
; 添加项
_GUICtrlListView_BeginUpdate($hListView)
_GUICtrlListView_AddItem($hListView, "我爱你123" & 1)
_GUICtrlListView_AddItem($hListView, "123我爱你" & 2)
_GUICtrlListView_AddItem($hListView, "你爱我abc" & 3)
For $iI = 4 To 49
_GUICtrlListView_AddItem($hListView, "你爱我" & $iI)
Next
_GUICtrlListView_AddItem($hListView, "Target item")
For $iI = 51 To 100
_GUICtrlListView_AddItem($hListView, "Item " & $iI)
Next
_GUICtrlListView_EndUpdate($hListView)
; 搜索目标项目
$iI = _GUICtrlListView_FindText($hListView, "你爱我", true)
MsgBox(4160, "Information", "Target Item Index: " & $iI)
_GUICtrlListView_EnsureVisible($hListView, $iI)
; 循环至用户退出
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
GUIDelete()
EndFunc ;==>_Main
;如上代码搜“你爱我”,结果索引为2,事实上我用了false,应该是找不到结果。我换成true后,结果索引还是为2
;真搞不懂了解决如下:;2014-03-31 修复项目文本包含中文无法完全匹配的BUG by Afan
Func _GUICtrlListView_FindItem($hWnd, $iStart, ByRef $tFindInfo, $sText = '')
Local $aSR = StringRegExp($sText, '[^\x00-\xff]', 3), $iL = UBound($aSR), $i
Local $iBuffer = StringLen($sText) + 1 + $iL
Local $tBuffer = DllStructCreate('char Text[' & $iBuffer & ']')
Local $pBuffer = DllStructGetPtr($tBuffer)
For $i = 0 To $iL - 2
$sText &= ' '
Next
DllStructSetData($tBuffer, 'Text', $sText)
Local $iRet
If IsHWnd($hWnd) Then
If _WinAPI_InProcess($hWnd, $_lv_ghLastWnd) Then
DllStructSetData($tFindInfo, 'Text', $pBuffer)
$iRet = _SendMessage($hWnd, $LVM_FINDITEM, $iStart, $tFindInfo, 0, 'wparam', 'struct*')
Else
Local $iFindInfo = DllStructGetSize($tFindInfo)
Local $tMemMap
Local $pMemory = _MemInit($hWnd, $iFindInfo + $iBuffer, $tMemMap)
Local $pText = $pMemory + $iFindInfo
DllStructSetData($tFindInfo, 'Text', $pText)
_MemWrite($tMemMap, $tFindInfo, $pMemory, $iFindInfo)
_MemWrite($tMemMap, $tBuffer, $pText, $iBuffer)
$iRet = _SendMessage($hWnd, $LVM_FINDITEM, $iStart, $pMemory, 0, 'wparam', 'ptr')
_MemFree($tMemMap)
EndIf
Else
DllStructSetData($tFindInfo, 'Text', $pBuffer)
$iRet = GUICtrlSendMsg($hWnd, $LVM_FINDITEM, $iStart, DllStructGetPtr($tFindInfo))
EndIf
Return $iRet
EndFunc ;==>_GUICtrlListView_FindItem下载文件直接用即可
经测试,在参数为 false 或 true时:
3.3.6.1 均返回 -1,其它如 3.3.7.15、3.3.9.4、3.3.9.21、3.3.10.0、3.3.10.2 均返回 2 回复 2# afan
A版你好,感谢测试,上例中感觉即便返回2也只对一半,因为true和false是区别全匹配或模糊匹配的选项,上例中,没有任何一项是纯“你爱我"的字符,都加了后辍编号的 楼主这不是坑么??
下面这行你写的就不对:$iI = _GUICtrlListView_FindText($hListView, "你爱我", true)第三个参数应该是索引,你竟然写true或false?
改成:$iI = _GUICtrlListView_FindText($hListView, "你爱我", -1, True)然后重试!!
还“严重BUG!”,我了个去。。。。
额外要说的是,你这段代码本身书写逻辑BUG也不少,例如先Opt('MustDeclareVars', 1)强制所有变量必须先定义后使用,紧接着$Debug_LV = False就没定义,以及在函数内声明Global类型变量等等。
做程序要严谨,出现问题永远要先怀疑自己! 回复 2# afan
你被坑了,亲,他代码写的就不对,看4楼解释。 回复 4# skyfree
不好意思,S大,首先说声抱歉,也向A版说声抱歉,我粘贴时弄得疏忽了,在自己电脑上测试去测试来,反而让代码弄乱了
这问题我也是在几个月前都遇到过了,当时也是在中文上出了点问题,我想不可能有错,这么多人用,而且我在坛子上搜索这方面的问题,没有一个人发过这样的疑问
于是当时我就临时解决了项目文本不要出现中文的可能
近段时间又在弄个东西,遇到要用这listView控件,且项目文本可能存在中文,于是问题来了,项目文本只要包含中文,全匹配搜索始终都返回-1,以开头模糊匹配,可以成功返回索引
但项目文本以开头相同的字符串是很多的,确定不了哪一项
最终,我就从帮助文档里copy了这段代码,格式上没有改,就专测试搜索的结果,也是我自己大意,让您们耽误时间看代码了,
我现在再上传一个格式正确的代码,上来供您测试下,问题仍然是包含中文的项目文本无法完全匹配搜索出来,返回值为-1
感谢S大,感谢A版!#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
_Main()
Func _Main()
GUICreate("ListView Find Text", 400, 300)
$hListView = GUICtrlCreateListView("", 2, 2, 394, 268)
GUISetState()
; 添加列
_GUICtrlListView_AddColumn($hListView, "Items", 100)
; 添加项
_GUICtrlListView_BeginUpdate($hListView)
_GUICtrlListView_AddItem($hListView, "我爱你123" & 1)
_GUICtrlListView_AddItem($hListView, "123我爱你" & 2)
_GUICtrlListView_AddItem($hListView, "你爱我abc" & 3)
For $iI = 4 To 49
_GUICtrlListView_AddItem($hListView, "你爱我" & $iI)
Next
_GUICtrlListView_AddItem($hListView, "Target item")
For $iI = 51 To 100
_GUICtrlListView_AddItem($hListView, "Item " & $iI)
Next
_GUICtrlListView_EndUpdate($hListView)
; 搜索目标项目
$iI = _GUICtrlListView_FindText($hListView, "你爱我abc3", -1, false)
MsgBox(4160, "Information", "Target Item Index: " & $iI)
_GUICtrlListView_EnsureVisible($hListView, $iI)
; 循环至用户退出
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
GUIDelete()
EndFunc ;==>_Main
回复afan
你被坑了,亲,他代码写的就不对,看4楼解释。
skyfree 发表于 2014-3-31 17:19 http://www.autoitx.com/images/common/back.gif
老熟人,没看代码,只帮测试去了,木有想到,还真坑 回复 7# afan
A大你才真是大“坑”!你的机器竟然能跑那么多个AU3版本! 回复afan
A大你才真是大“坑”!你的机器竟然能跑那么多个AU3版本!
user3000 发表于 2014-3-31 19:17 http://www.autoitx.com/images/common/back.gif
呵呵,还不止这几个哈 ~ 本帖最后由 afan 于 2014-3-31 21:09 编辑
回复 6# txm888
将 GuiListView.au3 内的原“_GUICtrlListView_FindItem”重命名,用以下替换试试Func _GUICtrlListView_FindItem($hWnd, $iStart, ByRef $tFindInfo, $sText = '')
Local $aSR = StringRegExp($sText, '[^\x00-\xff]', 3), $iL = UBound($aSR), $i
Local $iBuffer = StringLen($sText) + 1 + $iL
Local $tBuffer = DllStructCreate('char Text[' & $iBuffer & ']')
Local $pBuffer = DllStructGetPtr($tBuffer)
For $i = 0 To $iL - 2
$sText &= ' '
Next
DllStructSetData($tBuffer, 'Text', $sText)
Local $iRet
If IsHWnd($hWnd) Then
If _WinAPI_InProcess($hWnd, $_lv_ghLastWnd) Then
DllStructSetData($tFindInfo, 'Text', $pBuffer)
$iRet = _SendMessage($hWnd, $LVM_FINDITEM, $iStart, $tFindInfo, 0, 'wparam', 'struct*')
Else
Local $iFindInfo = DllStructGetSize($tFindInfo)
Local $tMemMap
Local $pMemory = _MemInit($hWnd, $iFindInfo + $iBuffer, $tMemMap)
Local $pText = $pMemory + $iFindInfo
DllStructSetData($tFindInfo, 'Text', $pText)
_MemWrite($tMemMap, $tFindInfo, $pMemory, $iFindInfo)
_MemWrite($tMemMap, $tBuffer, $pText, $iBuffer)
$iRet = _SendMessage($hWnd, $LVM_FINDITEM, $iStart, $pMemory, 0, 'wparam', 'ptr')
_MemFree($tMemMap)
EndIf
Else
DllStructSetData($tFindInfo, 'Text', $pBuffer)
$iRet = GUICtrlSendMsg($hWnd, $LVM_FINDITEM, $iStart, DllStructGetPtr($tFindInfo))
EndIf
Return $iRet
EndFunc ;==>_GUICtrlListView_FindItem 回复 8# user3000
多个版本没问题的,写个程序自动切换注册表项目就可以的。 回复 10# afan
看来这个函数还真是有问题,下午在公司测试的时候发现确实有问题~修改这个之后可以了~ 回复 11# skyfree
谢谢,还真没想过这么弄一弄的! 回复 10# afan
才人,解决了我很久以来的困惑,貌似问题一到A版这,就成小儿科了
看了下修改,加了点正则,但不明白意思,惭愧,再次感谢
我将代码和修改的文件发到了1楼,方便其它朋友下载使用。 回复 12# haijie1223
感谢参与
页:
[1]
2