找回密码
 加入
搜索
查看: 3549|回复: 11

[AU3基础] _GUICtrlTreeView_GetTree() 函数返回值为空

[复制链接]
发表于 2021-1-15 16:58:55 | 显示全部楼层 |阅读模式
本帖最后由 jiarqq 于 2021-1-15 17:16 编辑

最近在做QQ文件自动接收的小工具。任务栏图标闪烁检测,【全另存为】按钮自动化点击都还顺利,可是在点击【全另存为】按钮之后选择保存位置时遇到了麻烦。



先说一下我的整体思路吧。

第一步:
检测QQ图标是否闪烁,如果闪烁则说明两种可能,一是【来文件了】,二是【来消息了】。不管是来消息还是来文件,一律自动化点击闪烁的托盘图标以弹出聊天窗口做进一步的判断。
第二步:
检查聊天窗口是否存在【全另存为】的按钮,如果存在则判定是 【来文件了】,然后寻找该按钮的相对于窗口的坐标,然后自动化点击。这两步骤不难实现。
第三步:(卡这了)
点击【全另存为】后,会立即弹出一个浏览文件夹对话框,让你选择接收文件的路径。

我用的是思路是这样的:

   A.先使用 _GUICtrlTreeView_FindItemEx(控件句柄,树目录路径) 函数,检索(树视图)指定树目录路径的项目。成功则返回:匹配树目录路径的第一个项目句柄。
   B.再使用 _GUICtrlTreeView_Expand(控件 ID 或句柄,项目句柄, True)展开项目

可是,我发现 AB两个步骤都出了问题,于是我试试注册表,发现一点问题都没有。真是奇怪。

以下是我的实验过程:
测试注册表时成功展开,见下图:



#RequireAdmin
#include <GuiTreeView.au3>

Opt("GUIDataSeparatorChar", "");定义分隔符

;~ $hTreeView = ControlGetHandle('浏览文件夹', '', 'SysTreeView321');获取树控件句柄
$hTreeView = ControlGetHandle('注册表编辑器', '', 'SysTreeView321');获取树控件句柄
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hTreeView = ' & $hTreeView & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

;~ $hTreeView_Path = _GUICtrlTreeView_FindItemEx($hTreeView,'桌面\此电脑\');注意:不同系统【浏览文件夹】对话框显示的名称和路径有可能不一样,测试的时候记得改一下。
$hTreeView_Path = _GUICtrlTreeView_FindItemEx($hTreeView,'计算机\HKEY_CURRENT_USER\SOFTWARE\AutoIt v3');注意:不同系统【注册表】显示的名称或路径有可能不一样,测试的时候记得改一下。
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hTreeView_Path = ' & $hTreeView_Path & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
_GUICtrlTreeView_Expand($hTreeView,$hTreeView_Path,True);【浏览文件夹】指定路径展开失败,【注册表】指定路径展开成功,此函数没有返回值,只能看到状态:展开/折叠
测试QQ的浏览文件夹对话框,项目句柄及展开均失败。
#RequireAdmin
#include <GuiTreeView.au3>

Opt("GUIDataSeparatorChar", "");定义分隔符

$hTreeView = ControlGetHandle('浏览文件夹', '', 'SysTreeView321');获取树控件句柄
;~ $hTreeView = ControlGetHandle('注册表编辑器', '', 'SysTreeView321');获取树控件句柄
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hTreeView = ' & $hTreeView & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

$hTreeView_Path = _GUICtrlTreeView_FindItemEx($hTreeView,'桌面\此电脑\');注意:不同系统【浏览文件夹】对话框显示的名称和路径有可能不一样,测试的时候记得改一下。
;~ $hTreeView_Path = _GUICtrlTreeView_FindItemEx($hTreeView,'计算机\HKEY_CURRENT_USER\SOFTWARE\AutoIt v3');注意:不同系统【注册表】显示的名称或路径有可能不一样,测试的时候记得改一下。
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hTreeView_Path = ' & $hTreeView_Path & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
_GUICtrlTreeView_Expand($hTreeView,$hTreeView_Path,True);【浏览文件夹】指定路径展开失败,【注册表】指定路径展开成功,此函数没有返回值,只能看到状态:展开/折叠


















本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2021-1-15 17:00:10 | 显示全部楼层
对QQ的gui判断会有问题,我更建议是屏幕像素检测。
发表于 2021-1-15 21:24:12 | 显示全部楼层
试试这样
#include <GuiTreeView.au3>

#RequireAdmin
#AutoIt3Wrapper_UseX64 = n
DllCall('User32.dll', 'BOOL', 'SetProcessDPIAware')
Local $hWnd_Control = ControlGetHandle('[title:浏览文件夹; class:#32770]','','SysTreeView321')
Local $sExpandPath = '此电脑\Desktop\新建文件夹' , $sName
Local $aSplit = StringSplit($sExpandPath, '\', 2)
For $i = 0 To UBound($aSplit) - 1
        $sName = $aSplit[$i]
        _Expand($hWnd_Control ,$sName)
        If @error Then Exit MsgBox(0,0,'Err')
        If $i <> UBound($aSplit) -1 Then Sleep(800)
Next
ControlClick('[title:浏览文件夹; class:#32770]','','[CLASS:Button; text:确定]')


Func _Expand($hWnd_Control, $sName)
        Local $hItem = _GUICtrlTreeView_FindItem($hWnd_Control,$sName)
        If Not $hItem Then Return SetError(1,0,'')
        _GUICtrlTreeView_Expand($hWnd_Control, $hItem, True)
        _GUICtrlTreeView_SetSelected($hWnd_Control,$hItem , True)
        _GUICtrlTreeView_ClickItem($hWnd_Control, $hItem)
EndFunc   ;==>_Expand
 楼主| 发表于 2021-1-16 18:56:01 | 显示全部楼层

这样测试好像不行亲
发表于 2021-1-16 19:26:00 | 显示全部楼层
控件句柄都没获取到,后面怎么可能继续…
建议贴上窗口探测信息以参考
 楼主| 发表于 2021-1-16 19:41:48 | 显示全部楼层
afan 发表于 2021-1-16 19:26
控件句柄都没获取到,后面怎么可能继续…
建议贴上窗口探测信息以参考

窗口句柄获取到了,
发表于 2021-1-16 19:46:02 | 显示全部楼层
jiarqq 发表于 2021-1-16 19:41
窗口句柄获取到了,

控件
窗口何用?
 楼主| 发表于 2021-1-16 20:07:16 | 显示全部楼层
afan 发表于 2021-1-16 19:46
控件
窗口何用?

控件句柄已经获取到了
发表于 2021-1-16 20:32:20 | 显示全部楼层
jiarqq 发表于 2021-1-16 20:07
控件句柄已经获取到了

不说了。




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
 楼主| 发表于 2021-1-17 02:03:04 | 显示全部楼层

确实是函数的问题,这样改一下就可以了。
Func _GUICtrlTreeView_GetText32($hWnd, $hItem = 0)
  If Not IsHWnd($hItem) Then $hItem = _GUICtrlTreeView_GetItemHandle($hWnd, $hItem)
  If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

  If $hItem = 0x00000000 Then Return SetError(1, 1, "")

  ; All 8 byte data types for a 64 bit system changed to 4 byte uint's for a 32 bit system
  Local $tagTVITEMEX32 = "struct; uint Mask;struct; uint hItem;uint State;uint StateMask;uint Text;int TextMax;int Image;int SelectedImage;int Children;uint Param; endstruct;" & _
  "int Integral;uint uStateEx;uint hwnd;int iExpandedImage;int iReserved; endstruct"

  Local $tTVITEM = DllStructCreate($tagTVITEMEX32)
  Local $tText
  Local $fUnicode = _GUICtrlTreeView_GetUnicodeFormat($hWnd)
  If $fUnicode Then
    $tText = DllStructCreate("wchar Buffer[4096]"); create a text 'area' for receiving the text
  Else
    $tText = DllStructCreate("char Buffer[4096]"); create a text 'area' for receiving the text
  EndIf

  DllStructSetData($tTVITEM, "Mask", $TVIF_TEXT)
  DllStructSetData($tTVITEM, "hItem", BitShift( $hItem, -32 )) ; 8 byte value --> 4 byte value
  DllStructSetData($tTVITEM, "TextMax", 4096)

  If _WinAPI_InProcess($hWnd, $__ghTVLastWnd) Then
    DllStructSetData($tTVITEM, "Text", DllStructGetPtr($tText))
    _SendMessage($hWnd, $TVM_GETITEMW, 0, $tTVITEM, 0, "wparam", "struct*")
  Else
    Local $iItem = DllStructGetSize($tTVITEM)
    Local $tMemMap
    Local $pMemory = _MemInit($hWnd, $iItem + 4096, $tMemMap)
    Local $pText = $pMemory + $iItem
    DllStructSetData($tTVITEM, "Text", BitShift( $pText, -32 )) ; 8 byte value --> 4 byte value
    _MemWrite($tMemMap, $tTVITEM, $pMemory, $iItem)
    If $fUnicode Then
      _SendMessage($hWnd, $TVM_GETITEMW, 0, BitShift( $pMemory, -32 ), 0, "wparam", "ptr") ; 8 byte value --> 4 byte value
    Else
      _SendMessage($hWnd, $TVM_GETITEMA, 0, $pMemory, 0, "wparam", "ptr")
    EndIf
    _MemRead($tMemMap, $pText, $tText, 4096)
    _MemFree($tMemMap)
  EndIf

  Return DllStructGetData($tText, "Buffer")
EndFunc

参考链接:https://www.autoitscript.com/forum/topic/173529-guictrltreeview-udf-64bit-script-on-x86-control/?tab=comments#comment-1255321


另附32位的UDF




大工告成:








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
 楼主| 发表于 2021-1-17 02:14:30 | 显示全部楼层
本帖最后由 jiarqq 于 2021-1-17 02:16 编辑
jiarqq 发表于 2021-1-17 02:03
确实是函数的问题,这样改一下就可以了。

试了下标准函数 ControlTreeView 也同样不能获取到项目句柄。

看了下备注:在 64 位 Windows 系统上运行 32 位的 AutoIt 时,部分命令可能无效, 此时请使用 64 位 AutoIt 版本.
另一处备注:使用 32 位 Autoit 进程读取 64 位进程时,命令可能会失败. 同理,反之也可能失败.

也许如此吧!




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
 楼主| 发表于 2021-1-17 02:17:04 | 显示全部楼层
本帖最后由 jiarqq 于 2021-1-17 16:00 编辑
jiarqq 发表于 2021-1-17 02:14
试了下标准函数 ControlTreeView 也同样不能获取到项目句柄。

看了下备注:在 64 位 Windows 系统上运 ...

QQ是32位进程,而我使用的是AutoIt3_x64运行的脚本。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-4-20 13:29 , Processed in 0.077132 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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