关于窗口置屏的那个坑

从其它平台迁移而来 在开发多屏应用程序的时候,经常需要把某个窗口置到某个屏上的某个位置。以下是一个Delphi写的置屏方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 procedure ShowInMonitor(Sender: TObject; AIndex: Integer; ALeft: Integer = 0; ATop: Integer = 0); var lM: TMonitor; begin if Sender is TControl then begin if AIndex > Screen.MonitorCount - 1 then begin AIndex := 0; end; lM := Screen.Monitors[AIndex]; (Sender as TControl).Left := lM.Left + ALeft; (Sender as TControl).Top := lM.Top + ATop; end; end; Sender是需要置屏的窗口;AIndex是置屏的目标屏号,从0开始;ALeft是水平偏移量,ATop是垂直偏移量,默认均为0,即在目标屏的左上角。...

2019-03-01 16:16:46 · 1 分钟 · 慢步道人

DBGridEh显示、编辑标记字段

从其它平台迁移而来 在用Delphi开发数据库应用过程中,经常需要用到DBBrid来显示或编辑数据库表,但相对于IDE自带的DBBrid,DBGridEh显然要更好用一些(cxDBGrid也同样好使,这里只对DBGridEh进行说明)。 在数据库表结构设计时,通常会习惯使用整型字段来存储如男、女、已修改、已删除、已作废等具有标记性的信息,好处是占存储空间小且可扩展性强,缺点是显示方式不友好,但是,使用DBGridEh的一些设置可以弥补这个缺陷。 假设数据库里的表T_Demo里有一个表示性别的字段Sex,其用0表示男,1表示女,2表示未知,用DBGridEh显示时仍为0、1、2,十分不友好。这时只要做一点美化即可。 在DBGridEh的对应列的KeyList属性里分别加入0、1、2三个数字,每个数字一行,用代码实现的话就是: 1 2 3 4 5 //这里假设第一列就是性别,以下代码相同 DBGridEh.Columns[0].KeyList.Clear; DBGridEh.Columns[0].KeyList.Append('0'); DBGridEh.Columns[0].KeyList.Append('1'); DBGridEh.Columns[0].KeyList.Append('2'); 在DBGridEh的对应列的PickList属性里分别加入男、女、未知三行,用代码实现是: 1 2 3 4 DBGridEh.Columns[0].PickList.Clear; DBGridEh.Columns[0].PickList.Append('男'); DBGridEh.Columns[0].PickList.Append('女'); DBGridEh.Columns[0].PickList.Append('未知'); 这样,原先显示为0、1、2的性别就变成了男、女、未知。也可以加上图片来进一步美化。 放置一个TImagList控件,并命名为ilSex,然后分别添加三个图片,比如像卫生间的男、女图片和问号,注意添加后图片对应的索引,否则会张冠李戴。 在DBGridEh的ImagList属性里关联ilSex,并且设置ShowImageAndText属性为True,用代码是: 1 2 DBGridEh.ImagList := ilSex; DBGridEh.ShowImageAndText := True; 这样,性别这一列就有图片有文字,比0、1、2要友好很多,而且在编辑的时候也可以直接下拉进行选择来实现性别的录入。

2019-01-25 11:37:40 · 1 分钟 · 慢步道人

TClientDataSet的使用以及遇到的坑

从其它平台迁移而来 在Delphi未加入FireDAC之前,似乎是没有内存表控件的(也许有,可能我不知道吧),但是可以用TClientDataSet控件来做内存表使用,即使有了FireDAC可以使用TFDMemTable,我还是觉得TClientDataSet更好用一些。 做内存表使用 创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 with ClientDataSet do begin Close; //定义字段 with FieldDefs do begin Clear; Add('Field1', ftInteger, 0, False); Add('Field2', ftString, 0, False); ...... end; //创建结构 CreateDataSet; Open; end; 排序 在定义字段后,创建结构前,也可以指定排序字段。 1 IndexFieldNames := 'Field1'; 做缓存使用 需要结合TDataSetProvider来使用。以下示例以使用ADO组件为例。 拉取数据 方法1 TDBGrid->TDataSource->TClientDataSet->TDataSetProvider->TADOQuery->TADOConnection 1 2 3 4 5 6 7 ClientDataSet.ProviderName := DataSetProvider.Name; //设计器里设置过就不需要了 with ClientDataSet do begin Close; CommandText:='select * from T_Table'; Open; end; 方法2 TDBGrid->TDataSource...

2019-01-12 14:43:15 · 1 分钟 · 慢步道人

使用海康威视SDK的那些坑

从其它平台迁移而来 由于工作需要,项目中有使用到海康威视的产品,不可避免的就要使用海康的SDK进行二次开发。开发过程中磕磕绊绊的,踩了不少坑,这里做一个简单的记录,算是给健忘的自己提个醒吧。 Delphi版本的接口 Gitee地址 首先,自己一直使用Delphi进行开发,然而海康官方只提供了C/C++的接口和示例,无奈只能自己改写了。改写完的部分已经上传,希望能有人共同来完善。 由于Delphi商业使用的限制,现已转到Lazarus,全面拥抱开源。 坑 播放声音 预览时播放声音,回放时播放声音,甚至使用播放库播放已下载的视频时播放声音,这些对于前端摄像头自带麦克的场景肯定是刚需(另接麦克的情况暂未测试),然而按照官方SDK文档和示例代码写出的程序死活就是没有声音,这样的情况似乎不少人都遇到过,但是,好像并没有见谁把解决方法公开过。 其实,这个问题特别简单,只需要把HCNetSDKCom目录下的OpenAL32.dll拷贝到PlayCtrl.dll所在的目录下就可以了。这下就明白了吧,没有声音的原因其实就是使用NET_DVR_OpenSound调了PlayCtrl.dll,而PlayCtrl.dll又调了OpenAL32.dll来播放声音,但是由于PlayCtrl.dll没有找到OpenAL32.dll所以没有声音,而且这个有问题的返回值也并没有一层层的返回给NET_DVR_OpenSound函数,结果就是函数返回调用成功了,但就是死活没声音。 PlayCtrl.dll不是PlayCtrl.dll 使用海康SDK进行二次开发的,一般也会使用到海康的播放库,但是有一个问题是需要注意的,那就是SDK里的PlayCtrl.dll并不是播放库里的PlayCtrl.dll。虽然它们长得一样,名字也一样,但它们的本质却是完全不一样的,是不能互相替代的!有兴趣的朋友可以使用eXeScope详细查看。

2019-01-02 16:29:46 · 1 分钟 · 慢步道人

Delphi自定义图形控件的自定义字体属性在设计期报错的解决办法

从其它平台迁移而来 背景 自定义一个图形控件(继承自TGraphicControl类),需要在不同区域显示不同字体的内容,此时会需要在设计器中加入多个字体,方法是在控件的published区增加对应的字体属性即可(使用Ctrl+Shift+C可快速生成),如: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 TMyGraphicControl = class(GraphicControl) private FText1Font: TFont; FText2Font: TFont; procedure SetText1Font(const Value: TFont); procedure SetText2Font(const Value: TFont); protected procedure Paint; override; public { public declarations } published property Text1Font:TFont read FText1Font write SetText1Font; property Text2Font:TFont read FText2Font write SetText2Font; end; 这样就可以在设计器里像使用原生控件一样使用自己的控件了。 问题 但是,如果在设计期选择了弹出字体对话框进行设置字体,IDE就会报错(大意是读或写某个地址异常),而在运行期则正常! 原因 对比查看Delphi自带的控件源码,终于找到了原因。 1 2 3 4 5 6 7 8 9 10 //Delphi TControl类设置字体属性的方法 procedure TControl....

2018-10-02 02:40:14 · 1 分钟 · 慢步道人

Delphi版本号对照表

从其它平台迁移而来 Conditional VER Product Product Version Package Version VER330 Delphi / C++Builder XE10.3 Rio 26 260 VER320 Delphi / C++Builder XE10.2 Tokyo 25 250 VER310 Delphi / C++Builder XE10.1 Berlin 24 240 VER300 Delphi / C++Builder XE10 Seattle 23 230 VER290 Delphi / C++Builder XE8 22 220 VER280 Delphi / C++Builder XE7 21 210 VER270 Delphi / C++Builder XE6 20 200 VER260 Delphi / C++Builder XE5 19 190 VER250 Delphi / C++Builder XE4 18 180 VER240 Delphi / C++Builder XE3 17 170 VER230 Delphi / C++Builder XE2 16 160 VER220 Delphi / C++Builder XE 15 150 VER210 Delphi / C++Builder 2010 14 140 VER200 Delphi / C++Builder 2009 12 120 VER190 Delphi 2007 for ....

2018-08-12 15:52:38 · 2 分钟 · 慢步道人

使用FireDAC的TFDQuery查询Firebird遇到的坑

从其它平台迁移而来 这几天被Prepare这个东西搞死了,虽然用它解决了目前的问题,但是完全不知道为什么,如有大侠知道还望指教,不胜感激! 首先,说下开发环境: win10 x64(1709 [10.0.16299.125])+Delphi XE7 up1(自带FireDAC)+Firebird 3.0.2.32703_0(数据库字符集使用UTF8) 问题一:中文模糊查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var CompanyType: Integer FDQuery1.Close; FDQuery1.SQL.Text := 'SELECT * FROM companyinfo ' + 'WHERE (tag = 0) AND (companytype = :companytype) AND ' + '((companyname LIKE :Text) OR (pym LIKE :Text))' + ' ORDER BY TIMES DESC'; //FDQuery1.Prepare; //写在这里会报错,提示如下,大致意思是: //数据库 companytype 字段是SmallInt类型,却赋了一个Integer类型的值 {--------------------------- [FireDAC][Phys][FB]-338....

2018-01-03 01:43:02 · 2 分钟 · 慢步道人

cxGrid基本用法小记

从其它平台迁移而来 汉化 在DevExpress选项卡找到TcxLocalizer控件放到窗体上,为了通用,我是放到DataModule窗体上。 准备好汉化的资源文件或配置文件(我使用的是后者),在DataModule的Create事件里写上如下代码 1 2 3 4 5 6 7 with cxLocalizer1 do begin StorageType := lstIni; LoadFromFile(IniPath + 'DevChs.ini'); locale := 2052; Active := True; end; 在有cxGrid或其实Dev控件的单元引用DataModule单元。 更改视觉样式 在DevExpress选项卡找到TcxLookAndFeelController控件放到DataModule窗体上。 在有cxGrid或其它Dev控件的单元引用DataModule单元。 在要更改视觉样式的代码段里设置TcxLookAndFeelController控件的Kind属性和NativeStyle属性。 让cxGrid的数据以斑马线的方式显示,即奇偶行分别使用不同样式 在DevExpress选项卡找到TcxStyleRepository控件放到DataModule窗体上。 双击cxStyleRepository控件,打开如下窗口,点Add添加两个样式,并命名。 分别在属性中设置不同的样式,颜色、字体、字号、字体颜色等。 在有cxGrid的单元中引用DataModule单元。 选中cxGrid的cxGridDBTableView,展开Styles,分别关联ContentEven和ContentOdd。 另外也可设置Header、Selection和Inactive。Header改变的是表头的样式,Selection改变的是当前选择行的样式,Inactive改变的是cxGrid失去焦点时当前选择行的样式。 不显示分组框 设置cxGridDBTableView的OptionsView下的GroupByBox属性为False。 显示合计等脚注 设置cxGridDBTableView的OptionsView下的Footer属性为True。 点cxGrid的Customize...按钮,弹出对话框,选择Summary标签页,在Footer子标签页中点Add增加合计项目。 选择增加的项目,在属性中设置关联的列、字段名等属性。 设置行号 增加一列,不关联数据库字段,设置好属性。 在该列的OnGetDataText事件中写如下代码: 1 AText := IntToStr(ARecordIndex + 1); 编辑完成前光标不能离开当前行 在cxGridDBTableView的OnCanFocusRecord事件中写入类似以下的代码: 1 AAllow := DbState in [dsBrowse]; 只读 设置cxGridDBTableView.OptionsData.Editing属性为False。 选择整行 设置cxGridDBTableView.OptionsSelection.CellSelect属性为False。

2017-11-25 20:41:33 · 1 分钟 · 慢步道人

FireDAC之TFDStoredProc

从其它平台迁移而来 1.在FireDAC选项卡中找到TFDStoredProc控件,放到窗体上,并把Connection属性设置为准备好的数据库连接控件上。 2.在需要执行存储过程的位置写入类似以下的代码: 1 2 3 4 5 6 7 8 9 FDStoredProc1.StoredProcName := 'SP_StoredProcName'; FDStoredProc1.Prepare; //必须,否则会报找不到参数的错误 FDStoredProc1.ParamByName('I_ID').AsInteger := id; //无返回值或返回值由输出参数传递时 FDStoredProc1.ExecProc; UserName := FDStoredProc1.ParamByName('O_USERNAME').AsString; //有返回值或数据集时 FDStoredProc1.Open(); UserName := FDStoredProc1.FindField('O_USERNAME').AsString; 3.以上为存储过程返回单个值或单条记录时的用法,存储过程返回多条记录(即数据表)的用法暂未研究。

2017-11-24 10:11:13 · 1 分钟 · 慢步道人

FirdDAC之TFDQuery使用

从其它平台迁移而来 1.在FireDAC选项卡中找到TFDQuery控件,放到窗体上,并把Connection属性设置为准备好的数据库连接控件上。 2.在需要查询或执行SQL语句的位置写入类似以下的代码: 1 2 3 4 5 6 7 8 //查询,有返回集 FDQuery1.SQL.Text := 'SELECT * FROM DBTable WHERE id = :id'; FDQuery1.ParamByName('id').AsInteger := 1; FDQuery1.Open(); //执行SQL语句,无返回集 FDQuery1.SQL.Text := 'DELETE FROM DBTable WHERE id = :id'; FDQuery1.ParamByName('id').AsInteger := 1; FDQuery1.ExecSQL; 3.若查询结果需要连接到数据集,则在DataAccess选项卡中找到TDataSource控件,放到窗体上,并把DataSet属性连接到TFDQuery控件。然后把数据感知控件(如cxGrid等)的DataSource属性连接到TDataSource控件。 4.若只需要取出查询结果并进行后续处理,可使用如下代码取出结果: 1 2 3 id := FDQuery1.FindField('id').AsInteger; DeptName := FDQuery1.FindField('deptname').AsString; Money := FDQuery1.FindField('money').AsFloat;

2017-11-23 22:31:27 · 1 分钟 · 慢步道人