This code prevents the specified column(s) of a ListView control from being resized by the user. It does that by subclassing the ListView control and watching for the HDN_BEGINTRACK and HDN_DIVIDERDBLCLICK notification codes. Additionally, it also provides appropriate feedback to the user by displaying the "Unavailable" cursor when the mouse is over the locked column divider. That is done by subclassing the ListView's Header control and handling the WM_SETCURSOR message.
The modLockLVCols.bas file in the attached project below has been inspired by the codes in the following threads:
Also included in the attachment is frmLockLVColsDemo.frm:
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
This code prevents the specified column(s) of a ListView control from being resized by the user. It does that by subclassing the ListView control and watching for the HDN_BEGINTRACK and HDN_DIVIDERDBLCLICK notification codes. Additionally, it also provides appropriate feedback to the user by displaying the "Unavailable" cursor when the mouse is over the locked column divider. That is done by subclassing the ListView's Header control and handling the WM_SETCURSOR message.
The modLockLVCols.bas file in the attached project below has been inspired by the codes in the following threads:
hi...
possible to use this code in a vba userform and listview in VBA for Excel?
Tks.
Sorry, but I have not tested that code in VBA. The Subclass function, however, will let you know if it works there. So, try it and see what happens.
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
Yeah, I got that idea from Chris001, who has been wondering how to accomplish that:
Originally Posted by Chris001
Unfortunately I still haven't found a way to hide the double-arrow cursor when moving over a locked column divider. WM_SETCURSOR doesn't 'fire' when the cursor is moved over a column divider.
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
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
I'm sorry, but could you please attach a screenshot of your ListView control here (click the Insert Image button on the editor's toolbar)? Please also state which column(s) of your ListView that you want to be locked.
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
I'm sorry, but could you please attach a screenshot of your ListView control here (click the Insert Image button on the editor's toolbar)? Please also state which column(s) of your ListView that you want to be locked.
after the last visible column a just have other 5 columns with size(0) and are hide(are only a service column) not important to show tath.
after the last visible column a just have other 5 columns with size(0) and are hide(are only a service column) not important to show tath.
So, your ListView control has a total of 15 columns, of which 10 are visible and 5 are hidden. Is that right?
I'll ask this again: which column(s) do you want to be locked?
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
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
Just a quick comment... Like luca90 I'm using your code in XL VBA. I've noticed that if any of the locked columns have a width of zero, then the "resize" pointer still shows when hovering between the two (non zero width) columns either side of the zero width column. Not really a problem, as the locking functionality persists.
Once again thank you. Up till now I've had to rely on various form events to trigger a sub which reset all my column widths. Flicker city!
but have prb when exit from form with unload me...
i have see other form are freezed, and ivba ide work not correctlly..
perphs i need to destroyed a object opened from lock listview routine?
but have prb when exit from form with unload me...
i have see other form are freezed, and ivba ide work not correctlly..
perphs i need to destroyed a object opened from lock listview routine?
Can you post the code in your Form's Unload event? (You're not using the End statement, are you?)
EDIT
Originally Posted by blackworx
Just a quick comment... Like luca90 I'm using your code in XL VBA. I've noticed that if any of the locked columns have a width of zero, then the "resize" pointer still shows when hovering between the two (non zero width) columns either side of the zero width column. Not really a problem, as the locking functionality persists.
This issue turns out to be quite easy to fix (thanks to Krool for suggesting this solution). Just add this constant declaration:
Code:
Private Const HHT_ONDIVOPEN As Long = &H8
And then modify this line:
Code:
If HDHTI.Flags And HHT_ONDIVIDER Then
To:
Code:
If HDHTI.Flags And (HHT_ONDIVIDER Or HHT_ONDIVOPEN) Then
Last edited by Bonnie West; Jan 2nd, 2017 at 11:00 AM.
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
Do you mean a less complex way of doing it than what Bonnie has posted? Not really... you could do it with a few less lines but you still have to subclass and intercept HDN_BEGINTRACK