`

Delphi Tips and Articles 3

 
阅读更多

1在db控件中捕捉字段变化前后的值

from google groups

http://groups.google.com/group/borland.public.delphi.thirdparty-tools/browse_thread/thread/46ff3c56af4174a1/9b071486516dadb1?lnk=st&q=delphi+detect+field+change&rnum=2

Detecting a field change
All 2 messages in topic - view as tree
From:Ian Branch - view profile
Date:Wed, Apr 11 2001 5:11 pm
Not yet rated

show options


Hi Guys,

I need to reliably detect whether a field has changed as a result of
editing via a TDBEdit so I can write a log record of the date/time, user ID
and new value.

I am playing with BeforeEdit to detect the pre edit value and before
post to detect the 'post' edit value. I compare the two and if different,
write the data to the log file.

To my simple mind this should be OK but it seems to yield inconsistant
results. Sometimes it detects & writes correctly, sometimes not. In
particular it doesn't seem to detect if the field is changed twice in a row.

I prefer to do this at the table level as this is the lowest level and
they are all in a Datamodule.

Any suggestions?

Regards,

Ian

Reply Rate this post:


From:Michael G - view profile
Date:Wed, Apr 11 2001 8:35 pm
Not yet rated

show options


One way it can be done, but you need to be using cached updates and a TQuery
to do it, is to check the "OldValue" and "NewValue" variants in the
"OnChange" event of the TField. It has worked pretty well for me in the
past.(这里还有一个识别OldValue和NewValue是不是一样的问题,见下)

Another way, using a TTable and a TDbEdit is to capture the value of the
value of the TField (TableName.FieldByName('YourField').AsString) in the
OnChange event of the DBEdit and the value of the TField in its OnChange
event. For some reason, the value in the OnChange event of the DBEdit will
have the old value and the OnChange event of the TField the new value.

HTH


上述方案在使用datasource,clientdataset,datasetprovider,dataset(table,query),组合时不能用。

这时,数据提交之后,服务器端的dataset(table,query)·的相关事件中捕获不到,比如beforepost之类的事件。但是在前面的情况下,可以捕获到。

因此,这是的方案是:

在datasetprovider的beforeUpdateeRecord事件中捕获,每update一个record就会触发该事件。

该事件的解释:

The Sender parameter identifies the provider that is applying updates.

The SourceDS parameter is the dataset from which the data originated. If there is no source dataset, this value is nil (Delphi) or NULL (C++). The source dataset may not be active when the event occurs, so set its Active property to true before trying to access its data.

The DeltaDS parameter is a client dataset containing all the updates that are being applied. The current record represents the update that is about to be applied.

The UpdateKind parameter indicates whether this update is the modification of an existing record (ukModify), a new record to insert (ukInsert), or an existing record to delete (ukDelete).

The Applied parameter controls what happens after exiting the event handler. If the event handler sets Applied to true, the provider ignores the update: it neither tries to apply it, nor does it log an error indicating that the update was not applied. If the event handler leaves Applied as false, the provider tries to apply the update after the event handler exits.


procedure TDataModule2.dspBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;
UpdateKind: TUpdateKind; var Applied: Boolean);
begin
if UpdateKind=ukModify then
begin

//还使用了识别variant数据是否相等的方法。见2

if (Vartype( DeltaDS.FieldByName('bm').OldValue)=
VarType(DeltaDS.FieldByName('bm').NewValue)) and
((DeltaDS.FieldByName('bm').OldValue)=
(DeltaDS.FieldByName('bm').OldValue) ) then
showmessage('not equ');

end;

end;


2一个简单的识别variant类型数据是否相等的方法

http://groups.google.com/group/borland.public.delphi.objectpascal/browse_thread/thread/e6f4b39eea029013/3e1323ece5c56bf5?lnk=st&q=compare+variant&rnum=4

A simple way to compare would be something like this:

Function VariantCompare(v1,v2:Variant) : Boolean;
Begin
Result := False ;
If (VarType(v1) = VarType(v2)) Then Begin
Result := (v1 = v2) ;
End;
End;

If the Variant Types are the same then compare them, otherwise assume that
they are different because they are different Types.

3如何在不同的屏幕分辨率、刷新率下正常显示用Delphi开发的Windows程序

http://delphi.apub.org/doc/2006/07/12/10/40/34/175037.html

Delphi程序设计界面的动态调整

施江杰

--------------------------------------------------------------------------------

如何设计美观的程序一直是程序员的一大难题,很多程序员可以写出很好的程序,但往往困于拙劣的外观。其中如何使美观的程序能在不同的环境下一样美观也同样困扰着我们,我在一些程序的制作中掌握了一些使程序在不同环境同样美观的方法,希望给大家一点启示。
不同环境一般有不同的色彩数和不同的分辨率等等,我只对这两种环境进行说明。
一. 不同的色彩数
对于不同的色彩数我们可以用启动时加以判断并选择相应的配色/图片方案。可在窗口建立时加入程序如下:
procedure TForm1.FormCreate(Sender: TObject);
var
colorbits:Integer;
begin
colorbits :=GetDeviceCaps( h, BITSPIXEL );
case colorbits of
1: //黑白配色方案;
....
4: //16色配色方案;
....
8: //256色配色方案;
....
16: //16位色配色方案;
....
24: //24位色配色方案;
....
32: //32位色配色方案;
....
end;
end;
这样就可以在不同的颜色环境下使用不同的配色方案,不同的图标/图片/色彩均在设计者的控制下,可制作出比较好的图片/彩色环境,而不至于在真彩时很不错,而在16色时一塌糊涂。
二. 不同的分辨率
不同的分辨率下原来的窗口界面可能变得面目全非,对于这种问题,我一般采取以下方式:
先取得分辨率方法有如下:
procedure TForm1.FormCreate(Sender: TObject);
var
sx,sy:Integer;
begin
sx := GetSystemMetrics(SM_CXSCREEN); //分辨率宽
sy := GetSystemMetrics(SM_CYSCREEN); //分辨率高
end;
也可以用Screen.width/Screen.Height来取得
也可以用Var DevMode:TDeviceMode;
Begin
EnumDisplaySettings(nil,0,DevMode)
sx := DevMode.dmPelsWidth
sy := DevMode.dmPelsHeight 来取得
end
也可以用sx := GetDeviceCaps(GetDC(Form1.Handle), HORZRES)
sx :=GetDeviceCaps(GetDC(Form1.Handle), VERTRES) 来取得而后有以下几种方法:
1. 判断分辨率并选择相应的分辨率方案;
(对每种分辨率设计一套控件/字体的大小方案用于在不同分辨率下选择)
2. 固定窗口大小;
procedure TForm1.FormResize(Sender: TObject);
begin
width:=640; height:=480;
left:=0; top:=0;
end;
3. 使用procedure ScaleBy(M, D: Integer)这个过程来对可视控件进行大小调节(此过程不调节窗口大小,也不变动控件的left和top,对控件的大小按M/D比例来调节),具体如下:
procedure TForm1.FormCreate(Sender: TObject);
//假设原来的设计环境为800x600
var
FWidth:integer;
begin
if(Screen.width<> 800)then
begin
FWidth:=Width;
Scaled:=TRUE;
Font.Size:=(Width DIV FWidth)*Font.Size;//字体大小调整
ScaleBy(Screen.Width,800); //控件大小调整
Height:=longint(Height)*longint(Screen.Height)DIV 600;
Width:=longint(Width)*longint(Screen.Width)DIV 800;//窗口大小调整
end;
end;
用此种方法比较实用,而且使用比较简单,基本能适应大多数环境。
4. 调节分辨率到所需的分辨率(即设计时的分辨率,此法对要求封闭的系统比较有用,如工控、触摸屏等等)
procedure TForm1.FormCreate(Sender: TObject);
var
FWidth:integer;
DevMode:TDeviceMode;
begin
if(Screen.width<> 800)then
begin
  Result:=EnumDisplaySettings(nil,0,DevMode); //取得旧的显示参数
  if Result then
  begin
  DevMode.dmFields:=DM_PELSWIDTH Or DM_PELSHEIGHT;
 DevMode.dmPelsWidth:=800;
  DevMode.dmPelsHeight:=600;
ChangeDisplaySettings(DevMode,0); //设置新的显示参数
end;
end;
当然,我们还可以使用Delphi的法宝第三方控件,我找的有ResScale 控件,此控件能够适应多种不同屏幕分辨率,自动改变TForm上控件位置及尺寸的控件,控件位置会储存于.INI文件或注册表中。你还可以找到更好的控件或者方法,找到的话告诉我一下mail me: sjj@netease.com

4delphi中的换行符用#13表示,比如

if messagedlg('继续将删除该项'+#13+'是否继续', mtconfirmation,[mbyes,mbNo],0)=mryes then

begin

end;

5数据库提示:将截断字符串或二进制数据

是因为提交的字段的实际长度大于定义长度

6sql server中似乎不能将计算字段直接从一个表插入到另一个表

如insert into table1 (ziduan1,jisuanziduan1) select ziduan ,jisuanziduan1 from table2

7ttreeview中的节点排序的问题,

如果是设计期就确定了节点,只要通过指定sorttype来排序,

如果是运行期动态加入的节点,sorttype似乎无用,可以在加入节点后,调用alphaSort或CustomSort排序。

更高级的排序是利用oncompare事件。在onaddtion事件中调用oncompare事件来确定加入的节点的位置,这种方法似乎很麻烦,如果将b节点加入到A节点下面,又A下面已经有很多子节点,比较可能很多(猜测,未实践,因为oncompare一次只能做两两比较),

8DBImage不能读jpeg文件的解决

用dbimage控件显示JPEG图片----源代码 倾情奉献
版权所有 codesky.net 2003-2005

发表时间:2003-9-17 关键字:不详

http://www.codesky.net/article/doc/200309/2003091786115692.htm

procedure Tphotodataf.N81Click(Sender: TObject);
var
temp:string;
pics:Tstream;
bmp:Tbitmap;
jpg:Tjpegimage;
bmps:Tmemorystream;
begin
if opd1.Execute then
begin
if extractfileext(opd1.FileName)='.bmp' then
begin
temp :=opd1.FileName;
searchpic(temp,'photo',photo,datap.testdata);
end
else
begin
try
jpg:=Tjpegimage.Create;
bmp:=Tbitmap.Create;
bmps:=Tmemorystream.Create;
jpg.LoadFromFile(opd1.FileName);
bmp.Assign(jpg);
bmp.SaveToStream(bmps);
datap.testdata.Edit;//datap.testdata TDataset类型
pics:=datap.testdata.CreateBlobStream(datap.testdata.FieldByName('photo'),bmwrite);
pics:=bmps;
pics.Position:=0;
datap.testdata.Edit;
Tblobfield(datap.testdata.FieldByName('photo')).LoadFromStream(pics);
datap.testdata.Post;
finally
jpg.Free;
bmp.Free;
bmps.Free;
datap.testdata.Edit;
end;
end;
end;
end;

9QReport不能全部预览A3大小的报表的问题

这个问题是因为机器上面没有安装打印机驱动或者安装的驱动不支持A3大小的纸张的原因。

解决:安装一个支持A3的驱动(没有实际的打印机,也可以强制装一个,在控制面板中,windows xp自带驱动中的HP DeskJet 1220C是一个支持A3的驱动),

10TStringlist的常量问题的讨论

http://5idev.com/Article/438368

11TreeView.customsort的使用

help的说明:

This example shows how to use the CustomSort method to order a tree view in case-insensitive alphabetical order (either forward or backward). The application must provide a callback function such as CompareFunc below, which calls the global AnsiStrIComp function to perform the actual comparison.

function CustomSortProc(Node1, Node2: TTreeNode; Data: Integer): Integer; stdcall;

begin
Result := -AnsiStrIComp(PChar(Node1.Text), PChar(Node2.Text));
end;

This procedure can then be used as a parameter to CustomSort to sort the nodes of the tree view:

TreeView1.CustomSort(@CustomSortProc, 0);

注意:

customsort的回调函数是一个static函数, 不是类的方法.
不能是
function TXXXX.xxxx(....)而是function xxxx(....);
如果非要用类的方法不可, 可以用makeobjectinstance将类的方法转换成
标准函数或方法, 然后赋给TreeView.CustomSort.

实现:在class的定义下,定义

function customsortproc(Node1, Node2: TTreeNode; Data: Integer): Integer; stdcall;

在implementation里

function customsortproc(Node1, Node2: TTreeNode; Data: Integer): Integer; stdcall;
begin
result := 利用node1和node2计算一个值

end;

12从TFrame继承一个class,但不是form形式的,编译可能提示:oldcreateorder不存在,或.....要被ignore,

解决:从dfm的txt形式中删除它提示的要ignore的属性,如oldcreateorder,textheight,scale等。

13DBtext列印自動換列問題

http://vclxx.org/forum/index.php?topic=17694.msg54591

QRdbtext1.autosize := False;
Qrdbtext1.autostretch :=true;
qrdbtext1.wordwrap := true;

必需要在換行的地方加上一個空白,QuickReport才會換行

上面这个不行。

用下面这个:绝对终极方案,试过,可行

http://vclxx.org/forum/index.php?topic=22428.msg69697

procedure TqrWeekQA.QRDBTxtInTimePrint(sender: TObject; var Value: String);

var
I: Integer;
begin
with Sender as TQRDBText do
begin
meCutWord.Font.Assign(Font); // 指定字型
meCutWord.Width := Width; // 指定寬度
meCutWord.Lines.Clear; // 清除上一次的東西
meCutWord.Lines.Text := Value; // 把 value assign 進去
Value := meCutWord.Lines.Strings[0];
for I := 1 to meCutWord.Lines.Count - 1 do
begin
Value := Value + #13 + meCutWord.Lines.Strings[i]; // 逐行
取出再塞回去
end;
end;
end;


辦法就是放一個 TMemo 元件來負責換行,把換好行後的 Lines 再 Assign 回來即可。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics