当前位置: 首页 > news >正文

Delphi 窗体间通信之接口回调模式

 

Delphi 窗体间通信之事件回调模式 - 一曲轻扬 - 博客园 (cnblogs.com)

书接上例.这回我们将使用接口回调模式,来完成窗体间的通讯问题

核心套路:

  1. 定义接口(在弹出窗体单元)

  2. 实现接口(在主窗体/框架单元)

  3. 设置回调(创建时连接)

  4. 触发回调(事件发生时)


具体实现代码如下:

第一步:在 FMTop20Record 单元定义接口

// ==================== FMTop20Record.pas ====================
unit FMTop20Record;interface// ... 原有uses部分保持不变type// 1. 定义物料选择回调接口// GUID使用Ctrl+Shift+G生成,确保唯一性IMaterialSelectCallback = interface['{4C9F8A12-7B2C-4D8B-89A3-6F1B7E5D9F0A}']// 方法1:检查物料是否已存在(用于提示用户)function IsMaterialExists(MaterialID: Integer): Boolean;// 方法2:添加物料到入库单(核心业务逻辑)procedure AddMaterialToRK(MaterialID: Integer; MaterialCode, MaterialName, SpecModel, CustomerPartNo: string; WarehouseID: Integer);end;TTop20Record = class(TForm)// ... 原有组件声明privateFCallback: IMaterialSelectCallback;  // 存储接口引用public// 设置回调接口的方法procedure SetCallback(ACallback: IMaterialSelectCallback);property Callback: IMaterialSelectCallback read FCallback write SetCallback;// ... 原有方法声明end;// ... 原有实现部分// 2. 实现设置回调接口的方法
procedure TTop20Record.SetCallback(ACallback: IMaterialSelectCallback);
beginFCallback := ACallback;  // 保存主框架传递来的接口实例
end;// 3. 修改双击事件,通过接口回调
procedure TTop20Record.GridViewTop20CellDblClick(Sender: TcxCustomGridTableView;ACellViewInfo: TcxGridTableDataCellViewInfo; AButton: TMouseButton;AShift: TShiftState; var AHandled: Boolean);
varCurrentMaterialID: Integer;
beginAHandled := True;  // 阻止事件继续传播// 安全检查:确保有数据和回调接口if FDQTop20.IsEmpty or not Assigned(FCallback) thenExit;// 获取当前记录的物料ID(关键业务字段)CurrentMaterialID := FDQTop20.FieldByName('物料ID').AsInteger;// 4. 第一次接口调用:检查是否已存在if FCallback.IsMaterialExists(CurrentMaterialID) thenbegin// 业务逻辑:已存在时询问用户if MessageDlg('该物料已存在于入库单中,是否继续添加?',mtConfirmation, [mbYes, mbNo], 0) = mrNo thenExit;end;// 5. 第二次接口调用:执行添加操作
  FCallback.AddMaterialToRK(CurrentMaterialID,FDQTop20.FieldByName('物料代码').AsString,      // 物料代码FDQTop20.FieldByName('物料名称').AsString,      // 物料名称FDQTop20.FieldByName('规格型号').AsString,      // 规格型号FDQTop20.FieldByName('客户料号').AsString,      // 客户料号FDQTop20.FieldByName('仓库ID').AsInteger       // 仓库ID(用于收货仓库字段)
  );
end;

 

第二步:在 FrmRK 单元实现接口

// ==================== FrmRK.pas ====================
unit FrmRK;interfaceuses// ... 原有uses部分FMTop20Record,  // 引用窗体单元(这里不会造成循环,因为只是使用)// ... 其他uses
  System.Generics.Collections;typeTRK = class(TFrame, IMaterialSelectCallback)  // 关键:声明实现接口private// IMaterialSelectCallback 接口实现方法function IsMaterialExists(MaterialID: Integer): Boolean;procedure AddMaterialToRK(MaterialID: Integer; MaterialCode, MaterialName, SpecModel, CustomerPartNo: string; WarehouseID: Integer);public// ... 原有方法和属性end;implementation// 6. 实现接口方法1:检查物料是否存在
function TRK.IsMaterialExists(MaterialID: Integer): Boolean;
beginResult := False;// 遍历FDMemTable1(入库单临时表)查找相同物料IDFDMemTable1.DisableControls;  // 暂停UI刷新提高性能tryFDMemTable1.First;while not FDMemTable1.EOF dobeginif FDMemTable1.FieldByName('物料ID').AsInteger = MaterialID thenbeginResult := True;  // 找到相同物料ID
        Break;end;FDMemTable1.Next;end;finallyFDMemTable1.EnableControls;  // 恢复UI刷新end;
end;// 7. 实现接口方法2:添加物料到入库单
procedure TRK.AddMaterialToRK(MaterialID: Integer; MaterialCode, MaterialName, SpecModel, CustomerPartNo: string; WarehouseID: Integer);
begin// 在FDMemTable1中添加新记录
  FDMemTable1.Append;try// 设置各个字段值(与FMTop20Record中的查询字段对应)FDMemTable1.FieldByName('物料ID').AsInteger := MaterialID;FDMemTable1.FieldByName('物料代码').AsString := MaterialCode;FDMemTable1.FieldByName('物料名称').AsString := MaterialName;FDMemTable1.FieldByName('规格型号').AsString := SpecModel;FDMemTable1.FieldByName('客户料号').AsString := CustomerPartNo;FDMemTable1.FieldByName('收货仓库').AsInteger := WarehouseID;  // 对应仓库IDFDMemTable1.FieldByName('数量').AsFloat := 1.0;  // 默认数量FDMemTable1.FieldByName('备注').Clear;          // 清空备注
    FDMemTable1.Post;  // 提交记录// 用户反馈(可选)ShowMessage(Format('"%s"已添加到入库单', [MaterialName]));exceptFDMemTable1.Cancel;  // 发生异常时取消操作raise;               // 重新抛出异常end;
end;// 8. 修改原有方法,设置接口回调
procedure TRK.入库单号RightButtonClick(Sender: TObject);
var rkobj: string;FM: TTop20Record;
begin// ... 原有验证逻辑(检查入库对象等)// 创建Top20记录窗体FM := TTop20Record.Create(nil);try// 设置窗体属性(原有逻辑)FM.sobj := 入库对象.Text;// 构建SQL(原有逻辑)if SCLKRaBtn.Checked thenrkobj := Format('部门ID=%d', [入库对象.Tag])elserkobj := Format('供应商ID=%d', [入库对象.Tag]);FM.isql := 'SELECT DISTINCT top 20 入库单.日期, 入库单.物料ID, ' +'物料代码, 物料名称, 规格型号, 客户料号, 助记码, ' +'物料信息.材质, 仓库列表.仓库ID, 仓库列表.仓库名称 ' +'FROM (入库单 LEFT JOIN 物料信息 ON 入库单.物料ID = 物料信息.物料ID) ' +'LEFT JOIN 仓库列表 ON 物料信息.仓库ID = 仓库列表.仓库ID ' +'WHERE ' + rkobj;// 9. 关键连接:将自身(实现接口的TRK实例)设置为回调FM.Callback := Self;  // Self就是TRK的当前实例,它实现了IMaterialSelectCallback// 加载数据并显示窗体
    FM.GetData;FM.ShowModal;finallyFM.Free;end;
end;

 

套路总结表

 
步骤所在单元关键操作目的
1. 定义接口 FMTop20Record 定义IMaterialSelectCallback 建立通信契约
2. 添加接口属性 FMTop20Record 添加FCallback字段和Callback属性 存储接口引用
3. 声明实现接口 FrmRK TRK = class(TFrame, IMaterialSelectCallback) 表明实现接口的能力
4. 实现接口方法 FrmRK 实现IsMaterialExistsAddMaterialToRK 提供具体业务逻辑
5. 设置回调连接 FrmRK FM.Callback := Self 建立两个对象的联系
6. 触发接口调用 FMTop20Record 在双击事件中调用FCallback.xxx 执行回调操作

实际贴合说明

  1. 字段对应:接口方法参数与FDQTop20查询字段完全对应

  2. 业务逻辑:检查重复、添加记录都使用实际的FDMemTable1

  3. 原有代码:保持原有的SQL构建逻辑和验证逻辑不变

  4. 数据结构:WarehouseID对应收货仓库字段,MaterialID是核心关联字段

这种模式的优势:

  • 解耦:两个单元不直接依赖对方的具体实现

  • 可测试:可以创建模拟对象测试接口

  • 可扩展:其他窗体也可实现同一接口

  • 类型安全:接口提供编译时类型检查

http://www.jsqmd.com/news/153499/

相关文章:

  • OpenCopilot与Slack深度整合:打造智能团队协作新体验
  • Multisim安装教程从零开始:构建个人电路仿真实验室
  • 2025年知名的燃气台车炉/台车炉厂家推荐及采购指南 - 品牌宣传支持者
  • Notepads:重新定义Windows文本编辑体验的5大理由
  • Unity Spaceship Demo完整入门指南:打造AAA级第一人称太空体验
  • 2025年苏作红木信誉厂家推荐:苏作红木来图定制/精品定制靠谱公司有哪些? - 工业品牌热点
  • 2025年终GEO优化公司推荐:聚焦垂直行业实效的5强服务商深度解析 - 十大品牌推荐
  • 零基础也能轻松掌握的电子设计入门指南 [特殊字符]
  • 图解Keil5安装步骤:解决常见报错问题
  • 【Java毕设全套源码+文档】基于JavaScript的在线考试系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • YOLO在建筑工地的应用:安全帽与反光衣识别
  • 2025年终GEO优化公司推荐:聚焦垂直行业案例的5强榜单深度测评 - 十大品牌推荐
  • BrowserBox完整使用指南:5步搭建安全远程浏览器隔离系统
  • YOLO推理服务支持负载均衡,横向扩展无压力
  • 2025年高端极简家具/现代家具厂家最新用户好评榜 - 品牌宣传支持者
  • 【Java毕设全套源码+文档】基于springboot的亚运会志愿者管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • GEO优化公司哪家技术强?2025年终5家服务商权威评测及最终推荐! - 十大品牌推荐
  • 如何快速掌握ANSYS Fluent:2024最新流体仿真学习指南
  • YOLO模型推理支持模型热插拔,无缝替换
  • 【Java毕设全套源码+文档】基于Java的电影院售票管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 【Java毕设源码分享】基于springboot+vue的房屋买卖平台的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 2025最新!9个AI论文工具测评:本科生毕业论文写作全攻略
  • YOLO目标检测支持灰度发布,新旧模型平滑切换
  • YOLO目标检测支持动态批处理,提升吞吐量
  • 5个高效使用Apache Druid REST API的实战技巧
  • YOLO在矿山安全监测中的应用:人员违规闯入识别
  • uni-ui组件库终极指南:快速上手跨端开发
  • 【Java毕设全套源码+文档】基于springboot的房屋买卖平台的设计与实现(丰富项目+远程调试+讲解+定制)
  • 如何快速掌握275种CAD字库的终极使用指南
  • 2025年靠谱的地面变形缝最新TOP品牌厂家排行 - 品牌宣传支持者