You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi中DBGrid处于编辑状态时如何禁用鼠标点击切换记录

DBGrid编辑状态禁用鼠标点击切换记录实现方法

你之前编写的键盘、鼠标事件拦截逻辑失效,核心原因是DBGrid响应鼠标左键点击触发记录切换的执行时机早于公开的OnMouseDown/OnMouseUp事件触发时间,事件触发时记录自动保存、切换的动作已经完成,此时拦截无法达到预期效果。

以下提供两种可直接落地的实现方案,无需开发自定义DBGrid控件:

方案1:数据集层面拦截(优先推荐,覆盖全场景)

所有触发记录切换的操作(键盘方向键、鼠标点击、鼠标滚轮、代码调用跳转记录等)最终都会触发绑定数据集的滚动动作,且编辑状态下点击其他行时会先触发自动保存逻辑,直接在数据集事件节点拦截即可覆盖所有场景,不需要单独处理各类输入事件。

  • 首先为绑定的数据集(即代码中dbdata.fininkrg)添加BeforeScroll事件处理:
procedure Tf_inkfak.fininkrgBeforeScroll(DataSet: TDataSet);
begin
  if (DBGrid3.SelectedField <> nil)
    and (DBGrid3.SelectedField.DisplayLabel = 'GRB_REK')
    and (DataSet.State in [dsEdit]) then
    Abort;
end;
  • 再为同一数据集添加BeforePost事件处理,拦截编辑状态下点击其他行触发的自动保存动作,可按需增加提示:
procedure Tf_inkfak.fininkrgBeforePost(DataSet: TDataSet);
begin
  if (DBGrid3.SelectedField <> nil)
    and (DBGrid3.SelectedField.DisplayLabel = 'GRB_REK')
    and (DataSet.State in [dsEdit]) then
  begin
    // 可按需增加提示:ShowMessage('请先提交或取消当前编辑后再切换记录');
    Abort;
  end;
end;

该方案逻辑统一,不会遗漏记录切换入口,后续新增其他记录跳转操作时也无需额外补充拦截代码,维护成本最低。

方案2:窗口消息层面拦截鼠标操作

如果不想修改数据集层面的逻辑,可以直接拦截DBGrid窗口收到的鼠标类消息,在消息处理最前端阻断操作:

  • 在窗体类的私有段声明自定义窗口过程与原过程存储变量:
type
  Tf_inkfak = class(TForm)
    // 原有控件、方法声明保持不变
  private
    FOldDBGrid3WndProc: TWndMethod;
    procedure DBGrid3WndProc(var Message: TMessage);
  end;
  • 在窗体创建事件(FormCreate)中替换DBGrid原窗口过程:
procedure Tf_inkfak.FormCreate(Sender: TObject);
begin
  FOldDBGrid3WndProc := DBGrid3.WindowProc;
  DBGrid3.WindowProc := DBGrid3WndProc;
end;
  • 实现自定义窗口过程,拦截编辑状态下的鼠标左键点击、双击、滚轮消息:
procedure Tf_inkfak.DBGrid3WndProc(var Message: TMessage);
var
  AllowOp: Boolean;
begin
  AllowOp := True;
  if (DBGrid3.SelectedField <> nil)
    and (DBGrid3.SelectedField.DisplayLabel = 'GRB_REK')
    and (dbdata.fininkrg.State in [dsEdit]) then
  begin
    if (Message.Msg = WM_LBUTTONDOWN)
      or (Message.Msg = WM_LBUTTONDBLCLK)
      or (Message.Msg = WM_MOUSEWHEEL) then
      AllowOp := False;
  end;

  if AllowOp then
    FOldDBGrid3WndProc(Message)
  else
    Message.Result := 0;
end;
  • 在窗体销毁事件(FormDestroy)中还原原窗口过程,避免内存异常:
procedure Tf_inkfak.FormDestroy(Sender: TObject);
begin
  DBGrid3.WindowProc := FOldDBGrid3WndProc;
end;

注意:该方案仅拦截鼠标类操作,你之前编写的KeyDown事件中拦截上下方向键的逻辑需要保留,才能覆盖键盘切换记录的场景。


内容的提问来源于stack exchange,提问作者Hans van der Rijst

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:31:14