The other lines are just subitems. You have to add the columns, then when responding to LVN_GETDISPINFO supply the text as a normal subitem and also provide a response for LVIF_COLUMNS where you set puColumns, piColFmt(optional), and cColumns (the same as you would normally).
If you're not familiar with piColFmt, it's probably because no VB project has ever included it.
Code:
Public Type LVITEM 'LVITEMW ' was LV_ITEM
mask As LVITEM_mask
iItem As Long
iSubItem As Long
State As LVITEM_state
StateMask As LVITEM_state
pszText As Long
cchTextMax As Long
iImage As Long
lParam As Long
'#If (WIN32_IE >= &H300) Then
iIndent As Long
'#End If
'#If (WIN32_IE >= &H501) Then
iGroupId As Long
cColumns As Long
puColumns As Long
'#End If
'#If (WIN32_IE >= &H600) Then
piColFmt As Long 'array of certain LVCFMT_ for each subitem
iGroup As Long 'for single item in multiple groups in virtual listview
'#End If
End Type
Edit: I'm having a lot of trouble setting the text however. Looks like another VB memory ****up. The iSubItems it requests for text after tile view are set are garbage in the 40-64000 range, so it winds up showing a different number of subitems on mouseover, none with the correct text.
Also be advised MSDN says it's not supported, so who knows if it really can't be done or if it requires some extra unknown steps.
The problem seems to be setting which columns are to be displayed. Which should be done by .puColumns. It does request LVIF_COLUMNS in LVN_GETDISPINFO, but I haven't found a way of setting it that works. Tried the normal way of setting it to VarPtr(cols(0)), no luck, and also tried Copymemory .puColumns, ByVal VarPtr(col(0)), 4&/elements*4bytes/long -again, no luck.
Last edited by fafalone; Feb 8th, 2016 at 10:57 PM.
Friend Property Get fSubItemShowInTile(ByVal lIndex As Long, ByVal lSubItemIndex As Long) As Boolean
'
If (m_lMajor >= 6) Then
ReDim lOrigCols(0 To fColumnCount - 1) As Long
m_tLVW.puColumns = VarPtr(lOrigCols(0))
pGetStyle lIndex - 1, LVIF_COLUMNS
If (m_tLVW.cColumns > 0) Then
Dim i As Long
For i = 0 To m_tLVW.cColumns - 1
If (lOrigCols(i) = lSubItemIndex) Then
fSubItemShowInTile = True
End If
Next i
End If
End If
'
End Property
Friend Property Let fSubItemShowInTile(ByVal lIndex As Long, ByVal lSubItemIndex As Long, ByVal bState As Boolean)
'
If (m_lMajor >= 6) Then
' Check what we already have:
ReDim lOrigCols(0 To fColumnCount - 1) As Long
Dim lOrigColCount As Long
m_tLVW.puColumns = VarPtr(lOrigCols(0))
pGetStyle lIndex - 1, LVIF_COLUMNS
lOrigColCount = m_tLVW.cColumns
Dim lFoundIndex As Long
Dim i As Long
Dim lNewCols() As Long
Dim tSANew As SAFEARRAY1D
lFoundIndex = -1
For i = 0 To lOrigColCount - 1
If (lOrigCols(i) = lSubItemIndex) Then
lFoundIndex = i
Exit For
End If
Next i
If (bState) Then
' adding
If (lFoundIndex = -1) Then
ReDim lNewCols(0 To lOrigColCount) As Long
For i = 0 To lOrigColCount - 1
lNewCols(i) = lOrigCols(i)
Next i
lNewCols(lOrigColCount) = lSubItemIndex
m_tLVW.cColumns = lOrigColCount + 1
m_tLVW.puColumns = VarPtr(lNewCols(0))
pSetIStyle lIndex - 1, LVIF_COLUMNS
Else
' nothing to do
End If
Else
' removing
If (lFoundIndex = -1) Then
' nothing to do
Else
If (lOrigColCount = 1) Then
' clearing:
m_tLVW.cColumns = 0
m_tLVW.puColumns = 0
pSetIStyle lIndex - 1, LVIF_COLUMNS
Else
' modifying
ReDim lNewCols(0 To lOrigColCount - 2) As Long
For i = lFoundIndex To lOrigColCount - 2
lNewCols(i) = lOrigCols(i + 1)
Next i
m_tLVW.cColumns = lOrigColCount - 1
m_tLVW.puColumns = VarPtr(lNewCols(0))
pSetIStyle lIndex - 1, LVIF_COLUMNS
End If
End If
End If
End If
End Property
- Attached, please find the source of the above code (UniListView.zip)
LucasMKG
Last edited by LucasMKG; Feb 8th, 2016 at 11:56 PM.
That looks like the non-virtual way of doing it. In virtual mode you can't do a LVM_SETTILEINFO on an LVITEM, you have to respond to the LVN_GETDISPINFO request for LVIF_COLUMNS just like other LVIF_'s.. If (.mask And LVIF_COLUMNS) = LVIF_COLUMNS Then
# ListView_SetTileViewInfo is used together with LVN_GETDISPINFO
- and still can't figure out the LVIF_TEXT part...how to display the '.cColumns; .puColumns'... in the .pszText (or StringToPointer VarPtr(ArgList(0)), .pszText)?
Are you getting the other lines showing up, just not with the right text?
I just don't understand where these garbage values for iSubItem are coming from. Group view is a problem too. Without it, I can muddle through and get static text to appear (that is, can't look up based on given iSubItem, but can always set it to a particular one if an invalid isubitem is passed). But with it, that doesn't even work and the 2nd line tile text is always the same as the first, despite the static text being assigned.
It's just not looking good for groupview, but tiles without groups we might be able to get a workaround going.
Code:
If (.mask And LVIF_TEXT) = LVIF_TEXT Then
Debug.Print "isubitem " & .iItem & "," & .iSubItem
Select Case .iSubItem
Case 0
.pszText = StrPtr(VLItems(.iItem).sText)
Case 1 To 3
' .pszText = StrPtr("subitem " & .iSubItem)
.pszText = StrPtr(VLItems(.iItem).sSubItems(.iSubItem - 1))
Case Else
If bTiles Then
.pszText = StrPtr(VLItems(.iItem).sSubItems(2))
End If
See the debug statement there? That's what is reporting requested subitems as 101, 45000, 64000.. garbage. But always setting it to 2 works and shows subitem 2 as the 2nd tile line, but if groups are enabled the second tile line just stays the same as the first line, even though Case Else executes.
Code:
If (.mask And LVIF_COLUMNS) = LVIF_COLUMNS Then
.cColumns = 1
' CopyMemory .puColumns, ByVal VarPtr(lCol(0)), 4&
' Debug.Print "ptr=" & VarPtr(lCol(0))
.puColumns = VarPtr(lCol(0))
End If
Nothing I've tried there works; it always requests the garbage subitem values.
Last edited by fafalone; Feb 11th, 2016 at 08:29 PM.
Nothing special just a normal LVM_SETTILEVIEW routine.. I'm a little leery of the one you're using because it's overwriting your mask (which shouldn't include label margins unless actually setting them, which your code doesn't unless it's XP) and flags with the LVM_GETTILEVIEWINFO result.. so it may very well be passed back missing the LVTVIM_COLUMNS mask and autosize flag.
The one I use to switch it on:
Code:
Public Sub SetTileView(hWnd As Long)
Dim tLVI As LVTILEVIEWINFO
Call SendMessage(hWnd, LVM_SETVIEW, LV_VIEW_TILE, ByVal 0&)
tLVI.cbSize = Len(tLVI)
Call SendMessage(hWnd, LVM_GETTILEVIEWINFO, 0, tLVI)
tLVI.dwMask = LVTVIM_COLUMNS
tLVI.cLines = 2
Call SendMessage(hWnd, LVM_SETTILEVIEWINFO, 0, tLVI)
bTiles = True
End Sub
And one step to absolutely take is to confirm it's working in a standard listview before trying it when LVS_OWNERDATA is enabled.
thanks...after adding the below line, it worked:
'Call SendMessage(hWnd, LVM_SETVIEW, LV_VIEW_TILE, ByVal 0&)'
- it works even if '.cLine > 2'
Code:
'virtual listview
'in the DISPINFO (Case LVN_GETDISPINFOW, LVN_GETDISPINFOA)
'/* list item text
If (.Mask And LVIF_TEXT) = LVIF_TEXT Then
Select Case .iSubItem
Case 0
sTemp = m_cGridItem(lItem).Text(0)
Case Else
If (m_eGridMode = eLvwViewTile) Then
sTemp = m_cGridItem(lItem).Text(m_lTileViewLines)
Else
sTemp = m_cGridItem(lItem).Text(.iSubItem)
End If
End If
now..I'm debugging the whole 'extended-tile view mode to show sub-items' feature..for seamless integration with vhGrid.
LucasMKG
- as the author of vhGrid - John Underhill (Steppenwolfe) send his shout out to 'Carles 'da man!' PV, for his awesome api listview'
- I'm sending my shout-out to Fafalone 'da genius', for his wisdom impartation.
Last edited by LucasMKG; Feb 15th, 2016 at 05:40 AM.
but faf,
it's unresolved, since the 'sequence of subitems lines' as per '.puColumns' are not showing...and currently it shows all subitem lines of the last column or whatever the value of m_lTileViewLines'..(it should show variable subitem lines as per '.puColumns' sequence).
- is it possible to manipulate subitem lines with an array or something?
LucasMKG
?
Last edited by LucasMKG; Feb 16th, 2016 at 06:17 AM.
Re: Virtual ListView - Show Subitem Text in TileView
typed on my MobilePhone::
another option...it might be to manage it myself:
- if i remove:
'If (.Mask And
LVIF_COLUMNS) = LVIF_COLUMNS' ...i still get subitem text in tileview.
- i then insert this code to get logical data (but i have extra m_lTileViewLines in LVN_GETDISPINFO)
Code:
If (m_eGridMode = eLvwViewTile)
Static Once As Boolean
Static slCnt As Long
Static slCol As Long
If Once = False Then
slCol = 0
.iSubItem = slCol
slCnt = slCnt + 1
If slCnt = (m_lTileViewLines + 1) Then Once = True
Else
If slCol = m_lTileViewLines Then slCol = - 1
slCol = slCol + 1
.iSubItem = slCol
End If
the issue about the above code is that, i can't figure out how '.iSubItem' in tileview should behave when '.clines' are set.
Re: Virtual ListView - Show Subitem Text in TileView
It's not behaving at all is the main problem.. I get either 0 or some large number, like 48038 or 64802, makes no sense whatsoever and ive tried a dozen different ways to try to get it sending the right numbers.. Nothing helps. I really think it's just not implemented. Only solution i can think of is the nuclear option: just owner draw it.
Re: Virtual ListView - Show Subitem Text in TileView
This might mean something after all:
- Attached, pls find (xls zipped file) :: data extracted from '.iSubItem' : from 2 TileView Items: where # is the number of m_lTileViewLine
Re: Virtual ListView - Show Subitem Text in TileView
Not sure what I'm looking at.
There's the deeper problem too.. the text keeps changing back and forth as the mouse moves between the main item text, which shouldn't even be one of the 2nd/3rd lines, and the text it's supposed to be (on the 3rd line; the 2nd line is always the same as the first)
It's just random garbage. Like VB is randomizing which pointer is chooses with every paint.
And the first detail line (2nd line overall and first gray line) is ALWAYS the same as the main item text. Even explicitly setting it, verified it's called. .pszText = StrPtr("***").. ignored, text= "Item 1", StrPtr(public string).. ignored, text= "Item 1"
Last edited by fafalone; Feb 26th, 2016 at 09:19 PM.
Re: Virtual ListView - Show Subitem Text in TileView
It might be that if 'ISubItemCallback' is implemented...'TileView' will behave.
-Remember that we should be able to view items like in the attached image...it might explain why item data updates when the mouse pointer is on that item..
LucasMKG
TOL
Last edited by LucasMKG; Feb 29th, 2016 at 04:15 AM.
Re: Virtual ListView - Show Subitem Text in TileView
The item in 'Other' is the only tileview item.
The other items use subitem controls, which is proving to be the most complicated issue yet***. Timo already figured it out, but is one of those 'it's my secret code you can have it in a few years' guys
Also Explorer isn't the best example as it almost certainly uses many customizations that aren't even accessible to outsiders or are simply owner drawn.
*** - The main problem is I can't figure out for the life of me how to approach converting this mess to VB:
Edit: There mere presence of ISubItemCallback stabilized painting for the tiles, but still didn't help with .iSubItem random numbers. So it's now possible to have a single additional line; but only when not in group mode. Group mode is crashing right now; probably because it's calling GetSubItemControl and there's no code there yet.
Last edited by fafalone; Feb 29th, 2016 at 12:42 PM.
Re: Virtual ListView - Show Subitem Text in TileView
Originally Posted by fafalone
*** - The main problem is I can't figure out for the life of me how to approach converting this mess to VB:
Untested!!!
Code:
If SUCCEEDED(hr) Then
Dim pControl As IPropertyControlBase: GetMem4 ppObject, pControl
Dim themeAppName As String: themeAppName = ""
Dim themeIDList As String: themeIDList = ""
Dim pSubAppName As String: pSubAppName = String$(300&, 0)
Dim valueSubAppName As Integer: valueSubAppName = CInt(GetPropW(GetLngFromPtr(this), StrPtr("#43281")))
If valueSubAppName Then
GetAtomNameW valueSubAppName, StrPtr(pSubAppName), 300&
If Left$(pSubAppName, 2&) = "$" & vbNullChar Then pSubAppName = ""
Else
pSubAppName = vbNullString
End If
themeAppName = pSubAppName
Dim pSubIDList As String: pSubIDList = String$(300&, 0)
Dim valueSubIDList As Integer: valueSubIDList = CInt(GetPropW(GetLngFromPtr(this), StrPtr("#43280")))
If valueSubIDList Then
GetAtomNameW valueSubIDList, StrPtr(pSubIDList), 300&
If Left$(pSubIDList, 2&) = "$" & vbNullChar Then pSubIDList = ""
Else
pSubIDList = vbNullString
End If
Code:
Private Declare Function GetAtomNameW Lib "kernel32.dll" (ByVal nAtom As Integer, ByVal lpBuffer As Long, ByVal nSize As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60.dll" (ByVal Addr As Long, ByRef RetVal As Long) As Long
Private Declare Function GetPropW Lib "user32.dll" (ByVal hWnd As Long, ByVal lpString As Long) As Long
Public Function GetLngFromPtr(ByVal Ptr As Long) As Long
GetMem4 Ptr, GetLngFromPtr
End Function
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
The rest of it is pretty straight forward and easy to convert with a couple exceptions...
VB doesn't allow LPVOID (As Any) in an implemented interface prototype; so I've made it IPropertyControlBase since it should be either that or an interface that inherits from it like IPropertyControl.
As always, all things PROPVARIANT are a phenomenally painful experience in VB. Any way to not use them?
Re: Virtual ListView - Show Subitem Text in TileView
Originally Posted by fafalone
What is the 'this' in CInt(GetPropW(GetLngFromPtr(this), StrPtr("#43281")))?
In the C++ code it refers to a class block; perhaps ObjPtr(Me)?
Well, the 1st parameter of the GetProp function is supposed to be an hWnd, so I guess the this pointer probably points to the ListView's hWnd value. That this pointer confuses me as well, because from what I understand, it is analogous to the Me keyword (i.e., they both point to a specific instance of the class).
Originally Posted by fafalone
As always, all things PROPVARIANT are a phenomenally painful experience in VB. Any way to not use them?
Sorry, I'm not familiar yet with PROPVARIANTs...
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Re: Virtual ListView - Show Subitem Text in TileView
but it seems like dilettante converts PROPVARIANT like this "...the returned value is a PROPVARIANT, so we first convert it to a Variant for use in VB6', in this thread http://earlier137.rssing.com/browser...78609&item=165
LucasMKG
'ISubItemCallback' will be implemented in VB6...its a matter of, how soon.
Re: Virtual ListView - Show Subitem Text in TileView
Yeah for simple cases that works fine, but you start running into problems before you get to half the complexity of what's going on here.
Another issue that's got me really concerned is the iSubItem bad values are showing up in ISubitemCallback_GetSubitemControl et al. too... This has the potential to ruin everything
Re: Virtual ListView - Show Subitem Text in TileView
I haven't really worked on it... The challenges just looked so problematic i got discouraged, then distracted with the massive expansion to my TLB (CoreAudio and DirectShow). It's not just a matter of translating cpp to vb... It appears vb may not even be receiving the proper data. I'll take another look tonight, but we might also consider talking to Timo.. I believe he got it working in VB, but unfortunately he says he won't release the code until he retires, however many years that is. But maybe we can gain some insights. It's also possible we might have to fall back on a cpp Dll for some things.
Now my BeginSubItemEdit function executes all the way through with seemingly successful calls, but still it's just a blank display (and a single call, despite that there should be multiple controls) that if interacted with has the border smeared then crashes
Here's the latest desperate attempt...
Code:
Public Function BeginSubItemEditVB(ByVal This As ISubItemCallback, ByVal itemIndex As Long, ByVal subItemIndex As Long, ByVal nMode As Long, requiredInterface As UUID, ppObjectPtr As Long) As Long ' ppObject As IPropertyControlBase)
Debug.Print "BeginSubItemEditVB idx=" & itemIndex & "," & subItemIndex & " nMode=" & nMode & ",reqi data1=0x" & Hex$(requiredInterface.Data1) & ",last=0x" & Hex$(requiredInterface.Data4(7))
Dim pddpc As IDrawPropertyControl
Dim ppc As IPropertyControl
Dim pdpc As oleexp.IUnknown
If (ppObjectPtr = 0) Then
Debug.Print "BeginSubitemEdit.No object"
BeginSubItemEditVB = E_POINTER
Exit Function
Else
If subItemIndex <> 1 Then
BeginSubItemEditVB = E_NOINTERFACE
Exit Function
End If
If requiredInterface.Data1 = IID_IDrawPropertyControl.Data1 Then
' Debug.Print "set pddpc " & ppObjectPtr
' vbaObjSetAddRef pdpc, ppObjectPtr
'' Set pdpc = PtrToObj(ppObjectPtr)
' Debug.Print "post-vbset"
'' Set pdpc = pddpc
'' Debug.Print "post-set"
ElseIf requiredInterface.Data1 = IID_IPropertyControl.Data1 Then
' Debug.Print "set ppc " & ppObjectPtr
'' vbaObjSetAddRef ppc, ppObjectPtr
' Set ppc = PtrToObj(ppObjectPtr)
' Debug.Print "post-vbobjset"
' Set pdpc = ppc
' Debug.Print "post-set"
Else
Debug.Print "req iface unknown, ==0x" & Hex$(requiredInterface.Data1)
BeginSubItemEditVB = E_POINTER
Exit Function
End If
End If
Dim hr As Long
hr = E_NOINTERFACE
Dim pPropertyDescription As IPropertyDescription
Dim propertyValue As Variant
Debug.Print "BeginSubItemEditVB creating instance..."
Select Case itemIndex
Case 0
hr = CoCreateInstance(CLSID_CInPlaceMLEditBoxControl, 0&, CLSCTX_INPROC_SERVER, requiredInterface, ppObjectPtr)
PSGetPropertyDescriptionByName StrPtr("System.Generic.String"), IID_IPropertyDescription, pPropertyDescription
Case 1
hr = CoCreateInstance(CLSID_CCustomDrawPercentFullControl, 0&, CLSCTX_INPROC_SERVER, requiredInterface, ppObjectPtr)
Case 2
hr = hr = CoCreateInstance(CLSID_CRatingControl, 0&, CLSCTX_INPROC_SERVER, requiredInterface, ppObjectPtr)
Case 3
If (requiredInterface.Data1 = IID_IDrawPropertyControl.Data1) Then
hr = CoCreateInstance(CLSID_CStaticPropertyControl, 0&, CLSCTX_INPROC_SERVER, requiredInterface, ppObjectPtr)
Else
hr = CoCreateInstance(CLSID_CInPlaceEditBoxControl, 0&, CLSCTX_INPROC_SERVER, requiredInterface, ppObjectPtr)
End If
PSGetPropertyDescriptionByName StrPtr("System.Generic.String"), IID_IPropertyDescription, pPropertyDescription
Case 4, 5
hr = CoCreateInstance(CLSID_CBooleanControl, 0&, CLSCTX_INPROC_SERVER, requiredInterface, ppObjectPtr)
PSGetPropertyDescriptionByName StrPtr("System.Generic.Boolean"), IID_IPropertyDescription, pPropertyDescription
Case 6
'todo: datetime
Case 7
hr = CoCreateInstance(CLSID_CInPlaceDropListComboControl, 0&, CLSCTX_INPROC_SERVER, requiredInterface, ppObjectPtr)
PSGetPropertyDescriptionByName StrPtr("System.Photo.Metering"), IID_IPropertyDescription, pPropertyDescription
Case 8
hr = CoCreateInstance(CLSID_CHyperlinkControl, 0&, CLSCTX_INPROC_SERVER, requiredInterface, ppObjectPtr)
End Select
'If (pdpc Is Nothing) Then
Debug.Print "BeginSubItemEditVB create instance 0x" & Hex$(hr)
'Else
' Debug.Print "BeginSubItemEditVB instance created; obj is valid"
'' ppObjectPtr = ObjPtr(pdpc)
'End If
If hr = S_OK Then
Debug.Print "S_OK"
Dim pControl As IPropertyControlBase
' Set pdpc = PtrToObj(ppObjectPtr)
vbaObjSet pControl, ppObjectPtr
Debug.Print "post-vbaset"
' Set pControl = pdpc
Dim themeAppName As String, themeIDList As String
Dim pSubAppNameBuffer(300) As Integer
Dim valueSubAppName As Long
Dim pSubAppName As String
pSubAppName = String$(300, 0)
valueSubAppName = GetPropW(hLVVG, StrPtr("#43281"))
' valueSubAppName = GetPropW(ObjPtr(This), StrPtr("#43281"))
Debug.Print "BeginSubItemEditVB GetProp 1=" & valueSubAppName
If valueSubAppName Then
' GetAtomNameW valueSubAppName, VarPtr(pSubAppNameBuffer(0)), 300
GetAtomNameW valueSubAppName, ByVal StrPtr(pSubAppName), 300&
If Left$(pSubAppName, 1&) = "$" & vbNullChar Then pSubAppName = ""
Else
pSubAppName = vbNullString
End If
Debug.Print "BeginSubItemEditVB AtomName1=" & pSubAppName
themeAppName = pSubAppName
Dim pSubIDList As String: pSubIDList = String$(300&, 0)
Dim valueSubIDList As Long: valueSubIDList = GetPropW(hLVVG, StrPtr("#43280")) 'GetPropW(ObjPtr(This), StrPtr("#43280"))
Debug.Print "BeginSubItemEditVB GetProp2=" & valueSubIDList
If valueSubIDList <> "0" Then
GetAtomNameW valueSubIDList, StrPtr(pSubIDList), 300&
If Left$(pSubIDList, 1&) = "$" & vbNullChar Then pSubIDList = ""
Else
pSubIDList = "" 'vbNullString
End If
Debug.Print "BeginSubItemEditVB AtomName2=" & pSubIDList
themeIDList = pSubIDList
Dim hFont As Long: hFont = SendMessage(hLVVG, WM_GETFONT, 0&, ByVal 0&)
Dim textColor As Long
textColor = SendMessage(hLVVG, LVM_GETTEXTCOLOR, 0&, ByVal 0&)
If textColor = CLR_NONE Then
textColor = GetSysColor(COLOR_WINDOWTEXT)
End If
Debug.Print "BeginSubItemEditVB font get"
' Dim pBuffer As String: pBuffer
Dim tmp As Variant
Dim tmp2 As Variant
Select Case itemIndex
Case 1, 2, 7
tmp = CLng(VLItems(itemIndex).sSubItems(0))
VariantToPropVariant tmp, tmp2
PropVariantChangeType propertyValue, tmp2, 0, VT_UI4
' PropVariantClear tmp
Case 4, 5
tmp = CBool(VLItems(itemIndex).sSubItems(0))
VariantToPropVariant tmp, tmp2
PropVariantChangeType propertyValue, tmp2, 0, VT_BOOL
' PropVariantClear tmp
Case Else
tmp = CStr(VLItems(itemIndex).sSubItems(0))
VariantToPropVariant tmp, tmp2
PropVariantChangeType propertyValue, tmp2, 0&, VT_LPWSTR 'It would be a VT_BSTR before this
End Select
Debug.Print "BeginSubItemEditVB setting value to " & tmp & "..."
Dim pPropertyValueObj As IPropertyValue
Set pPropertyValueObj = New cPropValue
pPropertyValueObj.InitValue propertyValue
Debug.Print "InitValue"
If (pPropertyDescription Is Nothing) = False Then
Debug.Print "initializing..."
pControl.Initialize pPropertyDescription, 1
End If
Debug.Print "setting value..."
pControl.SetValue pPropertyValueObj
Debug.Print "setting textcolor..."
pControl.SetTextColor textColor
Debug.Print "setting font..."
If hFont Then pControl.SetFont hFont
Debug.Print "setting theme..."
pControl.SetWindowTheme StrPtr(themeAppName), StrPtr(themeIDList)
Debug.Print "BeginSubItemEditVB out"
End If
End Function
It gets right up through 'Out', but it's nothing displayed and crashville after then, with no other methods are entered. The GetProp/GetAtomName issues have been resolved, I'm now intimately familiar with PROPVARIANT's so confident I'm doing those right... the object pointer is non-zero like it should be and CoCreateInstance is returning S_OK...
I think it might be time to concede getting real subitem controls in VB is just beyond my ability
Reached out to Timo on the project page for his CodeProject example too see if he ever got it working in VB (he did finally release his control source but it wasn't actually in VB, just C like the dmo).
Last edited by fafalone; Oct 13th, 2019 at 02:06 AM.
Re: Virtual ListView - Show Subitem Text in TileView
Originally Posted by fafalone
...
Public Function BeginSubItemEditVB(ByVal This As ISubItemCallback, ByVal itemIndex As Long, ByVal subItemIndex As Long, ByVal nMode As Long, requiredInterface As UUID, ppObjectPtr As Long) As Long ' ppObject As IPropertyControlBase)
...Reached out to Timo ... I've got the ppObject As Long to get a pointer... but it's not zero when received... I can't turn it into IPropertyControlBase with CopyMemory or vbaObjSetAddref before CoCreateInstance... I can call CoCreateInstance with that pointer and that returns S_OK, but then to call its methods afterwards CopyMemory/vbaObjSetAddref both still fail; vbaObjSet alone (not incrementing the reference counter) gives me a non-null object, but when I call .SetValue or .Initialize, execution just stops. No error, not frozen, just stops at that line and does nothing.
'ppObject' is trying to spoil thing
Last edited by LucasMKG; Oct 13th, 2019 at 04:56 AM.
Re: Virtual ListView - Show Subitem Text in TileView
I got it so execution doesn't stop; it returns from all the calls on it, but then just doesn't display anything (even the text of the listitem in the Name column doesn't show up) and eventually crashes whenever you touch the form.
Last edited by fafalone; Oct 13th, 2019 at 05:08 AM.
Re: Virtual ListView - Show Subitem Text in TileView
IID_PPV_ARGS is just a language feature that automatically looks up the IID for whatever interface you've passed it and fills in the argument for it. So if you've got a method with riid As UUID, ppv As Any, you'd have your variable declared already as e.g. IShellFolder psf;, so IID_PPV_ARGS(psf) would fill in both parameters instead of you manually entering IID_IShellFolder, psf.
VB doesn't support that language feature however, so you'll always see it written out fully in VB code.
If you have MyFunction(arg1, arg2) there's no mechanism that would allow you to call it as MyFunction(SingleCall()) and have SingleCall fill in both.
Last edited by fafalone; Oct 13th, 2019 at 10:46 AM.
Re: Virtual ListView - Show Subitem Text in TileView
ok, I see
Instead of catching ppObject in the 'Public Function BeginSubItemEditVB'
why not QueryInterface the ppObject just below the 'Public Function BeginSubItemEditVB'?
Code:
// query interface for the return value
HRESULT hResult = pShellExt->QueryInterface(riid, ppObject);
or
// query interface for the a pointer
HRESULT hResult = pClassFactory->QueryInterface(riid, ppReturn);