梦见亲人要重新结婚: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;