Click here to Skip to main content
Licence 
First Posted 13 Mar 2006
Views 41,844
Bookmarked 13 times

Disable Column Resizing in ListView Report Mode

By Jeremy A. Wilson | 13 Mar 2006
This article describes how to use the NativeWindow object to take control of the message processing of a ListView's column header. This allows the programmer to intercept messages and prevent or respond to things like column resizing.
1 vote, 11.1%
1

2
2 votes, 22.2%
3
1 vote, 11.1%
4
5 votes, 55.6%
5
3.94/5 - 9 votes
μ 3.94, σa 2.55 [?]

Introduction

I was recently tasked with figuring out a way to disable column resizing in a ListView control. After chasing leads on a Google search, reading documentation, and a little trial and error, I finally figured out how to do it. The solution is simple, elegant, and may be used as a basis for doing other things with the ListView control using the same technique.

Background

When the ListView control is placed in report mode, an additional child window is added to the control to hold column headers. The Windows class for this child window is a SysHeader32 class. Unfortunately, it appears that Microsoft neglected to expose a wrapper for this control in the .NET Framework, and provided no simple means to access to it.

Ultimately, this means that a whole host of Windows messages are being sent to the SysHeader32 window of your ListView control that fires no events for your control and to which you cannot respond.

Solution

The solution is a three step process:

  1. Get a Windows handle for the ListView's SysHeader32 child window.
  2. Use the Windows handle to somehow take over message handling for its window.
  3. Write code to respond to the messages of interest to accomplish our goal.

Step 1

The first step is easy. Remember the good ol' days of Win32 API calls? Well...they still work as well in Visual Basic .NET as they did in VB6. Put the following declarations in a scope reachable by your form load event:

Private Declare Function GetWindow Lib "user32" Alias "GetWindow" _
       (ByVal hwnd As IntPtr, ByVal wCmd As Integer) As IntPtr
Private Const GW_CHILD As Integer = 5
Dim SysHdr32Handle As IntPtr

and in your form load event, add the following:

SysHdr32Handle = GetWindow(ListView1.Handle, GW_CHILD)

The code above assumes you've created a form window and drawn a ListView control on it. Since the ListView control only has one child window (the SysHeader32 window), we can rest easy knowing this call will obtain its Windows Handle.

Step 2

We now need a way to intercept messages being sent to the child window. Fortunately, the .NET Framework Class Library contains a class designed especially for this purpose - the NativeWindow class. The MSDN help description for the class states:

Provides a low-level encapsulation of a window handle and a window procedure.

To use the class, we need to create a new class that inherits the NativeWindow class so we can override the WndProc message handling function to do what we want. Add the following class definition to your form code:

Private Class ListViewHeader
    Inherits System.Windows.Forms.NativeWindow
    Private ptrHWnd As IntPtr

    Protected Overrides Sub WndProc(ByRef m As _
                        System.Windows.Forms.Message)
        ' We'll add this in step 3

        MyBase.WndProc(m)
    End Sub

    Protected Overrides Sub Finalize()
        Me.ReleaseHandle()
        MyBase.Finalize()
    End Sub

    Public Sub New(ByVal ControlHandle As IntPtr)
        ptrHWnd = ControlHandle
        Me.AssignHandle(ptrHWnd)
    End Sub
End Class

Of course, we'll need a form global variable declaration to work with, and we'll need to initialize our instance of the class. Put the following declaration in your form class declaration:

Private ListViewHeader1 As ListViewHeader

Then add the following line of code to your form load event:

SysHdr32Handle = _
  GetWindow(ListView1.Handle, GW_CHILD) ' <-- added this in step 1
ListViewHeader1 = New ListViewHeader(SysHdr32Handle)

Step 3

Now that we have a way to receive messages, we can add code to do something about them. In this simple example, we are going to intercept WM_SETCURSOR and WM_LBUTTONDOWN messages and throw them away to prevent the user from seeing a resize column cursor and from being able to resize the columns. Modify the WndProc method of our ListViewHeader class as follows:

Protected Overrides Sub WndProc(ByRef m _
          As System.Windows.Forms.Message)
    Select Case m.Msg
        Case Is = &H20  ' WM_SETCURSOR
            m.Msg = 0
        Case Is = &H201  ' WM_LBUTTONDOWN
            m.Msg = 0
    End Select

    MyBase.WndProc(m)
End Sub

Conclusion

The above example gives you a bare-bones method of getting a handle on those SysHeader32 messages. As such, the example is rather crude. For instance, what if you wanted to disable column resizing for two ListView controls? As written above, you'd have to create two distinct classes. A robust implementation would add events to the class definition and fire them when Windows messages are received in the WndProc method, thus allowing the creator of the class instance to deal with them. For now, however, this will get you started.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Jeremy A. Wilson

Software Developer

United States United States

Member
I graduated from the University of North Texas in 2005. I live in North Texas with my fiance and two children. I work for a company that develops property appraisal and collections software and GIS systems to tax districts.
 
I first learned to program on a Commodore 64 when I was 12 years old. The rest is history...

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionHow to - Disable double click and alow column click PinmemberMartin Lowery3:52 14 Feb '10  
Generaldobbeltclick between columnheads PinmemberMegabitdk3:58 21 Apr '08  
GeneralRe: dobbeltclick between columnheads PinmemberTheLarrikin8:47 28 Sep '09  
QuestionPlaying with View mode Pinmemberklaus@gubbernet.com23:27 21 Nov '06  
QuestionPrevent certain columns resizing PinmemberNeil2202718:25 14 Nov '06  
QuestionThe code? PinmemberClorange21:18 27 Sep '06  
Generalusing in Derived class PinmemberMohsen Kokabi16:09 4 Jul '06  
GeneralRe: using in Derived class Pinmemberesskar2:25 26 Sep '07  
GeneralThanks a lot Pinmemberdl4gbe2:13 14 Mar '06  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120210.1 | Last Updated 13 Mar 2006
Article Copyright 2006 by Jeremy A. Wilson
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid