#include <GuiListView.au3>
#include <GUIConstants.au3>
Global Const $sIID_IOwnerDataCallback = '{44C09D56-8D3B-419D-A462-7B956B105B47}'
Global Const $dtag_IOwnerDataCallback = _
"GetItemPosition hresult(int;ptr*);" & _ ; int itemIndex, LPPOINT pPosition
"SetItemPosition hresult(int;ptr);" & _ ; int itemIndex POINT position
"GetItemInGroup hresult(int;int;ptr*);" & _ ;int groupIndex int groupWideItemIndex PINT pTotalItemIndex
"GetItemGroup hresult(int;int;ptr*;);" & _ ;int itemIndex,int occurenceIndex, PINT pGroupIndex
"GetItemGroupCount hresult(int;ptr*);" & _ ;
"OnCacheHint hresult(int;int);" ;LVITEMINDEX firstItem ;LVITEMINDEX lastItem
Global Const $sIID_IOleWindow = '{00000114-0000-0000-C000-000000000046}'
Global Const $dtag_IOleWindow = _
"GetWindow hresult(hwnd*);" & _ ; Gets a window handle.
"ContextSensitiveHelp hresult(int);" ; Controls enabling of context-sensitive help.
Global Const $sIID_IListView = '{BDD1F049-858B-11D1-B16A-00C0F0283628}'
;~ Global Const $sIID_IListView = '{F4D83600-895E-11D0-B0A6-000000000000}'
Global Const $dtag_IListView = $dtag_IOleWindow & _
"GetImageList hresult();" ; ИТД, пока нету всех методов, т.к не работает
;~ {BDD1F049-858B-11D1-B16A-00C0F0283628}
;~ {F4D83600-895E-11D0-B0A6-000000000000}
Global Const $LVM_QUERYINTERFACE = $LVM_FIRST + 189
GUICreate("ListView Insert Group", 400, 300)
Global $idListview = GUICtrlCreateListView('', 10, 40, 300 - 20, 200 - 20, $LVS_OWNERDATA, BitOR($WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT))
Global $hLV = GUICtrlGetHandle($idListview)
_GUICtrlListView_AddColumn($hLV, 'Items', 250)
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState(@SW_SHOW)
;==========================
#1 Вариант http://www.geoffchappell.com/studies/windows/shell/comctl32/controls/listview/messages/queryinterface.htm
;~ Local Const $tRIID_IListView = _WinAPI_GUIDFromString($sIID_IListView)
;~ Local $pListView
;~ Local $aResult = _SendMessage ($hLV, $LVM_QUERYINTERFACE, $tRIID_IListView, 0, 5, 'struct*')
;~ If Not IsArray($aResult) Or Not $aResult[4] Then
;~ MsgBox(0, 'Ошибка', 'LVM_QUERYINTERFACE не возвратил указатель')
;~ Exit @ScriptLineNumber
;~ EndIf
;==========================
;==========================
#2 Вариант http://www.geoffchappell.com/studies/windows/shell/comctl32/controls/listview/interfaces/iownerdatacallback.htm?tx=25
Local $tEvent
Local $oEvent = __ObjectCreate("__vl_" & 'IOwnerDataCallback' & "_", $dtag_IOwnerDataCallback, $tEvent, False)
_SendMessage($hLV, 0x10BB, $oEvent())
;==========================
Local $iGroupID = 1
_GUICtrlListView_InsertGroup($idListview, -1, $iGroupID, "Group 1")
_GUICtrlListView_EnableGroupView($hLV)
Global $iItems = 1
GUICtrlSendMsg($idListview, $LVM_SETITEMCOUNT, $iItems, 0)
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
Exit
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
Local Static $tText = DllStructCreate('wchar[50]')
Local Static $pText = DllStructGetPtr($tText)
Local $tNMHDR, $hWndFrom, $iCode
$tNMHDR = DllStructCreate($tagNMHDR, $lParam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
$iCode = DllStructGetData($tNMHDR, 'Code')
Switch $hWndFrom
Case $hLV
Switch $iCode
Case $LVN_GETDISPINFOW
ConsoleWrite('$LVN_GETDISPINFOW' & @CRLF)
;~ Local $tNMLVDISPINFO = DllStructCreate($tagNMLVDISPINFO, $lParam)
;~
;~ If BitAND(DllStructGetData($tNMLVDISPINFO, 'Mask'), $LVIF_TEXT) Then
;~ Local $sItem = $aItems[DllStructGetData($tNMLVDISPINFO, 'Item')]
;~
;~ DllStructSetData($tText, 1, $sItem)
;~ DllStructSetData($tNMLVDISPINFO, 'Text', $pText)
;~ DllStructSetData($tNMLVDISPINFO, 'TextMax', StringLen($sItem))
;~
;~ ;Странно, но в структуре есть упоминание о группе, почему не реагирует?
;~ DllStructSetData($tNMLVDISPINFO, 'GroupID', 0)
;~ EndIf
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY
Func __ObjectCreate($sFunctionPrefix, $tagInterface, ByRef $tInterface, $fPrint = False, $bIsUnknown = Default, $sIID = "{00000000-0000-0000-C000-000000000046}") ; last param is IID_IUnknown by default
If $bIsUnknown = Default Then $bIsUnknown = True
Local $sInterface = $tagInterface ; copy interface description
Local $tagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _
"AddRef dword();" & _
"Release dword();"
; Adding IUnknown methods
If $bIsUnknown Then $tagInterface = $tagIUnknown & $tagInterface
; Below line is really simple even though it looks super complex. It's just written weird to fit in one line, not to steal your attention
Local $aMethods = StringSplit(StringReplace(StringReplace(StringReplace(StringReplace(StringTrimRight(StringReplace(StringRegExpReplace(StringRegExpReplace($tagInterface, "\w+\*", "ptr"), "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF), 1), "object", "idispatch"), "hresult", "long"), "bstr", "ptr"), "variant", "ptr"), @LF, 3)
Local $iUbound = UBound($aMethods)
Local $sMethod, $aSplit, $sNamePart, $aTagPart, $sTagPart, $sRet, $sParams, $hCallback
; Allocation
$tInterface = DllStructCreate("int RefCount;int Size;ptr Object;ptr Methods[" & $iUbound & "];int_ptr Callbacks[" & $iUbound & "];ulong_ptr Slots[16]") ; 16 pointer sized elements more to create space for possible private props
If @error Then Return SetError(1, 0, 0)
For $i = 0 To $iUbound - 1
$aSplit = StringSplit($aMethods[$i], "|", 2)
If UBound($aSplit) <> 2 Then ReDim $aSplit[2]
$sNamePart = $aSplit[0]
$sTagPart = $aSplit[1]
$sMethod = $sFunctionPrefix & $sNamePart
If $fPrint Then
Local $iPar = StringInStr($sTagPart, ";", 2), $t
If $iPar Then
$t = "Ret: " & StringLeft($sTagPart, $iPar - 1) & " " & _
"Par: " & StringRight($sTagPart, StringLen($sTagPart) - $iPar)
Else
$t = "Ret: " & $sTagPart
EndIf
Local $s = "Func " & $sMethod & _
"($pSelf) ; " & $t & @CRLF & _
"EndFunc" & @CRLF
ConsoleWrite($s)
EndIf
$aTagPart = StringSplit($sTagPart, ";", 2)
$sRet = $aTagPart[0]
$sParams = StringReplace($sTagPart, $sRet, "", 1)
$sParams = "ptr" & $sParams
If Not $fPrint Then
$hCallback = DllCallbackRegister($sMethod, $sRet, $sParams)
If @error Then
ConsoleWrite('! ' & @error & ' ' & $sMethod & ' ' & $sParams & @CRLF & @CRLF)
EndIf
DllStructSetData($tInterface, "Methods", DllCallbackGetPtr($hCallback), $i + 1) ; save callback pointer
DllStructSetData($tInterface, "Callbacks", $hCallback, $i + 1) ; save callback handle
EndIf
Next
If Not $fPrint Then
DllStructSetData($tInterface, "RefCount", 1) ; initial ref count is 1
DllStructSetData($tInterface, "Size", $iUbound) ; number of interface methods
DllStructSetData($tInterface, "Object", DllStructGetPtr($tInterface, "Methods")) ; Interface method pointers
Return ObjCreateInterface(DllStructGetPtr($tInterface, "Object"), $sIID, $sInterface, $bIsUnknown) ; pointer that's wrapped into object
EndIf
EndFunc ;==>__ObjectCreate
Func __mbn_DeleteObjectFromTag(ByRef $tInterface)
For $i = 1 To DllStructGetData($tInterface, "Size")
DllCallbackFree(DllStructGetData($tInterface, "Callbacks", $i))
Next
$tInterface = 0
EndFunc ;==>__mbn_DeleteObjectFromTag
Func __StringFromGUID($pGUID)
Local $aResult = DllCall("ole32.dll", "int", "StringFromGUID2", "struct*", $pGUID, "wstr", "", "int", 40)
If @error Then Return SetError(@error, @extended, "")
Return SetExtended($aResult[0], $aResult[2])
EndFunc ;==>__StringFromGUID
Func __vl_IOwnerDataCallback_GetItemGroupCount($pSelf, $iItemIndex, $pOccurenceCount) ; Ret: long Par: int; ptr
ConsoleWrite('__vl_IOwnerDataCallback_GetItemGroupCount ' & $iItemIndex & ' ' & $pOccurenceCount & @CRLF)
DllStructSetData(DllStructCreate("ptr", $pOccurenceCount), 1, 1)
Return 0 ; $S_OK
EndFunc ;==>__vl_IOwnerDataCallback_GetItemGroupCount
Func __vl_IOwnerDataCallback_GetItemInGroup($pSelf, $iGroupIndex, $iGroupWideItemIndex, $pTotalItemIndex) ; Ret: long Par: int;int;ptr
;~ GetItemGroup maps indexes in the opposite direction. It is called with a total item index, and returns this item's group index:
ConsoleWrite('__vl_IOwnerDataCallback_GetItemInGroup' & $iGroupIndex & ' ' & $iGroupWideItemIndex & ' ' & $pTotalItemIndex & @CRLF)
;~ // we want group 0 to contain items 0, 3, 6...
;~ // group 1 items 1, 4, 7...
;~ // group 2 items 2, 5, 8...
;~ *pTotalItemIndex = groupIndex + groupWideItemIndex * 3;
DllStructSetData(DllStructCreate("ptr", $pTotalItemIndex), 1, $iGroupIndex + $iGroupWideItemIndex * 1)
Return 0 ; $S_OK
EndFunc ;==>__vl_IOwnerDataCallback_GetItemInGroup
Func __vl_IOwnerDataCallback_GetItemGroup($pSelf, $iItemIndex, $iOccurenceIndex, $pGroupIndex) ; Ret: long Par: int;int;int
ConsoleWrite('__vl_IOwnerDataCallback_GetItemGroup ' & $iItemIndex & ' ' & $iOccurenceIndex & ' ' & $pGroupIndex & @CRLF)
;~ __vl_IOwnerDataCallback_GetItemGroup 0 0 0x00D2F4F4
;~ GetItemGroup maps indexes in the opposite direction. It is called with a total item index, and returns this item's group index:
;~ // group 0 contains items 0, 3, 6...
;~ // group 1 contains items 1, 4, 7...
;~ // group 2 contains items 2, 5, 8...
;~ *pGroupIndex = itemIndex % 3;
;~ return S_OK;
;~ That's it. The occurenceIndex parameter is useful only if you want single items to appear in multiple groups.
DllStructSetData(DllStructCreate("ptr", $pGroupIndex), 1, 1)
Return 0 ; $S_OK
EndFunc ;==>__vl_IOwnerDataCallback_GetItemGroup
Func __vl_IOwnerDataCallback_QueryInterface($pSelf, $pRIID, $pObj) ; Ret: long Par: ptr;ptr
Local Static $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
Local $sIID = __StringFromGUID($pRIID)
ConsoleWrite('__vl_IOwnerDataCallback_QueryInterface ' & $sIID & @CRLF)
If $sIID = $sIID_IUnknown Then
DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
Return 0 ; 0 ; $S_OK
ElseIf $sIID = $sIID_IOwnerDataCallback Then
DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
Return 0 ; $S_OK
Else
Return 0x80004002 ; $E_NOINTERFACE
EndIf
EndFunc ;==>__vl_IOwnerDataCallback_QueryInterface
Func __vl_IOwnerDataCallback_AddRef($pSelf) ; Ret: dword
;~ ConsoleWrite('__vl_IOwnerDataCallback_AddRef' & @CRLF)
Return 1
EndFunc ;==>__vl_IOwnerDataCallback_AddRef
Func __vl_IOwnerDataCallback_Release($pSelf) ; Ret: dword
Return 1
EndFunc ;==>__vl_IOwnerDataCallback_Release
Func __vl_IOwnerDataCallback_GetItemPosition($pSelf, $iItemIndex, $pPosition) ; Ret: long Par: int; ptr
ConsoleWrite('__vl_IOwnerDataCallback_GetItemPosition' & @CRLF)
;~ Return 0 ; $S_OK
Return 0x80004002 ; $E_NOINTERFACE
EndFunc ;==>__vl_IOwnerDataCallback_GetItemPosition
Func __vl_IOwnerDataCallback_SetItemPosition($pSelf, $iItemIndex, $pPosition) ; Ret: long Par: int; ptr
ConsoleWrite('__vl_IOwnerDataCallback_SetItemPosition' & @CRLF)
;~ Return 0 ; $S_OK
Return 0x80004002 ; $E_NOINTERFACE
EndFunc ;==>__vl_IOwnerDataCallback_SetItemPosition
Func __vl_IOwnerDataCallback_OnCacheHint($pSelf, $p1, $p2) ; Ret: long
Return 0x80004002 ; $E_NOINTERFACE
;~ Return 0 ; $S_OK
EndFunc ;==>__vl_IOwnerDataCallback_OnCacheHint