请教下ListView中加入Combo后,感觉融合有点问题,请教下大家怎么修改和完善
本帖最后由 锋城未逾年 于 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
$g_Item = DllStructGetData($tLVHITTESTINFO, "Item")
$g_Item = DllStructGetData($tLVHITTESTINFO, "SubItem")
$aRect = _GUICtrlListView_GetSubItemRect($g_ListView, $g_Item, $g_Item)
$aPos = ControlGetPos($hGUI, "", $g_ListView)
$sData = _GUICtrlListView_GetItemText($g_ListView, $g_Item, $g_Item)
_WinAPI_SetParent(GUICtrlGetHandle($g_Combo), $g_ListView)
_WinAPI_BringWindowToTop(GUICtrlGetHandle($g_Combo))
GUICtrlSetPos($g_Combo, $aPos + $aRect +5, $aPos + $aRect + 3, _GUICtrlListView_GetColumnWidth($g_ListView, $g_Item))
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, GUICtrlRead($g_Combo), $g_Item)
GUICtrlSetPos($g_Combo, -1000, -100)
GUICtrlSetData($g_Combo, "")
Dim $g_Item = 0
EndFunc ;==>_UdpData
本帖最后由 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
$g_Item = DllStructGetData($tLVHITTESTINFO, "Item")
$g_Item = DllStructGetData($tLVHITTESTINFO, "SubItem")
$aRect = _GUICtrlListView_GetSubItemRect($g_ListView, $g_Item, $g_Item)
$aPos = ControlGetPos($hGUI, "", $g_ListView)
$sData = _GUICtrlListView_GetItemText($g_ListView, $g_Item, $g_Item)
_WinAPI_SetParent(GUICtrlGetHandle($g_Combo), $g_ListView)
_WinAPI_BringWindowToTop(GUICtrlGetHandle($g_Combo))
GUICtrlSetPos($g_Combo, $aPos + $aRect +5, $aPos + $aRect + 3, _GUICtrlListView_GetColumnWidth($g_ListView, $g_Item))
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 Or $iX > $aComboPos + $aComboPos Or _
$iY < $aComboPos Or $iY > $aComboPos + $aComboPos 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, GUICtrlRead($g_Combo), $g_Item)
GUICtrlSetPos($g_Combo, -1000, -100)
GUICtrlSetData($g_Combo, "")
Dim $g_Item = 0
$g_bComboVisible = False ; 重置组合框可见状态
EndFunc ;==>_UdpData
redapple2008 发表于 2025-6-20 11:39
修复内容包括:
添加全局变量跟踪组合框可见状态
非常感谢您的回复,就是我发现一个问题,编辑listView中的项目和子项时,文字一上一下的,就是感觉融合的不彻底,好像是图层问题,请教下老师怎么解决,谢谢! #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("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 = DllStructGetData($tLVHITTESTINFO, "Item")
$g_Item = DllStructGetData($tLVHITTESTINFO, "SubItem")
; 获取子项位置和文本
Local $aRect = _GUICtrlListView_GetSubItemRect($g_ListView, $g_Item, $g_Item)
Local $aPos = ControlGetPos($hGUI, "", $g_ListView)
Local $sData = _GUICtrlListView_GetItemText($g_ListView, $g_Item, $g_Item)
; 设置组合框为ListView的子窗口
_WinAPI_SetParent(GUICtrlGetHandle($g_Combo), $g_ListView)
WinSetOnTop(GUICtrlGetHandle($g_Combo), "", 1) ; 置顶显示
; 定位组合框到子项位置
GUICtrlSetPos($g_Combo, $aPos + $aRect + 5, $aPos + $aRect + 3, _
_GUICtrlListView_GetColumnWidth($g_ListView, $g_Item))
; 设置组合框内容
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 Or $iX > $aComboPos + $aComboPos Or _
$iY < $aComboPos Or $iY > $aComboPos + $aComboPos 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, GUICtrlRead($g_Combo), $g_Item)
; 隐藏组合框
GUICtrlSetPos($g_Combo, -1000, -100)
GUICtrlSetData($g_Combo, "")
$g_bComboVisible = False ; 重置可见状态
EndFunc
加了一些注释
有时间改成虚表吧
页:
[1]