By subclassing. Using this example, you can use a default subclassproc or pass an own subclassproc when registering the control.
Code: Select all
#Requires AutoHotkey v2.0
Win := Gui( , "LV WantReturn")
Win.OnEvent("Close", (*) => ExitApp())
Win.AddText("xm", "ListView:")
LV := Win.AddListView("xm y+5 w400 r5 -ReadOnly", ["Column 1" , "Column 2"])
LV.OnNotify(-4, LV_NM_RETURN)
LV_TV_WantReturnSC.Register(LV) ; register the LV
Loop 5
LV.Add("", "Row " . A_Index . " Column 1", "Row " . A_Index . " Column 1")
LV.ModifyCol()
Win.AddText("xm", "TreeView:")
TV := Win.AddTreeView("xm y+5 w400 r6 -ReadOnly")
TV.OnNotify(-4, TV_NM_RETURN)
LV_TV_WantReturnSC.Register(TV, TV_SubClassProc) ; register an own subclassproc for the TV
Win.AddText("xm", "Edit:")
EDT := Win.AddEdit("xm y+5 w400 r3")
Win.AddText("xm", "Listbox:")
LB := Win.AddListBox("xm y+5 w400 r3", [1, 2, 3])
BTN := Win.AddButton("w400 +Default", "Default Button")
BTN.OnEvent("Click", (*) => MsgBox("Button clicked!"))
Win.Show()
; ----------------------------------------------------------------------------------------------------------------------
LV_NM_RETURN(LV, *) {
MsgBox("Enter was pressed on registered ListView!")
}
; ----------------------------------------------------------------------------------------------------------------------
TV_NM_RETURN(LV, *) {
MsgBox("Enter was pressed on registered TreeView!")
}
; ----------------------------------------------------------------------------------------------------------------------
TV_SubClassProc(HWND, Msg, wParam, lParam, ID, Data) {
Static NMHDR := Buffer(24, 0) ; NMHDR structure 64-bit
Static NM_RETURN := -4
Switch Msg {
Case 135: ; WM_GETDLGCODE (0x0087)
If (wParam = 13) ; VK_RETURN
Return 4 ; DLGC_WANTALLKEYS
Case 256: ; WM_KEYDOWN (0x0100)
If (wParam = 13) { ; VK_RETURN
If !(lParam & 0x40000000) { ; not auto-repetition
Local Ctl := GuiCtrlFromHwnd(Hwnd)
Local CID := GetDlgCtrlID(Hwnd)
NumPut("Ptr", HWND, "Ptr", CID, "Ptr", NM_RETURN, NMHDR)
PostMessage(0x004E, CID, NMHDR.Ptr, Ctl.Gui.Hwnd) ; WM_NOTIFY
}
Return 0
}
Case 2: ; WM_DESTROY (0x0002)
DllCall("RemoveWindowSubclass", "Ptr", HWND, "Ptr", Data, "UPtr", Hwnd)
}
Return DllCall("DefSubclassProc", "Ptr", HWND, "UInt", Msg, "Ptr", wParam, "Ptr", lParam, "Ptr")
; -------------------------------------------------------------------------------------------------------------------
GetDlgCtrlID(Hwnd) => DllCall("GetDlgCtrlID", "Ptr", Hwnd, "Int")
}
; ======================================================================================================================
; LV_TV_WantReturnSC (SubClassing)
; 'Fakes' Return key processing for ListView and Treeview controls which otherwise won't process it.
; If enabled, the control will receive a NM_RETURN (-4) notification whenever the Return key is pressed while
; the control has the focus.
; Usage:
; To register a control call the functions once and pass the Gui.Control object as the first parameter.
; To deregister it, call the function again with the same Gui.Control object as the first parameter.
; You may pass a function object in the second parameterto be used as subclassproc for the specified control.
; This function must accept 6 parameters. Look at the built-in SubClassProc method for further details.
; ----------------------------------------------------------------------------------------------------------------------
; NM_RETURN -> https://learn.microsoft.com/en-us/windows/win32/controls/nm-return-list-view-
; -> https://learn.microsoft.com/en-us/windows/win32/controls/nm-return-tree-view-
; WM_KEYDOWN -> https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-keydown
; ======================================================================================================================
Class LV_TV_WantReturnSC {
Static Ctrls := Map()
Static SCProc := CallbackCreate(ObjBindMethod(LV_TV_WantReturnSC, "SubClassProc"), , 6)
; -------------------------------------------------------------------------------------------------------------------
Static Register(CtrlObj, SubClassProc?) {
If (Type(CtrlObj) = "Gui.ListView") || (Type(CtrlObj) = "Gui.TreeView") {
Local Hwnd := CtrlObj.Hwnd, SCP := 0
If This.Ctrls.Has(Hwnd) { ; the control is already registered, remove it
DllCall("RemoveWindowSubclass", "Ptr", Hwnd, "Ptr", This.Ctrls[Hwnd].SCP, "UPtr", Hwnd, "Int")
This.Ctrls.Delete(Hwnd)
Return True
}
SCP := IsSet(SubClassProc) && IsObject(SubClassProc) ? CallbackCreate(SubClassProc, , 6) : This.SCProc
This.Ctrls[CtrlObj.Hwnd] := {CID: This.GetDlgCtrlID(Hwnd), HGUI: CtrlObj.Gui.Hwnd, SCP: SCP}
Return DllCall("SetWindowSubclass", "Ptr", Hwnd, "Ptr", SCP, "Ptr", Hwnd, "Ptr", SCP, "UInt")
}
Return False
}
; -------------------------------------------------------------------------------------------------------------------
Static SubClassProc(HWND, Msg, wParam, lParam, ID, Data) {
Static NMHDR := Buffer(24, 0) ; NMHDR structure 64-bit
Static NM_RETURN := -4
Switch Msg {
Case 135: ; WM_GETDLGCODE (0x0087)
If (wParam = 13) ; VK_RETURN
Return 4 ; DLGC_WANTALLKEYS
Case 256: ; WM_KEYDOWN (0x0100)
If (wParam = 13) { ; VK_RETURN
Local Ctl := This.Ctrls[Hwnd]
If !(lParam & 0x40000000) { ; not auto-repetition
NumPut("Ptr", HWND, "Ptr", Ctl.CID, "Ptr", NM_RETURN, NMHDR)
PostMessage(0x004E, Ctl.CID, NMHDR.Ptr, Ctl.HGUI) ; WM_NOTIFY
}
Return 0
}
Case 2: ; WM_DESTROY (0x0002)
DllCall("RemoveWindowSubclass", "Ptr", HWND, "Ptr", Data, "UPtr", Hwnd)
}
Return DllCall("DefSubclassProc", "Ptr", HWND, "UInt", Msg, "Ptr", wParam, "Ptr", lParam, "Ptr")
}
; -------------------------------------------------------------------------------------------------------------------
Static GetDlgCtrlID(Hwnd) => DllCall("GetDlgCtrlID", "Ptr", Hwnd, "Int")
}