Tuesday, November 29, 2005 2:07 PM
by
WhoIsKb
Winforms and SendMessage
I finally got a project where I can start playing with some winform stuff. I have been doing .net for a few years now, but only in the c#/asp.net world. I now have the chance to write an application in a winform environment, which I have been looking forward to.
One of the things I wanted to play with was customizing the listview. I wanted to set the listview up so that the column widths automatically adjust their width based on the data that is being displayed within them. Back in my VB6 days, we ended up subclassing a lot of the common controls and I have used Randy Birch's vbnet web site quite a bit, so I figured I would start there for the info. Since all of the code is in VB, I use this little vb to c# converter to convert some of the constants and such.
The next part was getting the send message called defined, so here is what I came up with:
public class UnsafeNativeMethods
{
public const int LVM_FIRST = 4096;
public const int LVM_SETCOLUMNWIDTH = (LVM_FIRST + 30);
public const int LVSCW_AUTOSIZE = -1;
public const int LVSCW_AUTOSIZE_USEHEADER = -2;
public UnsafeNativeMethods()
{
}
public IntPtr SendMessage(IntPtr hWnd, int msg, int wparam, int lparam)
{
return UnsafeNativeMethods.SendMessage(new HandleRef(this,hWnd), msg, wparam, lparam);
}
[DllImport("user32.dll", CharSet=CharSet.Auto)]
internal static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
}
Once I got that defined, I was able to create a method that would setup this extended style for my ListViewEx control:
UnsafeNativeMethods methods = new UnsafeNativeMethods();
for( int x=0;x<Columns.Count;x++ )
{
methods.SendMessage( this.Handle, UnsafeNativeMethods.LVM_SETCOLUMNWIDTH, x, UnsafeNativeMethods.LVSCW_AUTOSIZE_USEHEADER );
}
One final thing I had to do for the listview was to ensure that when the listview was resized that the far right column fills out the unused area of the listview. To ensure this, I had to override the WndPrc method and capture the onpaint method and reset that style:
protected override void WndProc( ref Message message )
{
const int WM_PAINT = 0xf ;
// if the control is in details view mode and columns
// have been added, then intercept the WM_PAINT message
// and reset the last column width to fill the list view
switch ( message.Msg )
{
case WM_PAINT:
if ( this.View == View.Details && this.Columns.Count > 0 )
this.Columns[this.Columns.Count - 1].Width = -2 ;
break ;
}
// pass messages on to the base control for processing
base.WndProc( ref message ) ;
}