Jerry@完美生活

青春的岁月,我们身不由己,只因这胸中,燃烧的梦想;青春的岁月,放浪的生涯,就任这时光,奔腾如流水。 体会这狂野,体会孤独,体会这欢乐,爱恨离别;体会这狂野,体会孤独,这是我的完美生活,也是你的完美生活。 我多想看到你,那依旧灿烂的笑容,再一次释放自己,胸中那灿烂的情感,我多想告诉你,那依旧灿烂的笑容,再一次释放自己。

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

.NET Framework 1.1中的ListView有一个AllowColumnReordered属性,设置为True后,用户可以通过鼠标拖动列来重新设置列的顺序(ViewStyle是Detail的时候才有效)。但是,ListView没有任何事件通知用户列的顺序被改变了。.NET Framework 2.0 中提供了事件ColumnReordered。我们可以通过扩展.NET Framework 1.1中的ListView来添加这个事件。

当用户拖动列的时候,会有一个BeginDrag的Windows通知消息,结束后,会有一个EndDrag 的Windows通知消息,因此,我们可以截获这个EndDrag的Windows通知消息,抛出ColumnReordered事件。

首先重载WndProc方法:

protected override void WndProc(ref Message m)
        {
            
if (m.Msg == WM_NOTIFY && WmNotify(ref m)) {
                
// it's handled in WmNotify, WndProc does not handle it again.
                return;
            }

            
base.WndProc (ref m);
        }

在WmNotify(ref m)中,比较Column的显示序号,如果不等,就表示Column的顺序被改变了,抛出ColumnReordered事件。ColumnReorderedEventArgs从CancalEventArgs派生,用户可以在事件接受里面拒绝更改Column的顺序。
private bool WmNotify(ref Message m) {
            NMHDR nmhr 
= (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
            
if (nmhr.code != HDN_ENDDRAG) {
                
return false;
            }

            
            
// it's end drag.
            NMHEADER nmheader = (NMHEADER) m.GetLParam(typeof(NMHEADER));
            
if (nmheader.pItem == IntPtr.Zero) {
                
return false;
            }

            
            HDITEM hditem 
= (HDITEM) Marshal.PtrToStructure(nmheader.pItem, typeof(HDITEM));
            
if ((hditem.mask & HDI_ORDER) == HDI_ORDER) {
                
// it's changing column order..
                int oldIndex = GetColumnDisplayIndex(nmheader.iItem);
                
int newIndex = hditem.iOrder;

                
if (oldIndex != newIndex) {
                    
// raise ColumnReordered event.
                    ColumnHeader header = Columns[nmheader.iItem];
                    ColumnReorderedEventArgs e 
= new ColumnReorderedEventArgs(newIndex, oldIndex, header);
                    OnColumnReordered(e);

                    
if (e.Cancel) {
                        
// column reorder is canceled.
                        m.Result = new IntPtr(Convert.ToInt32(true));
                        
return true;
                    }

                            
                    
return false;
                }

            }


            
return false;
        }

由于,Column的顺序改变以后,ListView的Columns里面ColumnHeader的顺序并没有被改变,改变的只是ColumnHeader的显示顺序,所以有必要提供方法,让用户获取某列的显示顺序。
        public int GetColumnDisplayIndex(int index) {
            LVCOLUMN column 
= new LVCOLUMN();
            column.mask 
= LVCF_ORDER;
            SendMessage(Handle, LVM_GETCOLUMN, index, 
ref column);
            
return column.iOrder;
        }


程序用到了很多Win32的常量和数据结构,可以查看MSDN获取详细信息。点击这里下载完整源代码>>

posted on 2006-03-01 21:09  Jerry Zhou  阅读(1234)  评论(0)    收藏  举报