Jump to content
Sign in to follow this  
LarsJ

ListView example: Use Shift+Up/Down to move items

Recommended Posts

LarsJ

This is an example using a hook procedure to move items in a ListView with Shift+Up/Down.

The script is using APIConstants.au3 for the WinAPIEx.au3 UDF library.

The example is too small for the Example Scripts so I have posted it here. I'm not asking for help.

#include <Constants.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
#Include <APIConstants.au3>  ;For the WinAPIEx.au3 UDF library
#include <WinAPI.au3>
Opt( "MustDeclareVars", 1 )
InstallHookProc()
MainProgram()
Func MainProgram()
Global $hGUI, $hLV, $idLV, $idLVDummy                   ;Window, controls
Global $aIdLVI[1], $aDataLVI[1], $aIdxLVI[1], $idLVI0, $iMaxLVItems = 50 ;ListView items
Global $hLVNewProcHandle, $hLVPreProcHandle              ;LV window procedures (message handlers)
Global $fSHIFT = 0                          ;Flag for SHIFT key
Local $i
$hGUI = GUICreate( "ListView", 300, 200, 500, 200 )
$idLV = GUICtrlCreateListView( "Items|SubItems", 10, 10, 280, 180 )
$idLVDummy = GUICtrlCreateDummy()
ReDim $aIdLVI[$iMaxLVItems], $aDataLVI[$iMaxLVItems], $aIdxLVI[$iMaxLVItems]
$iMaxLVItems -= 1
For $i = 0 To $iMaxLVItems
  $aIdxLVI[$i] = $i
  $aDataLVI[$i] = "Text " & $i + 1 & "|Subtext " & $i + 1
  $aIdLVI[$i] = GUICtrlCreateListViewItem ( $aDataLVI[$i], $idLV )
Next
$idLVI0 = $aIdLVI[0]
;LV window procedures (message handlers)
$hLV = ControlGetHandle( $hGUI, "", $idLV )
$hLVNewProcHandle = DllCallbackRegister( "NewWindowProc", "int", "hwnd;uint;wparam;lparam" )      ;New window procedure, VK_RETURN
$hLVPreProcHandle = _WinAPI_SetWindowLong( $hLV, $GWL_WNDPROC, DllCallbackGetPtr( $hLVNewProcHandle ) ) ;Previous window procedure
GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )
GUISetState()
MsgBox( 0, "ListView", "Use Shift+Up/Down to move items" & @CRLF & _
             "Use Enter/Double click to process item" )
While 1
  Switch GUIGetMsg()
   Case $GUI_EVENT_CLOSE
    _WinAPI_SetWindowLong( $hLV, $GWL_WNDPROC, $hLVPreProcHandle )
    DllCallbackFree( $hLVNewProcHandle )
    GUIDelete( $hGUI )
    Exit
   Case $idLVDummy
    $i = GUICtrlRead( $idLV ) - $idLVI0
    MsgBox( 0, "ListView", "Item " & $i + 1 )
  EndSwitch
WEnd
EndFunc
Func NewWindowProc( $hWnd, $Msg, $wParam, $lParam )
Switch $hWnd
  Case $hLV      ;$WM_GETDLGCODE
   Switch $Msg     ;Sent to the window procedure associated with a control. By default, the system handles all
    Case $WM_GETDLGCODE  ;keyboard input to the control; the system interprets certain types of keyboard input as dia-
     Switch $wParam   ;log box navigation keys. To override this default behavior, the control can respond to the
      Case $VK_RETURN  ;WM_GETDLGCODE message to indicate the types of input it wants to process itself.
       GUICtrlSendToDummy( $idLVDummy )
       Return 0
     EndSwitch
   EndSwitch
EndSwitch
 
;The previous window procedure handles all keys except VK_RETURN
Return _WinAPI_CallWindowProc( $hLVPreProcHandle, $hWnd, $Msg, $wParam, $lParam )
EndFunc
Func WM_NOTIFY( $hWnd, $Msg, $wParam, $lParam )
Local $hWndListView, $tNMHDR, $hWndFrom, $iCode
 
$tNMHDR = DllStructCreate( $tagNMHDR, $lParam )
$hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) )
$iCode = DllStructGetData( $tNMHDR, "Code" )
 
Switch $hWndFrom
  Case $hLV
   Switch $iCode
    Case $NM_DBLCLK
     GUICtrlSendToDummy( $idLVDummy )
   EndSwitch
EndSwitch
 
Return $GUI_RUNDEFMSG
EndFunc
#cs############################################
#       Hook procedures    #
#ce############################################
Func InstallHookProc()
Local $handleModule
Global $hHookProc, $handleHookProc
$handleModule = _WinAPI_GetModuleHandle(0)
;Hook procedure callback function that monitors low-level keyboard input events
$hHookProc = DllCallbackRegister( "HookProc", "long", "int;wparam;lparam" ) ;dll "handle"
;Install the hook procedure callback function (WH_KEYBOARD_LL: Monitor low-level keyboard input events)
$handleHookProc = _WinAPI_SetWindowsHookEx( $WH_KEYBOARD_LL, DllCallbackGetPtr( $hHookProc ), $handleModule )
OnAutoItExitRegister( "UnHook" )
EndFunc
Func HookProc( $nCode, $wParam, $lParam )
Local $tKEYHOOKS, $vkCode, $i, $j, $k = -1
$tKEYHOOKS = DllStructCreate( $tagKBDLLHOOKSTRUCT, $lParam )
If $nCode < 0 Then Return _WinAPI_CallNextHookEx( $handleHookProc, $nCode, $wParam, $lParam )
If $wParam = $WM_KEYDOWN Then
  $vkCode = DllStructGetData( $tKEYHOOKS, "vkCode" )
  if ( $vkCode = $VK_LSHIFT ) Or ( $vkCode = $VK_RSHIFT ) Then
   $fSHIFT = 1
  elseIf ( $fSHIFT = 1 ) And ( ( $vkCode = $VK_DOWN ) Or ( $vkCode = $VK_UP ) ) Then
   $i = GUICtrlRead( $idLV ) - $idLVI0
   if $vkCode = $VK_DOWN Then
    If $i < $iMaxLVItems Then $k = $i + 1  ;Swap data for item $i and $i + 1
   Else ;$vkCode = $VK_UP
    If $i > 0 Then $k = $i - 1     ;Swap data for item $i and $i - 1
   EndIf
   If $k > -1 Then
    $j = $aIdxLVI[$i]
    $aIdxLVI[$i] = $aIdxLVI[$k]
    $aIdxLVI[$k] = $j
    GUICtrlSetData( $aIdLVI[$i], $aDataLVI[$aIdxLVI[$i]] )
    GUICtrlSetData( $aIdLVI[$k], $aDataLVI[$aIdxLVI[$k]] )
   EndIf
  EndIf
ElseIf $wParam = $WM_KEYUP Then
  $vkCode = DllStructGetData( $tKEYHOOKS, "vkCode" )
  if ( $vkCode = $VK_LSHIFT ) Or ( $vkCode = $VK_RSHIFT ) Then $fSHIFT = 0
EndIf
Return _WinAPI_CallNextHookEx( $handleHookProc, $nCode, $wParam, $lParam )
EndFunc
Func UnHook()
_WinAPI_UnhookWindowsHookEx( $handleHookProc )
DllCallbackFree( $hHookProc )
EndFunc

LarsJ

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×