Sign in to follow this  
Followers 0
ripdad

Menu to ListviewItem Control

5 posts in this topic

This is a simplified example of something I've been experimenting with.

Perhaps it has been done before. I'm sure this could be done better.

Benefits:

- Set a specific "menu group" to a specific listview item control.

- Menus won't activate, unless a control is assigned a menu group.

Side Benefits:

-> No menu on listview description bar.

-> No menu on listview item group labels.

-> No menu on white space

Now, what I'd like to be able to do is make a "menu group" a "module" and then

attach that module to a listview item control.

This way, I only have to get each menu group once. (stored as a control?)

I tried it with a dummy control. I couldn't make it work.

Any ideas would be appreciated.

Opt('MustDeclareVars', 1)
Opt('GUIOnEventMode', 1)
;
Local $gui = GUICreate('Example - SetMenu2LvItemCtrl', 410, 310, -1, -1)
Local $Lv = GUICtrlCreateListView('List of Items', 5, 5, 400, 300)
GUICtrlSendMsg($Lv, 0x101E, 0, 396)
GUISetOnEvent(-3, '_AllExit')
;
_Set_Menus()
GUISetState(@SW_SHOW, $gui)
;
While 1
    Sleep(1000)
WEnd
;
Func _AllExit()
    GUIDelete($gui)
    Exit
EndFunc
;
Func _Set_Menus()
    ; ========================================================
    Local $hLvi = GUICtrlCreateListViewItem('Label One', $Lv); set group label (no menu assigned)
    GUICtrlSetBkColor($hLvi, 0xC0C0C0); set color for label
    GUICtrlSetState($hLvi, 128);$GUI_DISABLE = 128
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        Menu1_SetMenu2LvItemCtrl($hLvi); assign menu to this listview item control
    Next
    ; ========================================================
    $hLvi = GUICtrlCreateListViewItem('Label Two', $Lv)
    GUICtrlSetBkColor($hLvi, 0xC0C0C0)
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        Menu2_SetMenu2LvItemCtrl($hLvi)
    Next
    ; ========================================================
    $hLvi = GUICtrlCreateListViewItem('Label Three', $Lv)
    GUICtrlSetBkColor($hLvi, 0xC0C0C0)
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        Menu3_SetMenu2LvItemCtrl($hLvi)
    Next
EndFunc
;
Func Menu1_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu1 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu1 - Menu Item2', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $c = GUICtrlCreateMenuItem('Menu1 - Menu Item3', $h)
    Local $d = GUICtrlCreateMenuItem('Menu1 - Menu Item4', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $e = GUICtrlCreateMenuItem('Menu1 - Menu Item5', $h)
    Local $f = GUICtrlCreateMenuItem('Menu1 - Menu Item6', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $g = GUICtrlCreateMenuItem('Menu1 - Menu Item7', $h)
    GUICtrlSetOnEvent($a, '_Function1')
    GUICtrlSetOnEvent($b, '_Function2')
    GUICtrlSetOnEvent($c, '_Function3')
    GUICtrlSetOnEvent($d, '_Function4')
    GUICtrlSetOnEvent($e, '_Function5')
    GUICtrlSetOnEvent($f, '_Function6')
    GUICtrlSetOnEvent($g, '_Function7')
EndFunc
;
Func Menu2_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu2 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu2 - Menu Item2', $h)
    GUICtrlSetOnEvent($a, '_Function1')
    GUICtrlSetOnEvent($b, '_Function8')
EndFunc
;
Func Menu3_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu3 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu3 - Menu Item2', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $c = GUICtrlCreateMenuItem('Menu3 - Menu Item3', $h)
    Local $d = GUICtrlCreateMenuItem('Menu3 - Menu Item4', $h)
    GUICtrlSetOnEvent($a, '_Function2')
    GUICtrlSetOnEvent($b, '_Function4')
    GUICtrlSetOnEvent($c, '_Function9')
    GUICtrlSetOnEvent($d, '_Function3')
EndFunc
;
Func _Function1()
    MsgBox(0,'','_Function1()')
EndFunc
;
Func _Function2()
    MsgBox(0,'','_Function2()')
EndFunc
;
Func _Function3()
    MsgBox(0,'','_Function3()')
EndFunc
;
Func _Function4()
    MsgBox(0,'','_Function4()')
EndFunc
;
Func _Function5()
    MsgBox(0,'','_Function5()')
EndFunc
;
Func _Function6()
    MsgBox(0,'','_Function6()')
EndFunc
;
Func _Function7()
    MsgBox(0,'','_Function7()')
EndFunc
;
Func _Function8()
    MsgBox(0,'','_Function8()')
EndFunc
;
Func _Function9()
    MsgBox(0,'','_Function9()')
EndFunc
;

Make yourself sheep and the wolves will eat you - Benjamin Franklin

Share this post


Link to post
Share on other sites



This is a simplified example of something I've been experimenting with.

Perhaps it has been done before. I'm sure this could be done better.

Benefits:

- Set a specific "menu group" to a specific listview item control.

- Menus won't activate, unless a control is assigned a menu group.

Side Benefits:

-> No menu on listview description bar.

-> No menu on listview item group labels.

-> No menu on white space

Now, what I'd like to be able to do is make a "menu group" a "module" and then

attach that module to a listview item control.

This way, I only have to get each menu group once. (stored as a control?)

I tried it with a dummy control. I couldn't make it work.

Any ideas would be appreciated.

you should use the listview groups feature and set group membership for each item

native listview items have their pseudo control ID stored in the items param

find the index of the item you want to set a menu to and get the control ID for the

items menu with _GUICtrlListView_GetItemParam()

(listview items are not controls, they only have an index and if set, a command ID that can be used to track items in a sorted listview)

this example shows how you could use the groups feature instead of an item as a group label

and sets a listview item to a menu of choice by getting the native listview item pseudo control ID

you cannot use this with UDF created items, either stick with GUICtrlCreateListViewItem() or _GUICtrlListView_AddItem), _GUICtrlListView_AddSubItem() and _GUICtrlListView_InsertItem()

but never both at the same time.

#Include <GuiListView.au3>

Opt('MustDeclareVars', 1)
Opt('GUIOnEventMode', 1)
;
Local $gui = GUICreate('Example - SetMenu2LvItemCtrl', 410, 460, -1, -1)
Local $Lv = GUICtrlCreateListView('List of Items', 5, 5, 400, 450)
GUICtrlSendMsg($Lv, 0x101E, 0, 396)
_GUICtrlListView_EnableGroupView($Lv)
GUISetOnEvent(-3, '_AllExit')
;

_Set_Menus()
GUISetState(@SW_SHOW, $gui)


;set last item in Group 4 to X menu
Local $hLvi = GUICtrlCreateListViewItem('ITEM X', $Lv)
_GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv)-1, 4) ;set index of item to group 4 membership
MenuX_SetMenu2LvItemCtrl(_GUICtrlListView_GetItemParam($Lv, _GUICtrlListView_GetItemCount($Lv)-1)) ;get ID of item and set menu


While 1
    Sleep(1000)
WEnd
;
Func _AllExit()
    GUIDelete($gui)
    Exit
EndFunc
;
Func _Set_Menus()
    ; ========================================================
    Local $hLvi
    ;Local $hLvi = GUICtrlCreateListViewItem('Label One', $Lv); set group label (no menu assigned)
    ;GUICtrlSetBkColor($hLvi, 0xC0C0C0); set color for label
    ;GUICtrlSetState($hLvi, 128);$GUI_DISABLE = 128
    _GUICtrlListView_InsertGroup($Lv, 0, 1, "Group 1")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv)-1, 1)
        Menu1_SetMenu2LvItemCtrl($hLvi); assign menu to this listview item control
    Next
    ; ========================================================
    ;$hLvi = GUICtrlCreateListViewItem('Label Two', $Lv)
    ;GUICtrlSetBkColor($hLvi, 0xC0C0C0)
    _GUICtrlListView_InsertGroup($Lv, _GUICtrlListView_GetItemCount($Lv)-1, 2, "Group 2")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv)-1, 2)
        Menu2_SetMenu2LvItemCtrl($hLvi)
    Next
    ; ========================================================
    ;$hLvi = GUICtrlCreateListViewItem('Label Three', $Lv)
    ;GUICtrlSetBkColor($hLvi, 0xC0C0C0)
    _GUICtrlListView_InsertGroup($Lv, _GUICtrlListView_GetItemCount($Lv)-1, 3, "Group 3")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv)-1, 3)
        Menu3_SetMenu2LvItemCtrl($hLvi)
    Next

    ;Create Group 4 "x"
    _GUICtrlListView_InsertGroup($Lv, _GUICtrlListView_GetItemCount($Lv)-1, 4, "Group X")

EndFunc
;
Func Menu1_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu1 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu1 - Menu Item2', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $c = GUICtrlCreateMenuItem('Menu1 - Menu Item3', $h)
    Local $d = GUICtrlCreateMenuItem('Menu1 - Menu Item4', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $e = GUICtrlCreateMenuItem('Menu1 - Menu Item5', $h)
    Local $f = GUICtrlCreateMenuItem('Menu1 - Menu Item6', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $g = GUICtrlCreateMenuItem('Menu1 - Menu Item7', $h)
    GUICtrlSetOnEvent($a, '_Function1')
    GUICtrlSetOnEvent($b, '_Function2')
    GUICtrlSetOnEvent($c, '_Function3')
    GUICtrlSetOnEvent($d, '_Function4')
    GUICtrlSetOnEvent($e, '_Function5')
    GUICtrlSetOnEvent($f, '_Function6')
    GUICtrlSetOnEvent($g, '_Function7')
EndFunc
;
Func Menu2_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu2 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu2 - Menu Item2', $h)
    GUICtrlSetOnEvent($a, '_Function1')
    GUICtrlSetOnEvent($b, '_Function8')
EndFunc
;
Func Menu3_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu3 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu3 - Menu Item2', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $c = GUICtrlCreateMenuItem('Menu3 - Menu Item3', $h)
    Local $d = GUICtrlCreateMenuItem('Menu3 - Menu Item4', $h)
    GUICtrlSetOnEvent($a, '_Function2')
    GUICtrlSetOnEvent($b, '_Function4')
    GUICtrlSetOnEvent($c, '_Function9')
    GUICtrlSetOnEvent($d, '_Function3')
EndFunc

Func MenuX_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('MenuX - Menu Item1', $h)
    GUICtrlSetOnEvent($a, '_FunctionX')
EndFunc


;
Func _Function1()
    MsgBox(0,'','_Function1()')
EndFunc
;
Func _Function2()
    MsgBox(0,'','_Function2()')
EndFunc
;
Func _Function3()
    MsgBox(0,'','_Function3()')
EndFunc
;
Func _Function4()
    MsgBox(0,'','_Function4()')
EndFunc
;
Func _Function5()
    MsgBox(0,'','_Function5()')
EndFunc
;
Func _Function6()
    MsgBox(0,'','_Function6()')
EndFunc
;
Func _Function7()
    MsgBox(0,'','_Function7()')
EndFunc
;
Func _Function8()
    MsgBox(0,'','_Function8()')
EndFunc
;
Func _Function9()
    MsgBox(0,'','_Function9()')
EndFunc
;
Func _FunctionX()
    MsgBox(0,'','_FunctionX()')
EndFunc

I see fascists...

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

OK I misunderstood you initially, I think this is what you want.

A variation on the example for GUICtrlCreateContextMenu(), but using Groups

Edit: some additional error checking and example of a group without a menu added

#include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiMenu.au3>

Opt('MustDeclareVars', 1)
Opt('GUIOnEventMode', 1)
;
Local $gui = GUICreate('Example - SetMenu2LvItemCtrl', 410, 400, -1, -1)
Local $Lv = GUICtrlCreateListView('List of Items', 5, 5, 400, 390)
GUICtrlSendMsg($Lv, 0x101E, 0, 396)
_GUICtrlListView_EnableGroupView($Lv)
GUISetOnEvent(-3, '_AllExit')
;
;create as many context menus set to a dummy control placeholder as you need
Local $aMenu[4] ;array for storing group menu handles
Local $cMenu1 = GUICtrlCreateDummy()
Local $cMenu2 = GUICtrlCreateDummy()
$aMenu[1] = Menu1_SetMenu2LvItemCtrl($cMenu1)
$aMenu[2] = Menu2_SetMenu2LvItemCtrl($cMenu2)
$aMenu[3] = 0
$aMenu[0] = 2

_Set_Items();create listview items and set each item to group 1 or 2 membership

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")
GUISetState(@SW_SHOW, $gui)


While 1
    Sleep(1000)
WEnd
;
Func _AllExit()
    GUIDelete($gui)
    Exit
EndFunc   ;==>_AllExit
;
Func _Set_Items()
    ; ========================================================
    Local $hLvi
    _GUICtrlListView_InsertGroup($Lv, 0, 1, "Group 1")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 1)
    Next
    ; ========================================================
    _GUICtrlListView_InsertGroup($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 2, "Group 2")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 2)
    Next
    ; ========================================================
    _GUICtrlListView_InsertGroup($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 3, "Group 3")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 3)
    Next
    ; ========================================================
EndFunc   ;==>_Set_Items
;

Func _WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $wParam
    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Local $IDFrom = DllStructGetData($tNMHDR, "IDFrom")

    Switch $IDFrom
        Case $Lv
            Switch $iCode
                Case $NM_RCLICK ; determine if right click on an item
                    Local $tInfox = DllStructCreate($tagNMITEMACTIVATE, $lParam)
                    If @error Then Return $GUI_RUNDEFMSG
                    Local $Item = DllStructGetData($tInfox, "Index")
                    If @error Or $Item = -1 Then Return $GUI_RUNDEFMSG

                    Local $tTest = DllStructCreate($tagLVHITTESTINFO)
                    Local $x = DllStructGetData($tInfox, "X") ; X
                    Local $y = DllStructGetData($tInfox, "Y") ; Y
                    DllStructSetData($tTest, "X", $x)
                    DllStructSetData($tTest, "Y", $y)
                    Local $iRet = GUICtrlSendMsg($IDFrom, $LVM_HITTEST, 0, DllStructGetPtr($tTest))
                    If @error Or $iRet = -1 Then Return $GUI_RUNDEFMSG ; -1 = not on lv item, otherwise returns index
                    Switch DllStructGetData($tTest, "Flags")
                        Case $LVHT_ONITEMICON, $LVHT_ONITEMLABEL, $LVHT_ONITEM ;hit was on item icon or 1st row or subitem
                            ;get the items group membership ID
                            Local $iGroupID = _GUICtrlListView_GetItemGroupID($IDFrom, $Item)
                            If @error Or $iGroupID < 0 Then Return $GUI_RUNDEFMSG
                            ;pop the menu for the group membership ID
                            If $iGroupID > UBound($aMenu)-1 Then Return $GUI_RUNDEFMSG
                            If $aMenu[$iGroupID] <> 0 And _GUICtrlMenu_IsMenu($aMenu[$iGroupID]) = 1 Then
                                Local $tpoint = DllStructCreate("int X;int Y")
                                DllStructSetData($tpoint, "X", $x)
                                DllStructSetData($tpoint, "Y", $y)
                                ;convert hittest coordinates to screen coordinates for context menu
                                _WinAPI_ClientToScreen($hWndFrom, $tpoint)
                                ;$iSubItem = DllStructGetData($tInfox, "SubItem")
                                _GUICtrlMenu_TrackPopupMenu($aMenu[$iGroupID], $hWnd, DllStructGetData($tpoint, "X"), DllStructGetData($tpoint, "Y"), 1, 1, 1)
                            EndIf
                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_NOTIFY



Func Menu1_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu1 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu1 - Menu Item2', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $c = GUICtrlCreateMenuItem('Menu1 - Menu Item3', $h)
    Local $d = GUICtrlCreateMenuItem('Menu1 - Menu Item4', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $e = GUICtrlCreateMenuItem('Menu1 - Menu Item5', $h)
    Local $f = GUICtrlCreateMenuItem('Menu1 - Menu Item6', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $g = GUICtrlCreateMenuItem('Menu1 - Menu Item7', $h)
    GUICtrlSetOnEvent($a, '_Function1')
    GUICtrlSetOnEvent($b, '_Function2')
    GUICtrlSetOnEvent($c, '_Function3')
    GUICtrlSetOnEvent($d, '_Function4')
    GUICtrlSetOnEvent($e, '_Function5')
    GUICtrlSetOnEvent($f, '_Function6')
    GUICtrlSetOnEvent($g, '_Function7')
    Return GUICtrlGetHandle($h)
EndFunc   ;==>Menu1_SetMenu2LvItemCtrl
;
Func Menu2_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu2 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu2 - Menu Item2', $h)
    GUICtrlSetOnEvent($a, '_Function1')
    GUICtrlSetOnEvent($b, '_Function8')
    Return GUICtrlGetHandle($h)
EndFunc   ;==>Menu2_SetMenu2LvItemCtrl
;

;
Func _Function1()
    MsgBox(0, '', '_Function1()')
EndFunc   ;==>_Function1
;
Func _Function2()
    MsgBox(0, '', '_Function2()')
EndFunc   ;==>_Function2
;
Func _Function3()
    MsgBox(0, '', '_Function3()')
EndFunc   ;==>_Function3
;
Func _Function4()
    MsgBox(0, '', '_Function4()')
EndFunc   ;==>_Function4
;
Func _Function5()
    MsgBox(0, '', '_Function5()')
EndFunc   ;==>_Function5
;
Func _Function6()
    MsgBox(0, '', '_Function6()')
EndFunc   ;==>_Function6
;
Func _Function7()
    MsgBox(0, '', '_Function7()')
EndFunc   ;==>_Function7
;
Func _Function8()
    MsgBox(0, '', '_Function8()')
EndFunc   ;==>_Function8
Edited by rover

I see fascists...

Share this post


Link to post
Share on other sites

rover,

Thanks for your time and examples. That will give me plenty to work with.


Make yourself sheep and the wolves will eat you - Benjamin Franklin

Share this post


Link to post
Share on other sites

ripdad

One more thing I would like to add if you or anyone else is interested.

The code I use for my listview contextmenus differs slightly from what I posted.

I use a WM_CONTEXTMENU handler for _GUICtrlMenu_TrackPopupMenu()

This way the NM_RCLICK notification returns immediately, and the WM_CONTEXTMENU handler,

has the blocking function TrackPopupMenu().

WM_CONTEXTMENU also has the screen coordinates, eliminating the need for _WinAPI_ClientToScreen().

This revised and more efficient version splits the menu between WM_CONTEXTMENU and WM_NOTIFY,

and has the advantage of getting the selected lv item and the client coordinates for the hittest

from the WM_NOTIFY NMITEMACTIVATE struct, and the screen coordinates for _GUICtrlMenu_TrackPopupMenu()

from WM_CONTEXTMENU lParam.

This can also be done entirely in the WM_CONTEXTMENU handler, but it requires

extra dllcalls (SendMessage() for getting the selected lv item and _WinAPI_ScreenToClient() for the hittest coordinates.

Addendum:

I never put listview contextmenu Appkey/Shift-F10 support in my code, so I've worked it out for my own use and added it here.

So, more code ends up in the WM_CONTEXTMENU handler after all...

You can remove the WM_SYSCOMMAND handler and the WM_CONTEXTMENU keyboard navigation code

if you don't require Appkey/Shift-F10 support or care about possible use

of shift-f10 on a listview item. *** (see notes in code) -remove the code in section below "If $lParam = -1 Then" ;Menu Appkey or Shift-F10

#include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiMenu.au3>

Opt('MustDeclareVars', 1)
Opt('GUIOnEventMode', 1)

Local $iGroupID = -1, $fSysMenu = True, $hLv
Local $gui = GUICreate('Example - SetMenu2LvItemCtrl', 410, 450, -1, -1)
Local $Lv = GUICtrlCreateListView('List of Items', 5, 5, 400, 390)
$hLv = GUICtrlGetHandle($Lv)
GUICtrlSendMsg($Lv, 0x101E, 0, 396)
_GUICtrlListView_EnableGroupView($Lv)
GUISetOnEvent(-3, '_AllExit')
;
;create as many context menus set to a dummy control placeholder as you need
Local $aMenu[4] ;array for storing group menu handles
Local $cMenu1 = GUICtrlCreateDummy()
Local $cMenu2 = GUICtrlCreateDummy()
$aMenu[1] = Menu1_SetMenu2LvItemCtrl($cMenu1)
$aMenu[2] = Menu2_SetMenu2LvItemCtrl($cMenu2)
$aMenu[3] = 0
$aMenu[0] = 2

_Set_Items();create listview items and set each item to group 1 or 2 membership

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")
GUIRegisterMsg($WM_CONTEXTMENU, "_WM_CONTEXTMENU")
GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND")
GUISetState(@SW_SHOW, $gui)

GUICtrlCreateButton("", 5, 410, 80, 25)
;***
;button added to allow changing focus with tab to demonstrate fix for annoying windows feature.
;the system menu will capture the keyboard focus from the listview
;when shift-f10 is used on an item without a contextmenu.

;when scrolling through the listview items with the arrow keys and using shift-f10
;instead of the menu appkey to pop up the selected items contextmenu, the system menu will be activated if
;the item does not have a contextmenu, this is standard windows behaviour.
;when the arrow key is next moved after using shift-f10 on an item without a contextmenu,
;the system menu will pop up and capture the keyboard.

;this behaviour can be changed by setting a flag when an item does not have a contextmenu
;and in WM_SYSCOMMAND check for the $SC_KEYMENU command, reset the flag and return zero.


While 1
    Sleep(1000)
WEnd
;
Func _AllExit()
    GUIDelete($gui)
    Exit
EndFunc   ;==>_AllExit
;
Func _Set_Items()
    ; ========================================================
    Local $hLvi
    _GUICtrlListView_InsertGroup($Lv, 0, 1, "Group 1")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 1)
    Next
    ; ========================================================
    _GUICtrlListView_InsertGroup($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 2, "Group 2")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 2)
    Next
    ; ========================================================
    _GUICtrlListView_InsertGroup($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 3, "Group 3")
    For $i = 1 To 5
        $hLvi = GUICtrlCreateListViewItem('ITEM ' & $i, $Lv)
        _GUICtrlListView_SetItemGroupID($Lv, _GUICtrlListView_GetItemCount($Lv) - 1, 3)
    Next
    ; ========================================================
EndFunc   ;==>_Set_Items
;

Func _WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $wParam
    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Local $IDFrom = DllStructGetData($tNMHDR, "IDFrom")

    Switch $IDFrom
        Case $Lv
            Switch $iCode
                Case $NM_RCLICK ; determine if right click on an item
                    $iGroupID = -1 ;reset global ID
                    Local $tInfox = DllStructCreate($tagNMITEMACTIVATE, $lParam)
                    If @error Then Return $GUI_RUNDEFMSG
                    Local $Item = DllStructGetData($tInfox, "Index")
                    If @error Or $Item = -1 Then Return $GUI_RUNDEFMSG

                    Local $tTest = DllStructCreate($tagLVHITTESTINFO)
                    DllStructSetData($tTest, "X", DllStructGetData($tInfox, "X"))
                    DllStructSetData($tTest, "Y", DllStructGetData($tInfox, "Y"))
                    Local $iRet = GUICtrlSendMsg($IDFrom, $LVM_HITTEST, 0, DllStructGetPtr($tTest))
                    If @error Or $iRet = -1 Then Return $GUI_RUNDEFMSG ; -1 = not on lv item, otherwise returns index
                    Switch DllStructGetData($tTest, "Flags")
                        Case $LVHT_ONITEMICON, $LVHT_ONITEMLABEL, $LVHT_ONITEM ;hit was on item icon or 1st row or subitem
                            ;get the items group membership ID
                            ;(stripped down version of _GUICtrlListView_GetItemGroupID() - several dllcalls removed)
                            Local $tItem = DllStructCreate($tagLVITEM)
                            DllStructSetData($tItem, "Mask", $LVIF_GROUPID)
                            DllStructSetData($tItem, "Item", $Item)
                            Local $iRet = GUICtrlSendMsg($IDFrom, $LVM_GETITEMW, 0, DllStructGetPtr($tItem))
                            If @error Or $iRet <> 1 Then
                                $iGroupID = -1
                            Else
                                $iGroupID = DllStructGetData($tItem, "GroupID")
                                If $iGroupID < 0 Then $iGroupID = -1
                            EndIf
                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_NOTIFY


;fix for system menu focus stealing from the listview with Shift-F10
;on lv items without a contextmenu
Func _WM_SYSCOMMAND($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    ;SC_KEYMENU = 0xF100
    If $wParam = $SC_KEYMENU And $fSysMenu = False Then
        $fSysMenu = True
        Return 0
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_CONTEXTMENU


Func _WM_CONTEXTMENU($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Switch $wParam
        Case $hLv ;bypass other contextmenus
            ;If $lParam = -1 Then Return $GUI_RUNDEFMSG ;option: ignore menu appkey/Shift-F10
            Local $iX, $iY, $aSel, $aPos, $iIdx, $tpoint
            If $lParam = -1 Then ;Menu Appkey/Shift-F10
                ;get last selected item (if one or more selected by keyboard))
                $aSel = _GUICtrlListView_GetSelectedIndices($wParam, True)
                If @error Or UBound($aSel) <= 1 Then Return $GUI_RUNDEFMSG
                If $aSel[$aSel[0]] = -1 Then Return $GUI_RUNDEFMSG
                $iIdx = $aSel[$aSel[0]]
                ;get group ID
                Local $tItem = DllStructCreate($tagLVITEM)
                DllStructSetData($tItem, "Mask", $LVIF_GROUPID)
                DllStructSetData($tItem, "Item", $iIdx)
                Local $iRet = _SendMessage($wParam, $LVM_GETITEMW, 0, DllStructGetPtr($tItem), 0, "wparam", "ptr")
                If @error Or $iRet <> 1 Then
                    $iGroupID = -1
                Else
                    $iGroupID = DllStructGetData($tItem, "GroupID")
                    If $iGroupID < 0 Then $iGroupID = -1
                EndIf
                If $iGroupID <> -1 Then
                    $aPos = _GUICtrlListView_GetItemPosition($wParam, $iIdx)
                    $tpoint = DllStructCreate("int X;int Y")
                    DllStructSetData($tpoint, "X", $aPos[0])
                    DllStructSetData($tpoint, "Y", $aPos[1])
                    _WinAPI_ClientToScreen($wParam, $tPoint)
                    $iX = DllStructGetData($tpoint, "X")
                    $iY = DllStructGetData($tpoint, "Y")
                EndIf
            Else
                $iX = BitAND($lParam, 0x0000FFFF)
                $iY = BitShift($lParam, 16)
            EndIf

            If $iGroupID = -1 Or $iGroupID > (UBound($aMenu) - 1) Then Return $GUI_RUNDEFMSG ;failed hittests on listview
            If $iX >= 0 And $iY >= 0 Then
                ;pop the menu for the group membership ID
                If $aMenu[$iGroupID] <> 0 And _GUICtrlMenu_IsMenu($aMenu[$iGroupID]) = 1 Then
                    _GUICtrlMenu_TrackPopupMenu($aMenu[$iGroupID], $hWnd, $iX, $iY, 1, 1, 1)
                    $iGroupID = -1
                    Return True
                Else
                    $fSysMenu = False
                EndIf
            EndIf
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_CONTEXTMENU


Func Menu1_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu1 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu1 - Menu Item2', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $c = GUICtrlCreateMenuItem('Menu1 - Menu Item3', $h)
    Local $d = GUICtrlCreateMenuItem('Menu1 - Menu Item4', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $e = GUICtrlCreateMenuItem('Menu1 - Menu Item5', $h)
    Local $f = GUICtrlCreateMenuItem('Menu1 - Menu Item6', $h)
    GUICtrlCreateMenuItem('', $h)
    Local $g = GUICtrlCreateMenuItem('Menu1 - Menu Item7', $h)
    GUICtrlSetOnEvent($a, '_Function1')
    GUICtrlSetOnEvent($b, '_Function2')
    GUICtrlSetOnEvent($c, '_Function3')
    GUICtrlSetOnEvent($d, '_Function4')
    GUICtrlSetOnEvent($e, '_Function5')
    GUICtrlSetOnEvent($f, '_Function6')
    GUICtrlSetOnEvent($g, '_Function7')
    Return GUICtrlGetHandle($h)
EndFunc   ;==>Menu1_SetMenu2LvItemCtrl
;
Func Menu2_SetMenu2LvItemCtrl($LvI)
    Local $h = GUICtrlCreateContextMenu($LvI)
    Local $a = GUICtrlCreateMenuItem('Menu2 - Menu Item1', $h)
    Local $b = GUICtrlCreateMenuItem('Menu2 - Menu Item2', $h)
    GUICtrlSetOnEvent($a, '_Function1')
    GUICtrlSetOnEvent($b, '_Function8')
    Return GUICtrlGetHandle($h)
EndFunc   ;==>Menu2_SetMenu2LvItemCtrl
;

;
Func _Function1()
    MsgBox(0, '', '_Function1()')
EndFunc   ;==>_Function1
;
Func _Function2()
    MsgBox(0, '', '_Function2()')
EndFunc   ;==>_Function2
;
Func _Function3()
    MsgBox(0, '', '_Function3()')
EndFunc   ;==>_Function3
;
Func _Function4()
    MsgBox(0, '', '_Function4()')
EndFunc   ;==>_Function4
;
Func _Function5()
    MsgBox(0, '', '_Function5()')
EndFunc   ;==>_Function5
;
Func _Function6()
    MsgBox(0, '', '_Function6()')
EndFunc   ;==>_Function6
;
Func _Function7()
    MsgBox(0, '', '_Function7()')
EndFunc   ;==>_Function7
;
Func _Function8()
    MsgBox(0, '', '_Function8()')
EndFunc   ;==>_Function8

I see fascists...

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  
Followers 0