本帖最后由 yhxhappy 于 2017-12-17 12:06 编辑
我想复制 ListView 中 鼠标所点中行单元格 数据,所以就做了一个右键菜单,鼠标在ListView中点击右键时弹出菜单复制内容。
现在的问题是:如果ListView中一旦有水平滚动条,并且拖动后,获取的行列数据就不准了。
以下是演示的代码,初始状态是可以获取的,一旦向右滚动获取的内容就不准。
自己研究解决了,增加滚动条的补偿,_GUIScrollBars_GetScrollInfoPos 获取滚动条的位置,见第51,54行代码
实际还是有些误差,大概5个像素左右,当点击两列之间时会发现。但对我影响不大就不研究了。
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#Include <GuiScrollBars.au3>
Opt("MouseCoordMode", 0) ;设置用于鼠标函数的 coords 坐标参照 = 激活窗口的相对坐标
$GUI = GUICreate("listview 列表视图", 300, 250)
$listview = GUICtrlCreateListView("列 1 |列 2 |列 3 |列 4 |列 5 |列 6 |列 7 ", 10, 10, 280, 150)
GUICtrlCreateListViewItem("项目 1|子项 12|子项 13|项目 14|子项 15|子项 16|子项 17", $listview)
GUICtrlCreateListViewItem("项目 2|子项 22|子项 23|项目 24|子项 25|子项 26|子项 27", $listview)
GUICtrlCreateListViewItem("项目 3|子项 32|子项 33|项目 34|子项 35|子项 36|子项 37", $listview)
$ColumnNum = _GUICtrlListView_GetColumnCount($listview) ;取得列数
Global $xyArray[$ColumnNum]
For $i = 0 To $ColumnNum-1
$ItemXY = _GUICtrlListView_GetSubItemRect($listview, 0, $i)
$xyArray[$i] = $ItemXY[0]
Next
;===右键 系统菜单窗口=======================================================================
$OptionsDummy = GUICtrlCreateDummy() ;创建一个虚拟控件,让菜单依托于控件, 这个控制必须创建于主窗口,否则不能触发事件
$ContextMenu = GUICtrlCreateContextMenu($OptionsDummy) ;创造菜单
$CopyMenu = GUICtrlCreateMenuItem("复制单元格内容", $ContextMenu) ;"复制单元格内容"
;==========================================================================================
Global $ClickLVRowIndex ;LV选中的行序号
Global $ClickLVRowIndex ;LV鼠标所在的列序号
GUISetState()
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
Exit
Case $GUI_EVENT_SECONDARYUP
$Pos = GUIGetCursorInfo($GUI) ;取得鼠标当前停留控件的信息
If @error Or Not IsArray($Pos) Then ContinueLoop
If $Pos[4] <> $listview Then ContinueLoop ;鼠标没有点在LV内,则返回
If Not StringInStr(ControlGetFocus($GUI), "SysListView") Then ContinueLoop ;如果当前激活的控件不是LV,则返回
$ClickLVRowIndex = _GUICtrlListView_GetHotItem($listview) ;取得选中项的行序号
If $ClickLVRowIndex < 0 Then ContinueLoop ;没有项目被选中,则返回
$GPos = WinGetPos($GUI) ;取得窗口的坐标
If @error Or Not IsArray($GPos) Then ContinueLoop
$MPos = MouseGetPos() ;取得鼠标相对于窗口的坐标
If @error Then ContinueLoop
$ScrollBarsPOS = _GUIScrollBars_GetScrollInfoPos(GUICtrlGetHandle($listview), $SB_HORZ) ;LV控件水平滚动条位置
For $i = UBound($xyArray)-1 To 0 Step -1 ;当前鼠标X坐标 在 列坐标数组内 从大到小对比
If $MPos[0]+$GPos[0]+$ScrollBarsPOS-10 > $xyArray[$i]+$GPos[0] Then ;10是LV的X坐标,如果X坐标大于某列的X坐标,且小于下一列的X坐标,则说明鼠标点击了该列
$ClickLVColumnIndex = $i
ExitLoop
EndIf
Next
DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", GUICtrlGetHandle($ContextMenu), "int", 0, "int", $GPos[0]+$MPos[0], "int", $GPos[1]+$MPos[1], "hwnd", $GUI, "ptr", 0) ; 显示指定坐标(x,y), 属于一个指定 GUI 窗口(hWnd)的弹出菜单(hMenu).
Case $CopyMenu
$String = _GUICtrlListView_GetItemText($listview, $ClickLVRowIndex, $ClickLVColumnIndex)
MsgBox(0, "鼠标点中的单元格内容", $String)
EndSwitch
WEnd
|