我用ListView控件,想固定其前几列,如何做到?请指教!

解决方案 »

  1.   

    {*******************************************************}
    {                                                       }
    {  ComponentName : SJListView                           }
    {  Version       : 2.2a                                 }
    {  Author        : SJ(小笨苯)                           }
    {  E_Mail        : [email protected]                     }
    {  Last Modified : 2002-5-15                            }
    {  History       :                                      }
    {  修改          : 2004-12-25 afan              }
    {                                                       }
    {*******************************************************}unit SJListView;interfaceuses
      Windows, Messages, SysUtils, Classes, ComCtrls, Commctrl, WinSock, Controls;type
      TListView2 = class(TListView)
      private
        { Private declarations }
        ArrowUp : HBitMap;
        ArrowDown : HBitMap;
        CurColumn: integer;
        vHandle: HWND;    procedure SetHeaderBitmap(Col: integer);//画Header
      protected
        { Protected declarations }
        //procedure WndProc(var Msg : TMessage); override;
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
        procedure CreateWnd; override;
        destructor Destroy; override;
      published
        { Published declarations }
      end;type
      TMainListview = class(TListview2)
      private
        FEnabledColumnSort: boolean;
      protected
        procedure WndProc(var Msg: TMessage); override;
      Public
        constructor Create(AOwner: TComponent); override;
      Published
        property EnabledColumnSort: boolean read FEnabledColumnSort write FEnabledColumnSort;
      end;
    type
      TMyListview = class(TListview2)
      protected
        procedure WndProc(var Msg: TMessage); override;
    end;procedure Register;const
      COLUMN_UP   = 1;     //向上
      COLUMN_DOWN = -1;    //向下
      //COLUMN_SHOW = 2;     //显示的列
      COLUMN_HIDE = -2;    //隐藏的列
    implementation{$R SJListView.res}
    { 通用排序函数 }
    Function CustomSortProc( Item1, Item2 : TListItem; lParam : LongInt ) : Integer; stdcall;
    begin
       Result:=0;
       if (Item1=nil) or (Item2=nil)then
         exit;
       if lParam = 0 then
          result := CompareText(Item1.Caption,Item2.Caption )
       else if lparam > 0 then begin
         { 有的列可能是空的null,点击排序会raise exception }
         if (LParam > Item1.SubItems.Count) or (LParam > Item2.SubItems.Count) then
           exit;
          result := CompareText(Item1.SubItems[Lparam-1],Item2.SubItems[Lparam-1]);
       end;
       Result:= Result * Item1.ListView.Column[lParam].Tag ;
    end;
    function CustomSortProcMain( Item1, Item2 : TListItem; lParam : LongInt ) : Integer; stdcall;
    var
      ip1,ip2:cardinal;
      a,b: integer;
      s1,s2:String;
    begin
       Result:=0;
       if (Item1 = nil)or(Item2 = nil)then
         exit;
       { 有的列可能是空的null,点击排序会raise exception }
       if LParam > 0 then begin
         if (LParam > Item1.SubItems.Count) then begin
           result:= -1;
           exit;
         end
         else if (LParam > Item2.SubItems.Count) then begin
           result:= 1;
           exit;
         end;
       end;   if lParam = 0 then
          result := CompareText(Item1.Caption,Item2.Caption )
       else if lparam =2 then begin //排序 ip 采用新算法
         s1:=Item1.SubItems[1];
         s2:=Item2.SubItems[1];
         result:= CompareText(s1,s2);
       end
       else begin
         { 有图片的项目 }
         a:= Item1.SubItemImages[LParam-1];
         b:= Item2.SubItemImages[LParam-1];
         if  a + b <> -2 then
           result:= a - b
         else
          result := CompareText(Item1.SubItems[Lparam-1],Item2.SubItems[Lparam-1]) ;
       end;   Result:= Result * Item1.ListView.Column[lParam].Tag ;
    end;constructor TListview2.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      ArrowUp := LoadImage(hInstance, 'ArrowUp', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
      ArrowDown := LoadImage(hInstance, 'ArrowDown', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
      //SetHeaderBitmap;
    end;procedure TListview2.CreateWnd;
    begin
      inherited CreateWnd;
      if HandleAllocated then HandleNeeded;
      vHandle := ListView_GetHeader(Handle);
    end;destructor TListview2.Destroy;
    begin
      DeleteObject(ArrowUp);
      DeleteObject(ArrowDown);
      inherited Destroy;
    end;
      

  2.   


    procedure TListview2.SetHeaderBitmap(Col: integer);
    var
      HdItem : THdItem;
    begin
      FillChar(HdItem, SizeOf(HdItem), #0);  HdItem.Mask := HDI_FORMAT;
      Header_GetItem(vHandle, Col, HdItem);
      HdItem.Mask := HDI_BITMAP or HDI_FORMAT;  if Column[Col].Tag = COLUMN_DOWN then begin { 反向 }
        HdItem.fmt := HdItem.fmt or HDF_BITMAP or HDF_BITMAP_ON_RIGHT;
        HdItem.hbm := LoadImage(hInstance, 'ArrowDown', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
      end
      else if Column[Col].Tag = COLUMN_UP then begin { 正向 }
        HdItem.fmt := HdItem.fmt or HDF_BITMAP or HDF_BITMAP_ON_RIGHT;
        HdItem.hbm := LoadImage(hInstance, 'ArrowUp', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
      end
      else begin{ 消除箭头 }
        HdItem.fmt := HdItem.fmt and not (HDF_BITMAP or HDF_BITMAP_ON_RIGHT);
        HdItem.hbm := 0;
      end;  Header_SetItem(vHandle, Col, HdItem);
    end;(*
    procedure TListview2.WndProc(var Msg : TMessage);
    var
      pHD : PHDNotify;
      i: integer;
    begin
      inherited WndProc(Msg);  if Msg.Msg = WM_NOTIFY then //如果截获的消息是WM_NOTIFY
      begin
        pHD := PHDNotify(Msg.LParam);
        HwndFrom:= pHD.Hdr.hwndFrom ;
        if (hwndFrom = vHandle) and (vHandle <> 0) then begin
          wmCode:= 0;
          Case pHD.HDr.code of
            { 如果是点击Header }
            HDN_ITEMCLICK,HDN_ITEMCLICKW:
              begin
                CurColumn := Columns.Items[pHD.item].Index;
                wmCode:= pHD.Hdr.code ;
                { 做标记,正向或反向排序 }
                  for i:= 0 to Columns.Count - 1 do begin
                    if I = CurColumn then begin
                      if Column[I].Tag = 0 then
                        Column[I].Tag := 1
                      else
                        Column[I].Tag := -1 * Column[I].Tag ;
                      SetHeaderBitmap(I);
                    end
                    else begin
                      if Column[I].Tag <> 0 then begin
                        Column[I].Tag := 0;
                        SetHeaderBitmap(I);
                      end;
                    end;
                  end; {of FOR}            { 排序 }
                //CustomSort(@CustomSortProc, CurColumn);
              end;        { 拖动改变宽度时,ColumnItem <> 原来排序的列 }
            HDN_ENDTRACK,HDN_ENDTRACKW:
              Begin
                CurColumn:= Columns.Items[pHD.item].Index;
                if Columns[CurColumn].Tag <> 0 then
                  SetHeaderBitmap(CurColumn);
              end;
          end;
        end;
      end;
    end;
    *)Procedure TMyListview.WndProc(var Msg: TMessage);
    var
      pHD : PHDNotify;
      i: integer;
    begin
      inherited WndProc(Msg);  if Msg.Msg = WM_NOTIFY then //如果截获的消息是WM_NOTIFY
      begin
        pHD := PHDNotify(Msg.LParam);
        if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin
          Case pHD.HDr.code of
            { 如果是点击Header }
            HDN_ITEMCLICKA,HDN_ITEMCLICKW:
              begin
                CurColumn := Columns.Items[pHD.item].Index;
                { 做标记,正向或反向排序 }
                  for i:= 0 to Columns.Count - 1 do begin
                    if I = CurColumn then begin
                      if Column[I].Tag = 0 then
                        Column[I].Tag := COLUMN_UP
                      else
                        Column[I].Tag := -1 * Column[I].Tag ;
                      SetHeaderBitmap(I);
                    end
                    else begin
                      if Column[I].Tag <> 0 then begin
                        Column[I].Tag := 0;
                        SetHeaderBitmap(I);
                      end;
                    end;
                  end; {of FOR}            { 排序 }
                CustomSort(@CustomSortProc, CurColumn);
              end;        { 拖动改变宽度时,ColumnItem <> 原来排序的列 }
            HDN_ENDTRACKA,HDN_ENDTRACKW,HDN_DIVIDERDBLCLICKA,HDN_DIVIDERDBLCLICKW:
              Begin
                CurColumn:= Columns.Items[pHD.item].Index;
                if Columns[CurColumn].Tag <> 0 then
                  SetHeaderBitmap(CurColumn);
              end;
          end;
        end;
      end;
    end;{ 主窗口中的列表框 }
    constructor TMainListview.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      FEnabledColumnSort:= true;
    end;procedure TMainListview.WndProc(var Msg: TMessage);
    var
      pHD : PHDNotify;
      i: integer;
    begin
      { 如果截获的消息是WM_NOTIFY }
      if Msg.Msg = WM_NOTIFY then begin
        pHD := PHDNotify(Msg.LParam);
        Case pHD.HDr.code of
          HDN_BeginTrackA, HDN_BeginTrackW:
            if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin
              { 隐藏列 }
              if Columns.Items[pHD.item].Tag = COLUMN_HIDE then begin
                msg.Result := 1;
                exit;
              end;
            end;
        end; {of CASE}
      end;  inherited WndProc(Msg);  if Msg.Msg = WM_NOTIFY then
      begin
        pHD := PHDNotify(Msg.LParam);
        if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin
          Case pHD.HDr.code of
            { 如果是点击Header }
            HDN_ITEMCLICK,HDN_ITEMCLICKW:
              begin
                if not FEnabledColumnSort then exit;
                CurColumn := Columns.Items[pHD.item].Index;
                { 做标记,正向或反向排序 }
                  for i:= 0 to Columns.Count - 1 do begin
                    if I = CurColumn then begin
                      if Column[I].Tag = 0 then
                        Column[I].Tag := COLUMN_UP
                      else
                        Column[I].Tag := -1 * Column[I].Tag ;
                      SetHeaderBitmap(I);
                    end
                    else begin
                      if Column[I].Tag = COLUMN_HIDE then
                        SetHeaderBitmap(I)
                      { 对于隐藏的列,不要改变标记 }
                      else if Column[I].Tag <> 0 then begin
                        Column[I].Tag := 0;
                        SetHeaderBitmap(I);
                      end;
                    end;
                  end; {of FOR}            { 排序 }
                CustomSort(@CustomSortProcMain, CurColumn);
              end;        { 拖动改变宽度时,ColumnItem <> 原来排序的列 }
            HDN_ENDTRACKA,HDN_ENDTRACKW,HDN_DIVIDERDBLCLICKA,HDN_DIVIDERDBLCLICKW:
              Begin
                CurColumn:= Columns.Items[pHD.item].Index;
                if Columns[CurColumn].Tag <> 0 then
                  SetHeaderBitmap(CurColumn);
              end;
          end;
        end;
      end;
    end;
    procedure Register;
    begin
      RegisterComponents('Win32', [TMainListView, TMyListview]);
    end;
    end.