DELPHI积累
Delphi 中strpcopy 可以把一个字符串拷到一个CHAR型的数组
Var
Ary : arrary[0..100] of char;
S : string;
Ret : integer;
Begin
Strpcopy(ary,s);
For I :=0 to 99 do
Ret := ret xor integer(ary[I]);
Result :=inttohex(ret,2);
Result :=lowercase(result);
End;
用strpcopy也可以把一个字符串拷到一个CHAR型的数组的指定域function formatinttostr(icount :integer;len :integer) :string;
var
str:string;
strLen : integer;
iAry : Array[0..20]of char;
i : integer;
begin
str := IntToStr(iCount);
strLen := Length( str );
if ((Length( str ) > Len) or ( Len >= 20 )) then
begin
FormatIntToStr := '';
exit;
end;
for i := 0 to Len - strLen - 1 do
iAry[i] := '0' ;
strPCopy(@iAry[i],str );
iAry[Len] := #0 ;
FormatIntToStr := StrPas(iAry);
End;
在查询语句中加入条件时间的判断
Query1.sql.Add('select * from yourtable mytable where mytable."Date"=:currday'); Query1.ParamByName('currday').AsDate:=now;
Query1.open;
如果你的字段名是关键字(如date),请用双引号引上。
在DELPHI中执行系统函数
用WINEXEC或SHELLEXECUTE,但WINEXEC不等待的。
在使用静态的多页面功能时,可以使用TNOTEBOOK和TTABSET联用在开始化时设置TABSET的TABINDEX NOTEBOOK的PAGEINDEX等于TABSET的TABINDEX
在TABSET的CLICK事件中设置TABSET的TABS等于NOTEBOOK中的PAGES
创建多页面编辑器时要注意的问题
要创建多页面编辑器,必须从TPage的父件(Parent属件)创建相应编辑部件。但在动
态创建页面时,TPage只是一个与字符串相联系的TObject类,不能写成:MemoParent := Notebook1.Pages.Object[ ];
在Delphi中,宣称对象和创建对象都是用指针来标识,因此可用无类型指针进行指针传递。
var
Pi : Pointer;
begin
Pi := Notebook1.Pages.Object[];
Memo.Parent := Pi;
end;
这样就可在TPage上动态创建编辑部件了。
在动态创建的窗口也能用WITH 。。DO 的方法
if OpenFileDialog.Execute then
with TEditForm.Create(Self) do
Open(OpenFileDialog.FileName);
end;
在程序中要使用打印和剪贴的动作时,需要包括以下代码
uses Clipbrd, Printers;等
字符串属性的对象:
访问Strings属性Objects属性
加入项目Add 方法AddObjects方法
插入项目Insert方法InsertObjects方法
项目定位Indexof方法IndexofObject方法
问题:
在STRINGGIRD中不能截获对某个单元的CLICK事件,而且不能在CELLS中嵌入如COMBOBOX等控件
解决办法:
做隐含的EDITBOX或COMBOBOX来完成需要的工作,但这样不是很方便,需要在处理的时候屏蔽掉原来的STRINGGIRD并且显示需要的多个EDITBOX和COMBOBOX来完成系列的操作。
不知道是否有什么更好的方法。
事件发送者句柄要注意的问题
在多个控件调用同一个函数或过程时,需要注意发送句柄者对象拥有者的区别。
在DELPHI中,每个事件都有自己的事件句柄来识别所传递的消息和事件,以次来区分不同的动作(可以在一个函数内实现,可以做到代码共巷)。
With Sender as 某对象实体do
Begin
…..
end;
虚拟键盘的应用
在DELPHI中要注意软键盘的应用,可以节省时间和代码量
虚拟键定义在\...\Source\Rtl\Win\Windows.Pas中,
包括所有的键,除字母和数字外,
字母和数字的键值说明如下:
{ VK_0 thru VK_9 are the same as ASCII '0' thru '9' ($30 - $39) }
{ VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' ($41 - $5A) }
和键盘相关的事件有:OnKeyDown、OnKeyUp和OnKeyPress,
产生顺序如下:
1、OnKeyDown
2、OnKeyPress
3、OnKeyUp
不产生ASCII字符的按键不会触发OnKeyPress事件
使用不可见控件TSTRINGLIST
由于TstringList在控件栏上没有选项,它一般只能自己的定义,并在程序中生成
ALIST :TstringList;
。。
procedure a( …);
begin
HistoryList := TStringList.Create;
End;
另外在使用这个控件时,需要定义一个INDEX变量,用来定位。
自定义过程的定义和使用:
自己定义的过程要定义在一个FORM的V AR中而不能定义在它的TYPE中
调用时可以直接进行。
转义符号的使用:
在SQL语句中要使用LIKE等匹配或其他方式,需要在变量后加某个字符或其他变量,需要转移符对变量进行分离。
普通的SQL语句如果要是
select * from servs where type_index like 变量;
在DELPHI中就需要以下格式进行:
'select * from servs where type_index like '+''''+content.Edit2.text+'%'+'''';
在时间ON_CHANGE中注意的问题:
如果在CHANGE事件中定义了一些操作,譬如SELECT 某些字段的话,而条件来自于CHANGE事件发生者的TEXT域,那么就不能对它进行清除了,如果一清除该实体的TEXT 域,将又发生一个新的匹配。
那怎样能够避免这样的情况呢,ON_KEYDOWN事件替换CHANGE事件
继承的应用:
如果在一个应用程序中要多次用到基本相同的FORM,这样可以考虑建立一个基本的模版FORM,其他应用的FORM在它的基础上进行继承和延伸。
这样可以提高代码的使用率和良好的模块性。
文件传送的长度问题:
在DELPHI中如果要发送比较大的文件或图象,用判断Len的方法可不好。
最好先发送文件长度,然后再发送文件。或者直接发文件,发完就断掉连接。
记录移动的对象:
在DELPHI中,掌管记录移动事件的对象是DA TASOURCE控件。
SOCKET发送单行和多行的问题:
在DELPHI中可以把MEMO。LINE。TEXT作为一个字符串发过去,而不要去管它有几行,最多有几个#13#10等字符,在接收程序中把它过滤就可以了。如果只要发送MEMO 的当前行可以如下操作:
if Key = VK_Return then
Socket1.Socket.Connections[0].SendText(Memo1.Lines[Memo1.Lines.Count - 1]) 或者用STREAM方法,DELPHI中大部分的控件可以转化成STREAM的。
利用控件TNMStrm完成文件转化成流的发送以及接收
procedure TForm1.Button1Click(Sender: TObject); ---发送的按钮,选择一个文件进行发送var
MyFStream: TFileStream;
begin
If OpenPictureDialog1.Execute then
Begin
NMStrm1.Host := Edit2.Text;
NMStrm1.FromName := Edit1.Text;
MyFStream := TFileStream.Create(OpenPictureDialog1.FileName, fmOpenRead);
---把读出的文件转化成文件流的格式
try
NMStrm1.PostIt(MyFStream);----把文件流进行发送给SERVER
finally
MyFStream.Free;
end;
end;
end;
procedure TForm1.NMStrmServ1MSG(Sender: TComponent; const sFrom: String;
strm: TStream);
var
MyFStream: TFileStream;
begin
If FileExists('.\tmp.bmp') then DeleteFile('.\tmp.bmp');
----如果已经有这个文件,就删除,这只发生在已经知道要传送的文件名的情况或某些临时文件。
MyFStream := TFileStream.Create('.\tmp.bmp', fmCreate);
----创建文件
try
MyFStream.CopyFrom(strm, strm.size);
----把读出的流复制到创建好的文件中
finally
MYFStream.Free;
end;
end;
如何动态更新DBGrid的颜色
DBGrid控件是一个有许多用户接口的显示数据库的控件,以下的程序告诉如何根据显示的内容改变字体的显示颜色。例如,如果一个城市的人口大于200万,我们就让它显示为蓝色。使用的控件事件为DBGrid.OnDrawColumeCell.
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect:TRect;DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if Table1.FieldByName('Population').AsInteger > 20000000 then
DBGrid1.Canvas.Font.Color := clBlue;
DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
上面的例子是简单的,但是你可以根据自己的需要扩充,例如字体也变化等,甚至你可以调用画圆的函数在数字上画上一个红色的圆圈。
但是,怎样在DBGRID中把一个CELL变成一个DBCOMBOBOX呢,这样可以使编程简单很多啊,是否应该自己做一个部件呢?
或者是否能捕捉到DBGRID(STRINGGIRD)中的CELLS的FOCUS???
用INSERT CONTROL?
在DELPHI中定义指针变量:
//?在指针定义之前先定义一个指向这个指针的变量,以后可以用这个变量来定义变量。Type
PSortArray = ^TSortArray;
TSortArray = array[0..114] of Integer;
TSortThread = class(TThread)
private
FBox: TPaintBox;
FSortArray: PSortArray;
FSize: Integer;
FA, FB, FI, FJ: Integer;
procedure DoVisualSwap;
protected
procedure Execute; override;
procedure VisualSwap(A, B, I, J: Integer);
procedure Sort(var A: array of Integer); virtual; abstract;
public
constructor Create(Box: TPaintBox; var SortArray: array of Integer);
end;
使用*.INI文件:
要利用.INI文件做程序有关数据的存储工作,就需要能读和写.INI文件,有如下方法从.INI文件中获取字符串
var
strResult:pchar;
begin
GetPrivateProfileString(
'windows', // []中标题的名字
'NullPort', // =号前的名字
'NIL', // 如果没有找到字符串时,返回的默认值
strResult, //存放取得字符
100, //取得字符的允许最大长度
'c:\forwin95\win.ini' // 调用的文件名
);
edit1.text:=strResult; //显示取得字符串
从.INI文件中获取整数
edit1.text:=inttostr(GetPrivateProfileInt(
'intl', // []中标题的名字
'iCountry', // =号前的名字
0,// 如果没有找到整数时,返回的默认值
'c:\forwin95\win.ini' // 调用的文件名
));
向.INI文件写入字符串
WritePrivateProfileString(
'windows', // []中标题的名字
'load', // 要写入"="号前的字符串
'accca', //要写入的数据
'c:\forwin95\win.ini' // 调用的文件名
);
向.INI文件写入整数
WritePrivateProfileSection(
'windows', // []中标题的名字
'read=100', // 要写入的数据
'c:\forwin95\win.ini' // 调用的文件名
);
如何定时关闭WINDOWS:
写一个定时程序,在时间到时触发关机开关。
控制WINDOWS的开关:如关闭WINDOWS,重新启动WINDOWS等, 都是通过函数ExitWindowsEx(UINT uFlags,DWORD dwReserved)来实现。
首先定义常数
const
EWX_FORCE=4; //关闭所有程序并以其他用户身份登录
EWX_LOGOFF=0; //重新启动计算机并切换到MS-DOS方式
EWX_REBOOT=2; //重新启动计算机
EWX_SHUTDOWN=1;//关闭计算机
运行时给How赋值,让他等于EWX_SHUTDOWN或其他,调用以下语句
ExitWindowsEx(How,0);
关闭没有被激活的窗口:
在应用程序中,如何关闭已经被转移焦点的FORM,例如:有两个按钮各自产生一个FORM,第一个产生的FORM就被转移焦点,当然可以在按第二个按钮时判断是否第一个FORM是否存在,存在则将之关闭,另外一个也如此,但这样的方法很是老土,一般程序员不会喜欢的,而且也许还有其他情况下不能如此做的。
我们可以通过检测句柄来确定当前WINDOWS的工作任务是否与目前的FORM的应用程序一致,如果不一致就关闭以前或以后的任务。
procedure TForm1.AppDeactivate(Sender: TObject);
var
hw: HWnd;
CurTask: THandle;
WndStyle:Longint;
begin
CurTask:=GetWindowTask(handle);
hw:=GetWindow(GetDesktopWindow, GW_CHILD);
while GetWindowTask(hw)<>CurTask do
hw:=GetWindow(hw, GW_HWNDNEXT);
while (hw<>handle) and (GetWindowTask(hw)=CurTask) do
begin
PostMessage(hw, WM_Close, 0, 0);
hw:=GetWindow(hw, GW_HWNDNEXT);
end;
end;
把控件转化成流文件进行传送:
这样可以避免图象传送引起的各种问题,可以把控件转化成流文件,接收方根据接收到的流文件转化回图形文件。
procedure WriteComponentResFile(const FileName: string; Instance: TComponent);
function ReadComponentResFile(const FileName: string; Instance: TComponent):TComponent;
为应用程序创建HOTKEYS:
第一步:
设置FORM的KeyPreview := true;
第二步:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (ssCtrl in Shift) and (chr(Key) in ['A', 'a']) then
ShowMessage('Ctrl-A');
end;
当然也可以利用其他值,上面只是一个简单的例子。
动态创建控件:
动态创建控件第一件事就要登记注册需要创建的类。这个可以用RegisterClass(),RegisterClasses() or RegisterClassAlias() 等函数来实现。
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TButton, TEdit, TMemo, TLabel]);
end;
在创建控件中可以使用FindClass() 函数来返回要创建的部件的类关联。
procedure TForm1.CreateClick(Sender: TObject);
begin
SomeComponent:= TComponentClass(FindClass(ClassName.Text)).Create(Self);
(SomeComponent as TControl).Parent := Self;
end;
在创建以后怎样利用这个新控件呢?
使用SetXXXXProp() 函数来设置控件的值.
使用GetXXXXProp()函数来获得控件的值
用GetPropInfo来获得控件的属性?
在DELPHI中添加一条记录可以用APPEND ,这不同于一般的数据库,增加记录只能用INSERT。
inifile:=Tinifile.Create('..\User.ini');//
datamodule1.Query1.Active := false;
datamodule1.Query1.SQL.Clear;
datamodule1.Query1.SQL.Add('select * from Alog');
datamodule1.Query1.Active := true;
datamodule1.Query1.Edit;
datamodule1.Query1.Append;
datamodule1.Query1.FieldValues['Opid']:=inifile.ReadString('User','Id','');
datamodule1.Query1.FieldValues['Summary']:=summary;
datamodule1.Query1.FieldValues['Time']:=now;
datamodule1.Query1.Post;
datamodule1.Query1.Refresh;
datamodule1.Query1.Close;
使用数据导航条:
在使用数据导航条时,注意不要用Query.,如果用了Query.部件,那将只能进行查询而不能进行修改了,所以在DataSource中的DataSet应该设置为Table,而不是Query.
把记录组合成文件:
假设A是一个RECORD
MFILE :FILE OF A;
MRECA:A
这样在打开文件MFILE后就可以
READ(MFILE,MRECA)或WRITE(MFILE,MRECA)
如何在StringGrid控件中让Enter键作用象Tab键
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
{ 在FORM的OnKeyPress事件中插入,注意将Form的KeyPreview属性设为True } begin
if Key = #13 then
if not (ActiveControl is TStringGrid) then begin { 如果不是TStringGrid }
Key := #0; { 清除按键}
Perform(WM_NEXTDLGCTL, 0, 0); { 否则移到下一Control上}
end
else if (ActiveControl is TStringGrid) then
with TStringGrid(ActiveControl) do
if selectedindex < (fieldcount -1) then
selectedindex := selectedindex +1
else
selectedindex := 0;
end;
另一种更简便的方法:
在StringGrid的KeyPress事件中写入
if Key=Chr(VK_RETURN) then
SendMessage(StringGrid.Handle,WM_CHAR,VK_TAB,0);
*在D2,D3中用时去掉Chr()函数。
如何给TListBox加上水平的滚动条?
Delphi 的TListBox元件自动实现了垂直的滚动条,当ListBox不能显示全部的菜单(Item)时,这个垂直的滚动条就会出现。然而,当菜单的宽度比ListBox宽时水平的滚动条却不会出现。以下的程序就是处理这个问题的。
在你的Form的OnCreate事件中添加以下代码:
procedure TForm1.FormCreate(Sender: TObject);
var
i, MaxWidth: integer;
begin
MaxWidth := 0;
for i := 0 to ListBox1.Items.Count - 1 do
if MaxWidth < ListBox1.Canvas.TextWidth(ListBox1.Items.Strings[i]) then
MaxWidth := ListBox1.Canvas.TextWidth(ListBox1.Items.Strings[i]);
SendMessage(ListBox1.Handle, LB_SETHORIZONTALEXTENT, MaxWidth+2, 0);
end;
以上的代码首先得到ListBox中最长Item的长度,然后用LB_SETHORIZONTALEXTENT 消息设置ListBox的水平滚动的宽度,宽度加2是为了给右面留2个点的边。