找回密码
 加入
搜索
查看: 210|回复: 5

[GUI管理] 请教下ListView中加入Combo后,感觉融合有点问题,请教下大家怎么修改和完善

[复制链接]
发表于 2025-6-15 21:07:44 | 显示全部楼层 |阅读模式
本帖最后由 锋城未逾年 于 2025-6-15 21:07 编辑

请教下ListView中加入Combo后,感觉融合有点问题,请教下大家怎么修改和完善

代码如下:
#include <GuiListView.au3>
#include <GuiComboBox.au3>
#include <WinAPI.au3>

Global $hGUI, $g_ListView, $g_Combo, $g_Item, $hOldC
Opt("GUIOnEventMode", 1)
_CreateGUI()

While 1
        Sleep(100)
WEnd

Func _CreateGUI()
        $hGUI = GUICreate("ListViewClass", 600, 300, -1, -1)
        GUISetOnEvent(-3, "_Exit")
        $g_Combo = GUICtrlCreateCombo('', -100, -100)
        GUICtrlSetFont(-1,11)
        $g_ListView = GUICtrlCreateListView("", 60, 50, 480, 200, -1, 0x00000221)
        For $i = 1 To 5
                _GUICtrlListView_AddColumn(-1, "col1", 80)
        Next
        For $i = 0 To 9
                _GUICtrlListView_AddItem($g_ListView, "Item" & $i)
                For $j = 1 To 4
                        _GUICtrlListView_AddSubItem($g_ListView, $i, "SubItem" & $j, $j)
                Next
        Next

        $hCall = DllCallbackRegister("_ListViewProc", "ptr", "hWnd;uint;wparam;lparam")
        $hOldC = _WinAPI_SetWindowLong(GUICtrlGetHandle($g_ListView), -4, DllCallbackGetPtr($hCall))
        GUISetState(@SW_SHOW)
EndFunc   ;==>_CreateGUI

Func _Exit()
        Exit
EndFunc   ;==>_Exit

Func _ListViewProc($hWnd, $iMsg, $wparam, $lparam)
        Switch $iMsg
                Case 0x0203
                        $iX = BitAND($lparam, 0xFFFF)
                        $iY = BitShift($lparam, 16)
                        $tLVHITTESTINFO = DllStructCreate("int X;int Y;uint Flags;int Item;int SubItem")
                        DllStructSetData($tLVHITTESTINFO, "X", $iX)
                        DllStructSetData($tLVHITTESTINFO, "Y", $iY)
                        _SendMessage($hWnd, $LVM_SUBITEMHITTEST, 0, DllStructGetPtr($tLVHITTESTINFO))
                        Dim $g_Item[2]
                        $g_Item[0] = DllStructGetData($tLVHITTESTINFO, "Item")
                        $g_Item[1] = DllStructGetData($tLVHITTESTINFO, "SubItem")
                        $aRect = _GUICtrlListView_GetSubItemRect($g_ListView, $g_Item[0], $g_Item[1])
                        $aPos = ControlGetPos($hGUI, "", $g_ListView)
                        $sData = _GUICtrlListView_GetItemText($g_ListView, $g_Item[0], $g_Item[1])
                        _WinAPI_SetParent(GUICtrlGetHandle($g_Combo), $g_ListView)
                        _WinAPI_BringWindowToTop(GUICtrlGetHandle($g_Combo))
                        GUICtrlSetPos($g_Combo, $aPos[0] + $aRect[0] +5, $aPos[1] + $aRect[1] + 3, _GUICtrlListView_GetColumnWidth($g_ListView, $g_Item[1]))
                        GUICtrlSetData($g_Combo,"")
                        _GUICtrlComboBox_AddString($g_Combo,"添加")
                        _GUICtrlComboBox_SetEditText($g_Combo, $sData)
                Case 0x0201
                        If IsArray($g_Item) Then _UdpData()

        EndSwitch
        Return _WinAPI_CallWindowProc($hOldC, $hWnd, $iMsg, $wparam, $lparam)
EndFunc   ;==>_ListViewProc

Func _UdpData()
        If Not IsArray($g_Item) Then Return
        _GUICtrlListView_SetItemText($g_ListView, $g_Item[0], GUICtrlRead($g_Combo), $g_Item[1])
        GUICtrlSetPos($g_Combo, -1000, -100)
        GUICtrlSetData($g_Combo, "")
        Dim $g_Item = 0
EndFunc   ;==>_UdpData

本帖子中包含更多资源

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

×

评分

参与人数 1金钱 +10 收起 理由
qq413774005 + 10 很给力!

查看全部评分

发表于 2025-6-20 11:39:41 | 显示全部楼层
本帖最后由 redapple2008 于 2025-6-20 11:41 编辑

修复内容包括:

添加全局变量跟踪组合框可见状态

修改鼠标点击处理逻辑

添加键盘回车键支持

优化组合框显示/隐藏逻辑
#include <GuiListView.au3>
#include <GuiComboBox.au3>
#include <WinAPI.au3>

Global $hGUI, $g_ListView, $g_Combo, $g_Item, $hOldC
Global $g_bComboVisible = False ; 添加组合框可见状态跟踪
Opt("GUIOnEventMode", 1)
_CreateGUI()

While 1
        Sleep(100)
WEnd

Func _CreateGUI()
        $hGUI = GUICreate("ListViewClass", 600, 300, -1, -1)
        GUISetOnEvent(-3, "_Exit")
        $g_Combo = GUICtrlCreateCombo('', -100, -100)
        GUICtrlSetFont(-1,11)
        $g_ListView = GUICtrlCreateListView("", 60, 50, 480, 200, -1, 0x00000221)
        For $i = 1 To 5
                _GUICtrlListView_AddColumn(-1, "col1", 80)
        Next
        For $i = 0 To 9
                _GUICtrlListView_AddItem($g_ListView, "Item" & $i)
                For $j = 1 To 4
                        _GUICtrlListView_AddSubItem($g_ListView, $i, "SubItem" & $j, $j)
                Next
        Next

        $hCall = DllCallbackRegister("_ListViewProc", "ptr", "hWnd;uint;wparam;lparam")
        $hOldC = _WinAPI_SetWindowLong(GUICtrlGetHandle($g_ListView), -4, DllCallbackGetPtr($hCall))
        GUISetState(@SW_SHOW)
EndFunc   ;==>_CreateGUI

Func _Exit()
        Exit
EndFunc   ;==>_Exit

Func _ListViewProc($hWnd, $iMsg, $wparam, $lparam)
        Switch $iMsg
                Case 0x0203 ; WM_LBUTTONDBLCLK
                        $iX = BitAND($lparam, 0xFFFF)
                        $iY = BitShift($lparam, 16)
                        $tLVHITTESTINFO = DllStructCreate("int X;int Y;uint Flags;int Item;int SubItem")
                        DllStructSetData($tLVHITTESTINFO, "X", $iX)
                        DllStructSetData($tLVHITTESTINFO, "Y", $iY)
                        _SendMessage($hWnd, $LVM_SUBITEMHITTEST, 0, DllStructGetPtr($tLVHITTESTINFO))
                        Dim $g_Item[2]
                        $g_Item[0] = DllStructGetData($tLVHITTESTINFO, "Item")
                        $g_Item[1] = DllStructGetData($tLVHITTESTINFO, "SubItem")
                        $aRect = _GUICtrlListView_GetSubItemRect($g_ListView, $g_Item[0], $g_Item[1])
                        $aPos = ControlGetPos($hGUI, "", $g_ListView)
                        $sData = _GUICtrlListView_GetItemText($g_ListView, $g_Item[0], $g_Item[1])
                        _WinAPI_SetParent(GUICtrlGetHandle($g_Combo), $g_ListView)
                        _WinAPI_BringWindowToTop(GUICtrlGetHandle($g_Combo))
                        GUICtrlSetPos($g_Combo, $aPos[0] + $aRect[0] +5, $aPos[1] + $aRect[1] + 3, _GUICtrlListView_GetColumnWidth($g_ListView, $g_Item[1]))
                        GUICtrlSetData($g_Combo,"")
                        _GUICtrlComboBox_AddString($g_Combo,"添加")
                        _GUICtrlComboBox_SetEditText($g_Combo, $sData)
                        $g_bComboVisible = True ; 标记组合框可见
                        
                Case 0x0201 ; WM_LBUTTONDOWN
                        If $g_bComboVisible Then
                            ; 检查点击位置是否在组合框内
                            Local $hCombo = GUICtrlGetHandle($g_Combo)
                            Local $aComboPos = WinGetPos($hCombo)
                            Local $tPoint = DllStructCreate("int X;int Y")
                            DllStructSetData($tPoint, "X", BitAND($lparam, 0xFFFF))
                            DllStructSetData($tPoint, "Y", BitShift($lparam, 16))
                            _WinAPI_ClientToScreen($hWnd, $tPoint)
                            Local $iX = DllStructGetData($tPoint, "X")
                            Local $iY = DllStructGetData($tPoint, "Y")
                            
                            If $iX < $aComboPos[0] Or $iX > $aComboPos[0] + $aComboPos[2] Or _
                               $iY < $aComboPos[1] Or $iY > $aComboPos[1] + $aComboPos[3] Then
                                _UdpData()
                            EndIf
                        EndIf
                        
                Case 0x0100 ; WM_KEYDOWN - 添加键盘支持
                        If $g_bComboVisible And $wParam = 0x0D Then ; 回车键
                            _UdpData()
                        EndIf
                        
        EndSwitch
        Return _WinAPI_CallWindowProc($hOldC, $hWnd, $iMsg, $wparam, $lparam)
EndFunc   ;==>_ListViewProc

Func _UdpData()
        If Not IsArray($g_Item) Then Return
        _GUICtrlListView_SetItemText($g_ListView, $g_Item[0], GUICtrlRead($g_Combo), $g_Item[1])
        GUICtrlSetPos($g_Combo, -1000, -100)
        GUICtrlSetData($g_Combo, "")
        Dim $g_Item = 0
        $g_bComboVisible = False ; 重置组合框可见状态
EndFunc   ;==>_UdpData

 楼主| 发表于 2025-6-20 20:47:44 | 显示全部楼层
redapple2008 发表于 2025-6-20 11:39
修复内容包括:

添加全局变量跟踪组合框可见状态

非常感谢您的回复,就是我发现一个问题,编辑listView中的项目和子项时,文字一上一下的,就是感觉融合的不彻底,好像是图层问题,请教下老师怎么解决,谢谢!
发表于 2025-6-23 09:10:45 | 显示全部楼层
#include <GuiListView.au3>
#include <GuiComboBox.au3>
#include <WinAPI.au3>

; 全局变量声明
Global $hGUI, $g_ListView, $g_Combo, $g_Item[2], $hOldC ; 界面控件句柄
Global $g_bComboVisible = False ; 组合框可见状态跟踪
Opt("GUIOnEventMode", 1) ; 启用事件模式

; 创建主界面
_CreateGUI()

; 主循环保持程序运行
While 1
    Sleep(100)
WEnd

Func _CreateGUI()
    ; 创建主窗口
    $hGUI = GUICreate("ListView编辑示例", 600, 300)
    GUISetOnEvent(-3, "_Exit") ; 关闭按钮事件绑定
   
    ; 创建隐藏的组合框(初始位置在界面外)
    $g_Combo = GUICtrlCreateCombo('', -100, -100)
    GUICtrlSetFont(-1, 11) ; 设置字体大小
   
    ; 创建ListView控件
    $g_ListView = GUICtrlCreateListView("", 60, 50, 480, 200, -1, 0x00000221) ; LVS_SHOWSELALWAYS样式
   
    ; 添加5列
    For $i = 1 To 5
        _GUICtrlListView_AddColumn($g_ListView, "列" & $i, 80)
    Next
   
    ; 添加10行数据
    For $i = 0 To 9
        _GUICtrlListView_AddItem($g_ListView, "项目" & $i)
        For $j = 1 To 4
            _GUICtrlListView_AddSubItem($g_ListView, $i, "子项" & $j, $j)
        Next
    Next

    ; 设置ListView子类化处理
    $hCall = DllCallbackRegister("_ListViewProc", "ptr", "hWnd;uint;wparam;lparam")
    $hOldC = _WinAPI_SetWindowLong(GUICtrlGetHandle($g_ListView), -4, DllCallbackGetPtr($hCall)) ; GWL_WNDPROC
   
    GUISetState(@SW_SHOW) ; 显示窗口
EndFunc

; 退出程序
Func _Exit()
    Exit
EndFunc

; ListView消息处理函数
Func _ListViewProc($hWnd, $iMsg, $wparam, $lparam)
    Switch $iMsg
        Case 0x0203 ; WM_LBUTTONDBLCLK - 双击事件
            ; 获取点击位置
            $iX = BitAND($lparam, 0xFFFF)
            $iY = BitShift($lparam, 16)
            
            ; 检测点击的子项
            Local $tLVHITTESTINFO = DllStructCreate("int X;int Y;uint Flags;int Item;int SubItem")
            DllStructSetData($tLVHITTESTINFO, "X", $iX)
            DllStructSetData($tLVHITTESTINFO, "Y", $iY)
            _SendMessage($hWnd, $LVM_SUBITEMHITTEST, 0, DllStructGetPtr($tLVHITTESTINFO))
            
            ; 保存点击的项目和子项索引
            $g_Item[0] = DllStructGetData($tLVHITTESTINFO, "Item")
            $g_Item[1] = DllStructGetData($tLVHITTESTINFO, "SubItem")
            
            ; 获取子项位置和文本
            Local $aRect = _GUICtrlListView_GetSubItemRect($g_ListView, $g_Item[0], $g_Item[1])
            Local $aPos = ControlGetPos($hGUI, "", $g_ListView)
            Local $sData = _GUICtrlListView_GetItemText($g_ListView, $g_Item[0], $g_Item[1])
            
            ; 设置组合框为ListView的子窗口
            _WinAPI_SetParent(GUICtrlGetHandle($g_Combo), $g_ListView)
            WinSetOnTop(GUICtrlGetHandle($g_Combo), "", 1) ; 置顶显示
            
            ; 定位组合框到子项位置
            GUICtrlSetPos($g_Combo, $aPos[0] + $aRect[0] + 5, $aPos[1] + $aRect[1] + 3, _
                          _GUICtrlListView_GetColumnWidth($g_ListView, $g_Item[1]))
            
            ; 设置组合框内容
            GUICtrlSetData($g_Combo, "")
            _GUICtrlComboBox_AddString($g_Combo, "添加") ; 添加默认选项
            _GUICtrlComboBox_SetEditText($g_Combo, $sData) ; 显示当前文本
            
            $g_bComboVisible = True ; 标记组合框可见
            
        Case 0x0201 ; WM_LBUTTONDOWN - 左键点击
            If $g_bComboVisible Then
                ; 检查点击位置是否在组合框外
                Local $hCombo = GUICtrlGetHandle($g_Combo)
                Local $aComboPos = WinGetPos($hCombo)
                Local $tPoint = DllStructCreate("int X;int Y")
               
                ; 转换坐标到屏幕位置
                DllStructSetData($tPoint, "X", BitAND($lparam, 0xFFFF))
                DllStructSetData($tPoint, "Y", BitShift($lparam, 16))
                _WinAPI_ClientToScreen($hWnd, $tPoint)
               
                ; 判断点击是否在组合框区域外
                Local $iX = DllStructGetData($tPoint, "X")
                Local $iY = DllStructGetData($tPoint, "Y")
               
                If $iX < $aComboPos[0] Or $iX > $aComboPos[0] + $aComboPos[2] Or _
                   $iY < $aComboPos[1] Or $iY > $aComboPos[1] + $aComboPos[3] Then
                    _UdpData() ; 在外部点击时保存数据
                EndIf
            EndIf
            
        Case 0x0100 ; WM_KEYDOWN - 键盘事件
            ; 回车键保存数据
            If $g_bComboVisible And $wParam = 0x0D Then
                _UdpData()
            EndIf
    EndSwitch
   
    ; 传递消息给原始窗口过程
    Return _WinAPI_CallWindowProc($hOldC, $hWnd, $iMsg, $wparam, $lparam)
EndFunc

; 更新数据到ListView
Func _UdpData()
    If Not IsArray($g_Item) Then Return
   
    ; 更新子项文本
    _GUICtrlListView_SetItemText($g_ListView, $g_Item[0], GUICtrlRead($g_Combo), $g_Item[1])
   
    ; 隐藏组合框
    GUICtrlSetPos($g_Combo, -1000, -100)
    GUICtrlSetData($g_Combo, "")
   
    $g_bComboVisible = False ; 重置可见状态
EndFunc
发表于 2025-6-23 09:11:42 | 显示全部楼层
加了一些注释
发表于 2025-7-2 17:35:18 | 显示全部楼层
有时间改成虚表吧
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2025-7-11 07:38 , Processed in 0.070673 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

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