-
Apr 28th, 2022, 08:55 AM
#1
Thread Starter
Hyperactive Member
[RESOLVED] ColumnHeader.Tag Property
Is listview natively having ColumnHeader.Tag Property, or must it be retrofitted?
Or
Is there any ColumnHeader property where one can store data?
LucasMKG
?
Last edited by LucasMKG; Apr 28th, 2022 at 09:03 AM.
-
Apr 28th, 2022, 09:18 AM
#2
Re: ColumnHeader.Tag Property
If you add the control to your form you can see what properties it has by typing in the control name and a . afterward, intellisense will show you the list of things that can come next.
What would you want to store in a column header of a list view? It is really only meant to show the field name so the user can tell what that column of data is.
-
Apr 28th, 2022, 02:58 PM
#3
Re: ColumnHeader.Tag Property
The native structure has a .lParam member you can store an arbitrary 4 bytes in.
-
Apr 29th, 2022, 12:18 AM
#4
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
thanks,
What I am trying to achieve is:
1. I have a listview that interchanges between LVS_OWNERDATA and LVS_OWNERDRAWFIXED
2. it would be easier if, without retrofitting it, one could have something like:
- Column.text to store a value,
Reason:
Any column can house 'node-to-cell ole interop', meaning TreeGridColumn
Code:
'Seal.added: node-to-cell ole interop.implement s .............................
'Seal Systems *** Property.added: specify TreeGrid column
Public Property Get TreeGridColumn() As Long
TreeGridColumn = m_lTreeGridColumn
End Property
Public Property Let TreeGridColumn(ByVal vNewValue As Long)
m_lTreeGridColumn = vNewValue
PropertyChanged "TreeGridColumn"
End Property
m_lTreeGridColumn might not be constant, depending on the column drag and drop results.
In the GXISubclass_WndProc:
Code:
Case HDN_BEGINDRAG
'I am currently trying to effect the TreeGridColumn changes here.
Case HDN_ENDDRAG
Scene1: when I drag the TreeGridColumn, where ever I drop it, it should change to the column number dropped
Scene2: even if I drag any other column, the TreeGridColumn should auto change to reflect the new column order.
Scene3: when I switch to righttoleft, TreeGridColumn should auto change
Code:
'Seal.added.listview_mode - CreateListItems * end........................................................
'Seal.added.based on ©UniListView (Dana Seaman - www.cyberactivex.com) s -------------------------------------------
Public Property Get RightToLeft() As Boolean
'Attribute RightToLeft.VB_Description = "Determines text display direction and control visual appearance on a bidirectional system."
RightToLeft = m_bRightToLeft
End Property
Public Property Let RightToLeft(ByVal bState As Boolean)
m_bRightToLeft = bState
If m_bRightToLeft Then
WindowStyle m_lHGHwnd, eGWL_EXSTYLE, WS_EX_LAYOUTRTL, 0
'not working SetExtendedStyle WS_EX_LAYOUTRTL, 0 'Seal.added
Else
WindowStyle m_lHGHwnd, eGWL_EXSTYLE, 0, WS_EX_LAYOUTRTL
'not working SetExtendedStyle 0, WS_EX_LAYOUTRTL 'Seal.added
End If
Dim lS As Long
Dim lHwnd As Long
If Not (m_lHGHwnd = 0) Then
' Set the RightToLeft mode of the ListView's ColumnHeader control:
lHwnd = SendMessageLong(m_lHGHwnd, LVM_GETHEADER, 0&, ByVal 0&)
If Not (lHwnd = 0) Then
lS = GetWindowLong(lHwnd, GWL_EXSTYLE)
If bState Then
lS = lS Or WS_EX_LAYOUTRTL
Else
lS = lS And Not WS_EX_LAYOUTRTL
End If
SetWindowLong lHwnd, GWL_EXSTYLE, lS
'Apparent bug in ColumnHeader alignment if RTL and has vScrollBar
'Fix with SetWindowPos w/o SWP_NOMOVE flag
SetWindowPos lHwnd, 0, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOOWNERZORDER Or SWP_NOZORDER Or SWP_FRAMECHANGED
End If
End If
PropertyChanged "RightToLeft"
End Property
'Seal.added.based on ©UniListView (Dana Seaman - www.cyberactivex.com) e
So, I reckon that if I had column property which I can store the value, then all I have to do is to traverse the column headers to check the one that houses the treeview...and that will be the easiest route.
LucasMKG
..
Last edited by LucasMKG; Apr 29th, 2022 at 12:31 AM.
-
Apr 29th, 2022, 04:08 AM
#5
Re: ColumnHeader.Tag Property
The column header order is a separate issue. You can use HDM_ORDERTOINDEX to map the current column header order to the 0-based index representing the actual items. You can also use HDM_GETORDERARRAY/HDM_SETORDERARRAY to get/set the column order based on index.
Another thing to consider is that in an owner data ListView, the dispinfo requests you get refer to the index, not the current order. You can have drag/drop columns in a virtual ListView without needing to keep track of the current order at all; if it requests subitem 1, that's the index, it could be 0, 2, 3, etc, in the current order after drag/drop.
-
May 2nd, 2022, 03:02 PM
#6
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
Originally Posted by fafalone
...Another thing to consider is that in an owner data ListView, the dispinfo requests you get refer to the index, not the current order. You can have drag/drop columns in a virtual ListView without needing to keep track of the current order at all; if it requests subitem 1, that's the index, it could be 0, 2, 3, etc, in the current order after drag/drop.
bit confused...unable to digest
LucasMKG
?
-
May 2nd, 2022, 06:21 PM
#7
Re: ColumnHeader.Tag Property
If you have Column1, Column2, Column3, corresponding to subitem index 1, 2, 3 in LVN_GETDISPINFO, if the user drag drops them to Column2, Column1, Column3, subitem index 1 will still refer to Column1, even though it's now 2nd in the current order.
-
May 3rd, 2022, 03:09 AM
#8
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
Thanks...faf,
I didn't know that the column index remain constant...no matter what (even when the user rearranged the columns).
Then it's like the initial order is retained throughout...that comforting.
This info u just shared...changes everything. Meaning, the way I'll be viewing virtual listview.
(Then column.index might also be referred to as a permanent column.tag...storing the first (true) column identity/assigned index throughout)
Does this apply to virtual (LVS_OWNERDATA) listview only? How about (LVS_OWNERDRAWFIXED), and standard listview?
U just armed me...now, let me work on it.
LucasMKG
Last edited by LucasMKG; May 3rd, 2022 at 03:28 AM.
-
May 3rd, 2022, 04:54 AM
#9
Re: ColumnHeader.Tag Property
I've never used LVS_OWNERDRAWFIXED, but my initial impression is I don't see any special handling that indicates it uses order instead of index when presenting the message to draw items in the few projects that do, so it should be the same.
A standard ListView yes all the methods of setting the item text will also refer to the index, not the order. I'm not sure if anywhere actually refers to the order; pretty sure the only way you'll encounter it is by specifically asking for it with one of the messages to map between index/order.
You have to be more careful with item order, rather than subitem order. In a virtual listview, you'll always be asked for the order, so you have to sort the data source yourself.
PS- If you're going to be supporting standard mode and virtual mode in the same ListView, you can save yourself some trouble by using LVN_GETDISPINFO to handle item text/icon/etc for both, assuming you're using the Unicode items. When adding items, instead of setting text to StrPtr(str), set it to LPSTR_TEXTCALLBACK, and the icon to I_IMAGECALLBACK, and group to I_GROUPIDCALLBACK if you're using groups.
Last edited by fafalone; May 3rd, 2022 at 05:20 AM.
-
May 3rd, 2022, 06:49 AM
#10
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
Originally Posted by fafalone
...In a virtual listview, you'll always be asked for the order, so you have to sort the data source yourself...
My issue is right there...
Case study:
I have a virtual listview with 4 columns (0,1,2,3)
1. I assign column 0 to host a treeview...and set m_lTreeGridColumn=0 as per index,
2. I decide on the fly to switch the listview to RightToLeft...then i'll set m_lTreeGridColumn=3
easy, but if before 2 above, I decide to Drag_n_Drop TreeColumn(with index 0) to 2nd column, so the order will be (1,0,2,3), then
How will I pick it up (setting m_lTreeGridColumn) using:
Code:
Dim lCt As Long
For lCt = 0 To (m_lColumnCount - 1)
If ColumnIndex(lCt) = lIndex Then
ColumnAtIndex = lCt
Exit For
End If
Next lCt
LucasMKG
?
Last edited by LucasMKG; May 3rd, 2022 at 06:52 AM.
-
May 3rd, 2022, 08:34 AM
#11
Re: ColumnHeader.Tag Property
I addressed that. The column index is the column index, the column order doesn't matter.
That comment was talking about the list item order;
Item1(Sub0) Sub1 Sub2 Sub3
Item2(Sub0) Sub1 Sub2 Sub3
You'll always get the column index for Sub1/2/3 regardless of the order, but you can't apply a sort callback and have Item1,Item2 automatically reordered to Item2,Item1. It will always just ask for the 0-maxitem order sequentially.
Bottom line is when you have a virtual listview, LVM_SORTITEMS doesn't exist. Won't do anything. You sort by re-ordering the data source for the items. But this doesn't have anything to do with column order.
-
May 5th, 2022, 04:30 PM
#12
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
sorry,
but, maybe I'm not clear enough...
I'm simply looking for a redundant column property that I can use to store data/boleean
i.e column.text; column.width, etc
LucasMKG
?
-
May 6th, 2022, 12:31 AM
#13
Re: ColumnHeader.Tag Property
Originally Posted by fafalone
The native structure has a .lParam member you can store an arbitrary 4 bytes in.
Both ListItems and ColumnHeader items have it.
But you don't need that to know which column it is.
-
May 7th, 2022, 03:58 AM
#14
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
Originally Posted by fafalone
The native structure has a .lParam member you can store an arbitrary 4 bytes in.
That will be extreme, and I would struggle to assigning values or maintain.
having said that, i'm now about to wrap this up;
Originally Posted by fafalone
....Bottom line is when you have a virtual listview, LVM_SORTITEMS doesn't exist. Won't do anything. You sort by re-ordering the data source for the items. But this doesn't have anything to do with column order.
Since you said that in the virtual listview, LVM_SORTITEMS doesn't exist. I reckon that, this also applies to columns
Code:
Private Type LVCOLUMN ' was LV_COLUMN
Mask As LVCOLUMN_mask
fmt As LVCOLUMN_fmt
cx As Long
pszText As String ' if String, must be pre-allocated
cchTextMax As Long
iSubItem As Long
'#If (WIN32_IE >= &H300) Then
iImage As Long
iOrder As Long
'#End If
'#if (WIN32_IE >= &H600)
cxMin As Long
cxDefault As Long
cxIdeal As Long
'#End If
End Type
Will that render LVCOLUMN.iOrder redundant?
If so, can iOrder be used to store values (since its redundant) without desrupting things in the listview, (my intension is to assign 'Column Format') i.e. Numerical, Currency, Hyperlink, TreeView (node_to_cell), etc?
LucasMKG
?
Last edited by LucasMKG; May 7th, 2022 at 04:25 AM.
-
May 7th, 2022, 04:29 AM
#15
Re: ColumnHeader.Tag Property
A virtual listview provides item data via the callback, it doesn't affect the header control. You're not supplying column information in the wndproc like you are list item data.
Re-read from the beginning. The order isn't redundant, it's the order. Which is different from the index.
I don't know if it would retain the value if you set it but didn't specify LVCF_ORDER (which normally tells it that field is used), would have to check. Depends on whether it checks the flag before filling in the iOrder in HDITEM, And if the header control retained it if not used. Probably not. And if you did flag it as used, it would get treated as the order and rearrange your columns.
Also, you're talking about doing the same thing with the iOrder member that you just called extreme. Why is an HDITEM lParam extreme and you'd have trouble assigning values, but instead you want to do the same thing with a member that's already in use for something else? Yes you would have to interact with the header hwnd and HDITEM instead of the front end the ListView provides, but they're not any different, it's the same control underneath.
Last edited by fafalone; May 7th, 2022 at 04:40 AM.
-
May 7th, 2022, 04:44 AM
#16
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
Whats the difference between LVCOLUMN and HDITEM?
Code:
Private Type LVCOLUMN
Mask As Long
fmt As Long
cx As Long
pszText As Long
cchTextMax As Long
iSubItem As Long
iImage As Long
iOrder As Long
End Type
Private Type HDITEM
Mask As Long
cxy As Long
pszText As Long
hbm As Long
cchTextMax As Long
fmt As Long
lParam As Long
iImage As Long
iOrder As Long
End Type
Can I only use HDITEM, instead of LVCOLUMN ?
LucasMKG
?
-
May 7th, 2022, 04:52 AM
#17
Re: ColumnHeader.Tag Property
The ListView takes the LVCOLUMN structure, converts it to an HDITEM structure, and then sends it to the header control.
You can get the header control hwnd with LVM_GETHEADER and interact with it yourself. This also lets you use some header features not exposed directly by the ListView.
Header documentation: https://docs.microsoft.com/en-us/win...trol-reference
-
May 7th, 2022, 04:53 AM
#18
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
Originally Posted by fafalone
The native structure has a .lParam member you can store an arbitrary 4 bytes in.
I thought you were referring to some weird WNDPRC, not HDITEM
sorry about that
LucasMKG
-
May 7th, 2022, 05:03 AM
#19
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
Originally Posted by fafalone
The ListView takes the LVCOLUMN structure, converts it to an HDITEM structure, and then sends it to the header control.
Then I'll abandon LVCOLUMN and stick with HDITEM
Originally Posted by fafalone
Thanks for the link, it seems like Header has so many features to play with
LucasMKG
...
-
May 7th, 2022, 05:05 AM
#20
Thread Starter
Hyperactive Member
Re: ColumnHeader.Tag Property
fafalone,
u're amazing, thanks
LucasMKG
-
May 7th, 2022, 05:22 AM
#21
Re: [RESOLVED] ColumnHeader.Tag Property
Yeah it is a little confusing MS uses "lParam" as a spare member for user defined values in structures, then as an essential part of WndProc messages.
Glad to help
Playing around with the header directly is it's whole little world inside the report mode of a listview (or other modes, you can actually make it appear in all of them, there's a 'header in all views' listview style). Intercepting it's messages lets you do things like customize the font or have a menu pop up on right click.
-
May 12th, 2022, 05:21 AM
#22
Thread Starter
Hyperactive Member
Re: [RESOLVED] ColumnHeader.Tag Property
LVCOLUMN_fmt and HDITEM_FMT are okay
but why HDMASK differ with LVCOLUMN_mask
Code:
Private Enum HDMASK
HDI_WIDTH = &H1
HDI_HEIGHT = HDI_WIDTH
HDI_TEXT = &H2
HDI_FORMAT = &H4
HDI_LPARAM = &H8
HDI_BITMAP = &H10
HDI_IMAGE = &H20
HDI_DI_SETITEM = &H40
HDI_ORDER = &H80
'5.0
HDI_FILTER = &H100
'6.0
HDI_STATE = &H200
End Enum
Code:
Private Enum LVCOLUMN_mask
LVCF_FMT = &H1
LVCF_WIDTH = &H2
LVCF_TEXT = &H4
LVCF_SUBITEM = &H8
'#If (WIN32_IE >= &H300) Then
LVCF_IMAGE = &H10
LVCF_ORDER = &H20
'#End If
'#If (WIN32_IE >= &H600) Then
LVCF_MINWIDTH = &H40
LVCF_DEFAULTWIDTH = &H80
LVCF_IDEALWIDTH = &H100
'#End If
End Enum
LucasMKG
....
-
May 13th, 2022, 03:54 PM
#23
Re: [RESOLVED] ColumnHeader.Tag Property
You'd have to ask MS why they didn't perfectly sync them up. Maybe post a reply on Raymond Chen's blog.
-
May 18th, 2022, 02:54 AM
#24
Thread Starter
Hyperactive Member
Re: [RESOLVED] ColumnHeader.Tag Property
What's the best way of getting '.lParam'; using '.Mask = HDI_LPARAM' ?
Code:
Private Property Get ColumnTreeGridAtIndex(ByVal lColumn As Long) As Long
'/* [get] column index
Dim lCt As Long
Dim uHDI As HDITEMW
ColumnTreeGridAtIndex = -1
If Not (m_lHGHwnd = 0) Then
If (lColumn < m_lColumnCount) Then
For lCt = 0 To (m_lColumnCount - 1)
With uHDI
.Mask = HDI_LPARAM 'HDI_ORDER ' LVCF_ORDER
SendMessage m_lHdrHwnd, HDM_GETITEM, lCt, ByVal VarPtr(uHDI)
'Debug.Print ".lParam = " & .lParam
If .lParam = ecsType_TreeGrid Then
ColumnTreeGridAtIndex = lCt
Debug.Print "ColumnTreeGridAtIndex = " & lCt
Exit For
End If
End With
Next lCt
End If
End If
End Property
LucasMKG
?
-
May 18th, 2022, 09:51 AM
#25
Re: [RESOLVED] ColumnHeader.Tag Property
Yeah I use a common function for it:
Code:
Private Function GetHDItemlParam(hWnd As Long, i As Long) As Long
Dim tHDI As HDITEM
tHDI.Mask = HDI_LPARAM
If Header_GetItem(hWnd, i, tHDI) Then
GetHDItemlParam = tHDI.lParam
End If
End Function
Private Function Header_GetItem(hwndHD As Long, iItem As Long, phdi As HDITEM) As Boolean
Header_GetItem = SendMessage(hwndHD, HDM_GETITEM, iItem, phdi)
End Function
-
May 19th, 2022, 01:46 AM
#26
Thread Starter
Hyperactive Member
Re: [RESOLVED] ColumnHeader.Tag Property
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|