梦见亲人要重新结婚:DBGridEh让选择的记录不随垂直滚动条滚动而移动 .

来源:百度文库 编辑:偶看新闻 时间:2024/05/06 04:01:01

 

 

 

 

 

 

 

 

使用Delphi的人都知道,Delphi中的Grid与PB或者其他的Grid有区别,就是在滚动时记录指针会跟着改变。能不能做到像PB中的DataWindow一样滚动时选定记录不改变呢?

 

方案一、使用内存表控件,Ehlib里面有现成的。

          问题:数据量较大时速度很慢,而且内存占用比较严重;

 

方案二、不使用DB类的Grid控件,使用stringgrid或者listview之类的,虚拟列表比如Virtual stringtree。

          缺点:使用起来比较麻烦,实现一些扩展功能不太方便。Virtual stringtree功能那是相当强大,但是使用不太容易。

 

方案三、对DBGrid或者DBGridEh控件进行修改,滚动时进行重画。经过反复测试和参考TopGrid觉得方案可行,能到达要求。下面重点讨论这种方案。

 

    实现步骤:(以DBGridEh5.2.80为基础进行修改,这个控件扩展比较容易)

 

1、将记录指针的焦点框去除(修改DBGRIDEH源码);

 

constructor TDBGridEhStyle.Create;
begin
  inherited Create;
  FGrids := TObjectList.Create(False);
{$IFDEF CIL}
  FWindowHandle := WinUtils.AllocateHWnd(StyleWndProc);
{$ELSE}
  FWindowHandle := {$IFDEF EH_LIB_6}Classes.{$ENDIF}AllocateHWnd(StyleWndProc);
{$ENDIF}
  FLuminateSelection := True;
  FIsDrawFocusRect := false;// True;   //是否显示焦点框
  SysColorChanged;
  FInTitleFitlerButtonStyle := ebsDropDownEh;
end;

 

2、重载滚动条事件;

procedure TSDBGridF.DBGridEhProc(var Message: TMessage); // 处理滚动条信息
var
  si: TScrollInfo;
  Par: WPARAM;
begin

  DoubleBuffered := True;

  case Message.Msg of
    WM_MOUSEWHEEL: //鼠标中键
      begin
        FillChar(si, SizeOf(si), 0);
        si.cbSize := SizeOf(si); //下一句设置所有信息标志掩码位, 以便拿全部信息
        si.fMask := SIF_TRACKPOS or SIF_RANGE or SIF_POS or SIF_PAGE;
        with TWMMouseWheel(Message) do
        begin
          GetScrollInfo(Handle, SB_VERT, si); // 拿滚动条相关信息
          if WheelDelta < 0 then //小于 0 则表示向下滚动
          begin
            if Keys = MK_CONTROL then //做点处理, 按下CTRL键,则翻页滚动.
              //PostMessage(D.Handle, WM_VSCROLL, SB_PAGEDOWN, 0)
              Par := SB_PAGEDOWN
            else
              //PostMessage(D.Handle, WM_VSCROLL, SB_LINEDOWN, 0)
              Par := SB_LINEDOWN; //不按特殊键,则单行滚动
            Perform(WM_VSCROLL, Par, 0);
          end
          else
          begin
            if Keys = MK_CONTROL then //同上,只是滚动方向相反
              Par := SB_PAGEUP
            else
              Par := SB_LINEUP;
            Perform(WM_VSCROLL, Par, 0);
          end;
        end;
      end;
    WM_VSCROLL: //纵向滚动条
      begin
        with TWMVScroll(Message) do
        begin
          //          if DataSource.DataSet.RecordCount < 30000 then
          //          begin
          case ScrollCode of
            SB_THUMBTRACK:
              begin
                Perform(WM_VSCROLL, SB_THUMBPOSITION, Pos);
              end;
          end;
        end;
      end;
  end;
  F(Message);
end;

 

3、重载MouseDown事件;

procedure TSDBGridF.MouseDown(Button: TMouseButton; // 鼠标按下
  Shift: TShiftState; X, Y: Integer);
var
  i: Integer;
begin

  inherited MouseDown(Button, Shift, X, Y);

  if Assigned(DataSource) then
  begin
    if (ssleft in shift) and (Y > 22 {表格头部高度}) then
    begin

      bSortFlag := False; // 排序标志取消

      for i := 0 to Columns.Count - 1 do
      begin
        Columns[i].Color := clWindow;
        Columns[i].Font.Color := clBlack;
      end;

      if SelectedRows.Count > 0 then
        if SelectedRows.CurrentRowSelected = True then
          Exit;

      if not (dgMultiSelect in Options) then
        SelectedRows.Clear; //如果不是多项选择时清空

      if (dgRowSelect in Options) then //需要进行选择时才进行选择
        SelectedRows.CurrentRowSelected := True;

      if DataSource.DataSet.Active then
        SaveBookmark;
    end;
  end;
end;

 

4、重载KeyDown事件。

procedure TSDBGridF.KeyDown(var Key: Word; Shift: TShiftState); //键按下
begin

  inherited KeyDown(Key, Shift);

  if not Assigned(DataSource) then
    Exit;
  if not Assigned(DataSource.DataSet) then
    Exit;
  if not DataSource.DataSet.Active then
    Exit;
  if DataSource.DataSet.RecordCount < 1 then
    Exit;
  if ((not (dgMultiSelect in Options)) and (not (dgRowSelect in Options))) then
    Exit;

  DoubleBuffered := True;
  Parent.DoubleBuffered := True;

  BeginUpdate;

  if Key in [33..36] then // PgUp PgDn End Home
  begin
    SelectedRows.Clear;
    SelectedRows.CurrentRowSelected := True;
    SaveBookmark;
  end;

  if Key = 38 then // Up
  begin
    try
      RestoreBookmark;
      DataSource.DataSet.Prior;
      SelectedRows.Clear;
      SelectedRows.CurrentRowSelected := True;
      SaveBookmark;
    except
    end;
  end;

  if Key = 40 then // Down
  begin
    try
      RestoreBookmark;
      DataSource.DataSet.Next;
      SelectedRows.Clear;
      SelectedRows.CurrentRowSelected := True;
      SaveBookmark;
    except
    end;
  end;
end;