ListView control header events?

A

aualias

The ListView control allows you to reorder and resize columns, but a cannot
find out how to catch events coming from the header. I have looked at all
the WM_NOTIFY events that come through. Only the click seems to fire.

I would like to be able to save the changes to the header that are made by
the user. How do I do this?

Thanks for any help.

Alfredo
 
A

aualias

Jeffrey,

Thanks for the sample. I never actually checked for resizing - I just saw
stuff on the Internet that indicated that no header messages are sent and
assumed that it was true. What I looked at, and what I am most interested
in, are the messages sent when you reorder the column headers.

I did look for the reorder messages and found nothing that matched values in
commctrl.h. ( I did find some messages that came between the gaps in
sequential values in commctrl.h, but I do not know what to do with them. )

Alfredo



"Jeffrey Tan[MSFT]" said:
Hi Alfredo,

When the user drags the certain column header, the column header will send
a WM_NOTIFY message with HDN_BEGINTRACKW(A) code to the ListView, and when
the draging is over, a WM_NOTIFY message with HDN_ENDTRACKW(A) code will
also be sent to ListView control.

So, we can inherit from the ListView class, override WndProc method, then
intercept the WM_NOTIFY message with these 2 notify code to get the column
width draging event. Sample code lists below:

private const uint WM_NOTIFY=0x004E;
private const uint HDN_BEGINTRACKA = 0xFFFFFECE;
private const uint HDN_BEGINTRACKW = 0xFFFFFEBA;
private const uint HDN_ENDTRACKA = 0xFFFFFECD;
private const uint HDN_ENDTRACKW = 0xFFFFFEB9;

[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public uint hwndFrom;
public uint idfrom;
public uint code;
}

protected override void WndProc(ref Message m)
{
if(m.Msg==WM_NOTIFY)
{
NMHDR nm=(NMHDR)m.GetLParam(typeof(NMHDR));
if(nm.code==HDN_BEGINTRACKA||nm.code ==HDN_BEGINTRACKW)
{
//the draging begins, just save the column width setting, call
savecolumnsetting() method I listed below
}
else if(nm.code == HDN_ENDTRACKA ||nm.code == HDN_ENDTRACKW)
{
//draging is over
}
}
base.WndProc (ref m);
}
To record and restore the column width setting, we may write 2 methods for
our own, like this:
ArrayList al=new ArrayList();
public void savecolumnsetting()
{
al.Clear();
for(int i=0;i<this.Columns.Count;i++)
{
al.Add(this.Columns.Width);
}
}

public void restorecolumnsetting()
{
for(int i=0;i<this.Columns.Count;i++)
{
this.Columns.Width=(int)al;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Usage:
Because whenever we drag the column header, its original width setting is
saved in arraylist, we can use a button to invoke restorecolumnsetting()
method, then when we clicked the button, the listview headers will restore
to its original width.

It works well on my side, I will attach the sample project in this reply
for your information.
============================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi Alfredo,

Thanks very much for your feedback!

Yes, I see your concern is on reorder issue now. But, winform listview does
not support column headers reorder. I am not sure what does your "column
header reorder" mean. Does it mean the behavior: if we click certain column
header all the rows will be reordered alphabetically? I think this should
be the resort behavior of the one column.

Anyway, the reoder of column headers is not supported and please confirm
the meaning of "column header reorder" for me, so I can help you better.
Thanks
============================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
C

Claes Bergefall

Sounsd like you're looking for HDN_BEGINDRAG and HDN_ENDDRAG

private const int WM_NOTIFY = 0x004E;
private const int HDN_FIRST = -300
private const int HDN_BEGINDRAG = HDN_FIRST-10;
private const int HDN_ENDDRAG = HDN_FIRST-11;

Note that the AllowColumnReorder property must be true

/claes


aualias said:
Jeffrey,

Thanks for the sample. I never actually checked for resizing - I just saw
stuff on the Internet that indicated that no header messages are sent and
assumed that it was true. What I looked at, and what I am most interested
in, are the messages sent when you reorder the column headers.

I did look for the reorder messages and found nothing that matched values in
commctrl.h. ( I did find some messages that came between the gaps in
sequential values in commctrl.h, but I do not know what to do with them. )

Alfredo



"Jeffrey Tan[MSFT]" said:
Hi Alfredo,

When the user drags the certain column header, the column header will send
a WM_NOTIFY message with HDN_BEGINTRACKW(A) code to the ListView, and when
the draging is over, a WM_NOTIFY message with HDN_ENDTRACKW(A) code will
also be sent to ListView control.

So, we can inherit from the ListView class, override WndProc method, then
intercept the WM_NOTIFY message with these 2 notify code to get the column
width draging event. Sample code lists below:

private const uint WM_NOTIFY=0x004E;
private const uint HDN_BEGINTRACKA = 0xFFFFFECE;
private const uint HDN_BEGINTRACKW = 0xFFFFFEBA;
private const uint HDN_ENDTRACKA = 0xFFFFFECD;
private const uint HDN_ENDTRACKW = 0xFFFFFEB9;

[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public uint hwndFrom;
public uint idfrom;
public uint code;
}

protected override void WndProc(ref Message m)
{
if(m.Msg==WM_NOTIFY)
{
NMHDR nm=(NMHDR)m.GetLParam(typeof(NMHDR));
if(nm.code==HDN_BEGINTRACKA||nm.code ==HDN_BEGINTRACKW)
{
//the draging begins, just save the column width setting, call
savecolumnsetting() method I listed below
}
else if(nm.code == HDN_ENDTRACKA ||nm.code == HDN_ENDTRACKW)
{
//draging is over
}
}
base.WndProc (ref m);
}
To record and restore the column width setting, we may write 2 methods for
our own, like this:
ArrayList al=new ArrayList();
public void savecolumnsetting()
{
al.Clear();
for(int i=0;i<this.Columns.Count;i++)
{
al.Add(this.Columns.Width);
}
}

public void restorecolumnsetting()
{
for(int i=0;i<this.Columns.Count;i++)
{
this.Columns.Width=(int)al;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Usage:
Because whenever we drag the column header, its original width setting is
saved in arraylist, we can use a button to invoke restorecolumnsetting()
method, then when we clicked the button, the listview headers will restore
to its original width.

It works well on my side, I will attach the sample project in this reply
for your information.
============================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no
rights.
 
J

Jeffrey Tan[MSFT]

Oh, yes, I think Claes should be right. I missed
ListView.AllowColumnReorder property.

After enabling the column reorder, we can do the similiar as my last reply
sample code to intercept the WM_NOTIFY message and determine the
HDN_BEGINDRAG and HDN_ENDDRAG notification code. The program logic is the
same as my last reply's sample code.

Hope this helps

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
A

aualias

Jeffrey and Claes,

Interesting...

I am getting the codes HDN_BEGINDRAG and HDN_ENDDRAG (0xFFFFFECA and
0xFFFFFEC9) in your demo app, but not in mine. I have to check what else is
going on.

Thanks for your help.

David
 
A

aualias

Hi Jeffrey,

I discovered my problem...
I thought that the notifications were coming from the ListView and was
filtering the messages. However, duh, they were coming from the header.

One more problem, though...
After reordering the columns, how do I detect the new configuration so that
I can save it? I did a dump of the columns before and after reordering and
there was no change in the order of the collection.

Here is the dump method:
private void DumpListView(ListView lv)
{
Trace.WriteLine("\r\nDumping Column Headers...");

for ( int i = 0; i < lv.Columns.Count; i++ )
Trace.WriteLine(lv.Columns.Text);

// variation - same result...
// foreach ( ColumnHeader hdr in lv.Columns )
// {
// Trace.WriteLine(hdr.Text);
// }

Trace.WriteLine("End Dump Column Headers...\r\n");
}

Thanks.

Alfredo
 
A

aualias

Jeffrey,

Thank you for the example. And thanks for the quick response. I was just
in the process of figuring out how to marshal an array for SendMessage(),
but was not coming up with any examples. Looking at how you did it, it is
pretty obvious - but I was thinking of doing custom marshaling. I did not
think of changing the footprint for SendMessage(). You saved me a lot of
time.

Alfredo
 
J

Jeffrey Tan[MSFT]

You are welcome!! If you need further help, please feel free to tell me,
thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top