kk_lee69 发表于 2017-7-30 03:01:29

如何使用左键单点击达成LISTVIEW连续选中状态??

如何使用左键单点击达成可以达成LISTVIEW 如同 被
_GUICtrlListView_SetItemSelected 选中后的状态

标准的模式 是 我单点击 ITEM1就会选中 ITEM1
再单点击 一次 ITEM2 就会把 ITEM1 的状态取消 变成选中
ITEM2

我需要的是 可以不按 CTRL 键 可以达成 如同按下 CTRL键一样的效果

P.S 不使用 Send ( "按键" [, 标志] ) 方法 发送 CTRL按键






#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>
#include <WindowsConstants.au3>

$Debug_LV = False ; ?查??到 ListView 函?的?名, ?置 True,并使用一?句柄到另一?控件查看它的工作
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

   Local $hListView

    GUICreate("ListView 列表?? UDF 函?演示", 400, 300)
    $hListView = GUICtrlCreateListView("", 2, 2, 394, 268, $LVS_SHOWSELALWAYS , $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER)
    GUISetState()

    ; 添加列
    _GUICtrlListView_AddColumn($hListView, "數據", 100)

    ; 添加?据?
    GUICtrlCreateListViewItem("ITEN 1", $hListView)
    GUICtrlCreateListViewItem("ITEM 2", $hListView)
    GUICtrlCreateListViewItem("ITEM 3", $hListView)
    GUICtrlCreateListViewItem("ITEN 4", $hListView)
    GUICtrlCreateListViewItem("ITEM 5", $hListView)
    GUICtrlCreateListViewItem("ITEM 6", $hListView)
    GUICtrlCreateListViewItem("ITEN 7", $hListView)
    GUICtrlCreateListViewItem("ITEM 8", $hListView)
    GUICtrlCreateListViewItem("ITEM 9", $hListView)

    ; 循?到用?退出
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete()


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
      #forceref $hWnd, $iMsg, $iwParam
      Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo, $s

      $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
      $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
      $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
      $iCode = DllStructGetData($tNMHDR, "Code")
                Switch $iCode
                                                       
                        Case $NM_CLICK ;左點擊按一下
                        ConsoleWrite("A")

                EndSwitch

      Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

yamakawa 发表于 2017-7-30 15:06:56

本帖最后由 yamakawa 于 2017-7-30 15:13 编辑

首先, _GUICtrlListView_GetSelectedColumn读取出当前选择的项的索引,保存到数组
然后,循环读取数组,_GUICtrlListView_SetSelectedColumn设置。应该是这个过程,没测试,这几天折腾sqlite。懒得写代码了

不对,,应该是第一次选择的时候,_GUICtrlListView_GetSelectedIndices保存索引到数组
第二次选择的时候,添加当前选择索引到数组,然后循环读取数组,, _GUICtrlListView_SetItemSelected

yamakawa 发表于 2017-7-30 16:13:19

本帖最后由 yamakawa 于 2017-7-30 18:14 编辑

刚刚再看发现你要求 再次点击取消   所以修改代码

未精简,仅供测试Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
      #forceref $hWnd, $iMsg, $iwParam
      Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo, $index

      $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
      $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
      $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
      $iCode = DllStructGetData($tNMHDR, "Code")
                Switch $iCode
                                                      
                                        Case $NM_CLICK ;左點擊按一下
                                                ;====>特别说明,需要增加一个全局变量 Global $sResult
                                                               $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                              $index = DllStructGetData($tInfo, "Index")
                                                                ConsoleWrite( $index & @CRLF)
                                                                If $index = -1 Then
                                                                        ReDim $sResult
                                                                        Return
                                                                EndIf
                                                               
                                                                $tindex = _ArraySearch($sResult,$index)
                               If$tindex= -1 Then
                                                                   _ArrayAdd($sResult,$index)
                                                           Else
                                                                   _ArrayDelete($sResult,$tindex)
                                                                   _GUICtrlListView_SetItemSelected($hListView,$tindex,False)

                                                           EndIf
                                                          
                                                               
                                                       
                              ConsoleWrite(_ArrayToString($sResult) & @CRLF)
                                                                If IsArray($sResult) Then
                                                                        _GUICtrlListView_BeginUpdate($hListView)
                                                                        _GUICtrlListView_SetItemSelected($hListView,-1,False)

                                                                        For $i = 0 To UBound($sResult) -1
                                                                                _GUICtrlListView_SetItemSelected($hListView,$sResult[$i])
                                                                        Next
                                                                        _GUICtrlListView_EndUpdate($hListView)
                                                                EndIf
                                EndSwitch


      Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

kk_lee69 发表于 2017-7-30 18:14:24

本帖最后由 kk_lee69 于 2017-7-30 18:16 编辑

回复 3# yamakawa


這個方法我試過...最大的缺點就是 會閃爍畫面很不協調

因為你每點擊 一次就會 從頭到尾 將數組內的 資訊 再重新選擇一次

你可以點選看看效果跟你 是著按下 CTRL 然後點選看看 的效果 有差異的

因此 上來尋找更好的解決方法

yamakawa 发表于 2017-8-16 12:05:19

回复 4# kk_lee69


    {:face (356):}今天没事做,突然想到你这问题解决方法。。。                Case $NM_CLICK ;左點擊按一下
                        _WinAPI_Keybd_Event(0xA2, Default)没有加判断,比如点击空白怎么样,,你自己加吧


退出部分记得加If _IsPressed("A2") Then
        ConsoleWrite("LContrl is pressed!" & @CRLF)
        _WinAPI_Keybd_Event(0xA2, $KEYEVENTF_KEYUP)
EndIf
GUIDelete()释放ctrl按下状态。。。不然。。嘿嘿

kk_lee69 发表于 2017-8-27 02:50:21

回复 5# yamakawa

官方 已經有人回覆 有範例在

可是 老實說 我大概懂他在幹嘛但是我無法改成 可以融入我的 程式
又不好意思 跟 老外問太多所以只好上來這 找你幫忙我覺得 你的程式功力應該比我好
呵呵

大概看得出來 他是
; Subclass ListView to receive keyboard/mouse messages
Local $pListViewFunc = DllCallbackGetPtr( DllCallbackRegister( "ListViewFunc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) )
_WinAPI_SetWindowSubclass( $hListView, $pListViewFunc, 0, 0 ) ; $iSubclassId = 0, $pData = 0
註冊了一個子消息之類的然後再利用那個 ListViewFunc去控制

我常用的是 3.3.8 的程式

這個範例我改用 v3.3.8 的主程式   V3.3.14 的API 功能.... 無法執行成功畫面會不見整個程式GUI 都出不來....

也就是說 我如果要用這個方法就得 改用新版的主程式
但是 我的東西太多了不想改主程式版本
但是要把下面的範例改成 V3.3.8 可以用的 我又改不出來...
所以無法測試 ..........

不知道您是否可以幫忙改成 3.38 可以RUN   我在測試看看怎麼融入我的程式裡面

唉一堆的想法想用英文表達 還真是困難~~~


#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIShellEx.au3>
;#include <WinAPI.au3>
#include <GuiListView.au3>

Opt( "MustDeclareVars", 1 )

Global $idListView, $idAddSingleSel, $idDelSingleSel

Example()

Func Example()
; Create GUI
GUICreate( "ctrl+single-click --> single-click", 420, 200 )

; Create ListView
$idListView = GUICtrlCreateListView( "", 10, 10, 400, 180, $GUI_SS_DEFAULT_LISTVIEW-$LVS_SINGLESEL, $WS_EX_CLIENTEDGE )
_GUICtrlListView_SetExtendedListViewStyle( $idListView, $LVS_EX_DOUBLEBUFFER+$LVS_EX_FULLROWSELECT )
Local $hListView = GUICtrlGetHandle( $idListView )

; Add columns to ListView
_GUICtrlListView_InsertColumn( $idListView, 0, "Column 1", 94 )
_GUICtrlListView_InsertColumn( $idListView, 1, "Column 2", 94 )
_GUICtrlListView_InsertColumn( $idListView, 2, "Column 3", 94 )
_GUICtrlListView_InsertColumn( $idListView, 3, "Column 4", 94 )

; Fill ListView
Local $iItems = 100
For $i = 0 To $iItems - 1
    GUICtrlCreateListViewItem( $i & "/Column 1|" & $i & "/Column 2|" & $i & "/Column 3|" & $i & "/Column 4", $idListView )
Next

; Subclass ListView to receive keyboard/mouse messages
Local $pListViewFunc = DllCallbackGetPtr( DllCallbackRegister( "ListViewFunc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) )
_WinAPI_SetWindowSubclass( $hListView, $pListViewFunc, 0, 0 ) ; $iSubclassId = 0, $pData = 0

; Add/del single selection
$idAddSingleSel = GUICtrlCreateDummy()
$idDelSingleSel = GUICtrlCreateDummy()
Local $iItem

; Show GUI
GUISetState( @SW_SHOW )

; Message loop
While 1
    Switch GUIGetMsg()
      Case $idAddSingleSel
      $iItem = GUICtrlRead( $idAddSingleSel )
      _GUICtrlListView_SetItemSelected( $idListView, $iItem, True )
      _GUICtrlListView_SetItemFocused( $idListView, $iItem )
      Case $idDelSingleSel
      $iItem = GUICtrlRead( $idDelSingleSel )
      _GUICtrlListView_SetItemSelected( $idListView, $iItem, False )
      _GUICtrlListView_SetItemFocused( $idListView, $iItem )
      Case $GUI_EVENT_CLOSE
      ExitLoop
    EndSwitch
WEnd

; Cleanup
_WinAPI_RemoveWindowSubclass( $hListView, $pListViewFunc, 0 )
GUIDelete()
EndFunc

Func ListViewFunc( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData )
If $iMsg <> $WM_LBUTTONDOWN Then Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )

Switch $wParam
    Case 0x0001; 0x0001 = MK_LBUTTON (LButton down)
      If _GUICtrlListView_GetSelectedCount( $idListView ) Then
      Local $aHit = _GUICtrlListView_HitTest( GUICtrlGetHandle( $idListView ), BitAND( $lParam, 0xFFFF ), BitShift( $lParam, 16 ) )
      If Not ( @error Or $aHit = -1 ) Then
          If _GUICtrlListView_GetItemSelected( $idListView, $aHit ) Then
            GUICtrlSendToDummy( $idDelSingleSel, $aHit )
          Else
            GUICtrlSendToDummy( $idAddSingleSel, $aHit )
          EndIf
      EndIf
      Return 0 ; Disable single-click in ListView to prevent resetting selections
      EndIf

    Case 0x0009; 0x0009 = MK_LBUTTON (LButton down) + MK_CONTROL (Ctrl down)
      Return 0   ; Disable single selections in ListView with ctrl+single-click
EndSwitch

Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )
; Call next function in subclass chain (this forwards messages to main GUI)
#forceref $iSubclassId, $pData
EndFunc

yamakawa 发表于 2017-8-27 09:29:27

{:face (394):}scite错误代码是怎样的??
因为我也是3.3.14版本的,,,,,,要测试旧版得想办法先去下载

chzj589 发表于 2017-8-27 09:52:49

回复 6# kk_lee69


在3.3.9.4测试没问题呀

kk_lee69 发表于 2017-8-27 11:59:31

回复 8# chzj589
我的是 3.3.8

呵呵

kk_lee69 发表于 2017-8-27 12:01:15

回复 7# yamakawa

沒有錯誤代碼 就是這個方法在 3.3.8 版本   連 GUI 都跑不出來
但是 程式有在 工作管理員中 執行

yamakawa 发表于 2017-8-27 12:59:21

{:face (396):}没有错误代码?scite下面信息输出那里什么都没有?

yamakawa 发表于 2017-8-27 14:14:21

回复 10# kk_lee69


    你有旧版安装包么?没地方找了。。论坛的几个链接都失效了。。。。有的话你给我个。我试试看。。。繁中的也ok

yamakawa 发表于 2017-8-27 16:35:38

这个位置。。

chzj589 发表于 2017-8-27 17:05:15

回复 13# yamakawa

刚用3.3.6.1测试,
        If $iMsg <> $WM_LBUTTONDOWN Then Return DllCall("comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam) 
Return DllCall("comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)

问题出在这里:

yamakawa 发表于 2017-8-27 17:25:01

本帖最后由 yamakawa 于 2017-8-27 17:28 编辑

回复 14# chzj589


    那就试着分句写。。If $iMsg <> $WM_LBUTTONDOWN Then
        Local $result = DllCall("comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)
        If Not @error Then
                Return $result  
        Else
                ConsoleWrite("Error is " & @error & @CRLF)
        EndIf
EndIf
Local $result = DllCall("comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)
If Not @error Then
        Return $result  
Else
        ConsoleWrite("Error is " & @error & @CRLF)
EndIf
看看行不行
页: [1] 2 3 4 5 6
查看完整版本: 如何使用左键单点击达成LISTVIEW连续选中状态??