2009年5月30日

google-guice






http://code.google.com/p/google-guice/

Delphi TJclAnsiRegEx

需先安裝 JEDI VCL for Delphi
和 Perl-compatible Regular Ex-pressions

將 \Program Files\GnuWin32\bin\pcre3.dll 複製到
\WINDOWS\system32 目錄下,並更名為 pcre.dll
>copy "\Program Files\GnuWin32\bin\pcre3.dll" \WINDOWS\system32\pcre.dll

開啟 Delphi 在 Form Create 事件中加入
uses
JclPCRE;

procedure TForm1.FormCreate(Sender: TObject);
var
Re: TJclAnsiRegEx;
s: string;
i: Integer;
begin
Memo1.Lines.Clear;
Re := TJclAnsiRegEx.CReate;
try
Re.Compile('\d+', True, False);
s := 'hello 1234 test 5678 number'#13#10'90';
i := 1;
while Re.Match(s, i) do
begin
Memo1.Lines.Add(Re.CaptuRes[0]);
i := Re.CaptureRanges[0].LastPos +2;
end;
finally
Re.FRee;
end;
end;
{
1234
5678
90
}

Python 教學文件(中文)

中文
http://www.freebsd.org.hk/html/python/tut_tw/tut.html

英文
http://docs.python.org/tut/

網頁或郵件放入 Skype button

http://www.skype.com/share/buttons/
1. Enter your Skype Name 填入你的 Skype 帳號

4. Copy & paste this code
選擇用 Web HTML 或 Email HTML
copy 下來 paste 到 Web 或 Email 中

中文網址
http://www.skype.com/intl/zh-Hant/share/buttons/

Regular expression 規則運算式(正規表示)

http://msdn.microsoft.com/library/cht/default.asp?url=/library/CHT/jscript7/html/jsjsgrpregexpsyntax.asp
http://irw.ncit.edu.tw/peterju/webslide/re/
http://www.regular-expressions.info/
http://phi.sinica.edu.tw/aspac/reports/94/94019/
http://www.javaworld.com.tw/jute/post/view?bid=20&id=130126
http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html

Perl-compatible Regular Ex-pressions

Perl-compatible Regular Ex-pressions http://www.pcre.org/
Windows 版 http://gnuwin32.sourceforge.net/
安裝 Pcre for Windows 後,可以找到程式
C:\Program Files\GnuWin32\bin\pcregrep.exe
可將 C:\Program Files\GnuWin32\bin 加入環境變數 path 中
使用 pcregrep
Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]
例如要例出 a.txt 中有含數字的每一行
>pcregrep \d+ a.txt

Delphi JEDI CreateJunctionPoint (SymbolicLink)


uses
SysUtils, JclNTFS;

begin
// function NtfsCreateJunctionPoint(const Source, Destination: string): Boolean;
// Source must empty directory
NtfsCreateJunctionPoint('c:\tmp\ProgramFiles', 'C:\Program Files');
// Delete
// NtfsDeleteJunctionPoint('c:\tmp\ProgramFiles');
end.

Delphi JEDI CreateHardLink


uses
SysUtils, JclNTFS;

begin
NtfsCreateHardLink('C:\LINK_ODBC.INI', 'C:\WINDOWS\ODBC.INI');
end.

Delphi JEDI JvSearchFiles


type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
procedure FindFile(Sender: TObject; const AName: String);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

uses
JvSearchFiles;

procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
with TJvSearchFiles.Create(nil) do
begin
Files.Clear;
Directories.Clear;
DirOption := doIncludeSubDirs;
Options := Options + [soOwnerData];
FileParams.FileMasks.Text := '*.PAS';
FileParams.SearchTypes := [stFileMask];
RootDirectory := 'C:\JVCL333';
OnFindFile := FindFile;
Search;
Free;
end;
end;

procedure TForm1.FindFile(Sender: TObject;
const AName: String);
begin
Memo1.Lines.Add(AName);
end;

Delphi JEDI ScreenShot 擷取螢幕畫面到剪貼簿


// 在 Form 上放入一個 Button 並加入 onclick 事件

uses
JclGraphics, Clipbrd;

procedure TForm1.Button1Click(Sender: TObject);
var
Bitmap: TBitmap;
AFormat: Word;
AData: THandle;
APalette: HPALETTE;
begin
Bitmap := TBitmap.Create;
try
// Left, Top, Width, Height, HWND_DESKTOP
ScreenShot(Bitmap, 0,0, 300, 200, HWND_DESKTOP);
Bitmap.SaveToClipboardFormat(AFormat, AData, APalette);
ClipBoard.SetAsHandle(AFormat, AData);
finally
Bitmap.Free;
end;
end;

Delphi JEDI Form CaptionButton


// ...
// 在 uses 中加入 JvCaptionButton
uses
... , JvCaptionButton;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
// 加入 TJvCaptionButton 和 bonclick TNotifyEvent
b: TJvCaptionButton;
procedure bonclick(Sender: TObject);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.bonclick(Sender: TObject);
begin
ShowMessage('Hello');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
B := TJvCaptionButton.Create(self);
B.Caption := 'A';
B.onclick := bonclick;
end;

// ...

執行程式後 Caption 上就會多一個 'A' Button 了

Delphi JEDI TrayIcon Application

需先安裝 JEDI VCL for Delphi

加入元件
Jv Non-Visual -> JvTrayIcon
Standard -> PopupMenu
PopupMenu1 add MenuItem

設定元件屬性
MenuItem.Caption = Show
MenuItem.Name = Show1
JvTrayIcon1.Active = True
JvTrayIcon1.PopupMenu = PopupMenu1

// 加入 Show1 onclick 事件
procedure TForm1.Show1Click(Sender: TObject);
begin
JvTrayIcon1.ShowApplication;
end;

// 加入 Form1 OnCreate 事件
procedure TForm1.FormCreate(Sender: TObject);
begin
JvTrayIcon1.HideApplication;
end;

執行程式後會直接隱藏到 TrayIcon 中
右鍵點 PopupMenu -> Show 還原視窗

Delphi JEDI JvDebugHandler 紀錄 Exception 資訊 (full stack trace)


需先安裝 JEDI VCL for Delphi
先開啟 Map file
Project -> Options -> Linker -> Map file 選擇 Detailed 按 OK

放入元件 Jv System -> JvDebugHandler
放入元件 Memo

加入 Form1 OnCreate 事件

procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
try
Format('%s', [3]);
except

end;
end;

加入 JvDebugHandler1 OnOtherDestination 事件

procedure TForm1.JvDebugHandler1OtherDestination(Sender: TObject);
begin
Memo1.Lines.AddStrings(JvDebugHandler1.ExceptionStringList);
end;

執行程式並跳過 Exception
{ Memo
2008/3/29 下午 12:16:05 Exception EConvertError occured in ConvertErrorFmt at 0 in file
Message: Format '%s' invalid or incompatible with argument
Call stack:
[00408041] SysUtils.ConvertErrorFmt
[00409467] SysUtils.FmtStr
[00409412] SysUtils.Format
[0045EC2B] Unit1.TForm1.FormCreate (Line 32, "Unit1.pas")
[004470E1] Forms.TCustomForm.DoCreate
[00446DC1] Forms.TCustomForm.AfterConstruction
[0044E481] Forms.TApplication.CreateForm
[0045EFEF] Project1.Project1 (Line 11, "C:\Delphi7\Projects\Project1.dpr")

預設 JvDebugHandler.LogToFile = True
也會輸出 log file,預設檔名為 ${Application.Title} ERRORLOG.txt
可以直接設定 JvDebugHandler.LogFileName 來指定 log file 檔名

Delphi JEDI Persistence Form


Add Components
Jv Persistence -> JvAppIniFileStorage
Jv Persistence -> JvFormStorage
Jv Dialogs -> JvTipOfDay

Edit Object properties
JvFormStorage1.AppStorage = JvAppIniFileStorage1
JvAppIniFileStorage1.FileName = 'APP1.INI'
JvTipOfDay1.AppStoragePath = 'TIP'
JvTipOfDay1.Options = [toShowonstartUp, toUseAppStorage]
JvTipOfDay1.AppStorage = JvAppIniFileStorage1
JvTipOfDay1.Tips.Strings = (
'Tips 1'
'Tips 2'
'Tips 3')

Run program show Tips
Exit program save APP.INI file
Re-run program read APP.INI file and change properties

Delphi JEDI TJvComputerInfoEx 取得系統資訊


需先安裝 JEDI VCL for Delphi

uses
JvComputerInfoEx;

procedure TForm1.FormCreate(Sender: TObject);
var
JvComputerInfoEx1: TJvComputerInfoEx;
begin
JvComputerInfoEx1 := TJvComputerInfoEx.Create(Self);
with JvComputerInfoEx1, Memo1.Lines do
begin
Clear;
Values['OS Name'] := OS.ProductName +' '+ OS.VersionCSDString;
Values['CPU'] := CPU.Name;
Values['Screen'] := Format('%d X %d', [Screen.Width, Screen.Height]);
Values['Battery'] := Format('%d%%', [APM.BatteryLifePercent]);
Values['Desktop'] := Folders.Desktop;
Values['IPAddress'] := Identification.IPAddress;
Values['DomainName'] := Identification.DomainName;
end;
JvComputerInfoEx1.Free;
end;
{ Memo1
OS Name=Microsoft Windows XP Service Pack 2
CPU=Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz
Screen=1280 X 800
Battery=79%
Desktop=C:\Documents and Settings\Administrator\桌面
IPAddress=169.254.254.234
DomainName=SOLNONE
}

Delphi JEDI 增加、刪除 Windows 使用者帳號


需先安裝 JEDI VCL for Delphi

建立 Delphi Console Application
File -> New -> Other... -> Console Application

輸入參數
Run -> Paramters...
Paramters 中輸入 Username Password

program Project1;
{$APPTYPE CONSOLE}

uses
SysUtils, JclLANMan, System;

var
Username: string;
Password: string;
Input: string;
begin
if ParamCount < 2 then
begin
WriteLn(ExtractFileName(ParamStr(0)) + ' Username Password');
ReadLn(Input);
Exit;
end;
Username := ParamStr(1);
Password := ParamStr(2);
if CreateLocalAccount(Username, 'FullName',
Password, 'Comment', 'HomeDir', 'Script') then
begin
WriteLn('Create User ' + Username + ' Success');
if DeleteLocalAccount(Username) then
begin
WriteLn('Delete User ' + Username + ' Success');
end
else
begin
WriteLn('Delete User ' + Username + ' Success');
end;
end
else
begin
WriteLn('Create User ' + Username + ' Failure');
end;
ReadLn(Input);
end.
{ Stdout
Create User Username Success
Delete User Username Success
}

Delphi JEDI MultiStringHolder 存多個 TStrings


需先安裝 JEDI VCL for Delphi
在 Form 中
放入 TMemo 顯示訊息
放入 Jv Non-Visual -> TJvMultiStringHolder
加入 Form1 OnCreate 事件
procedure TForm1.FormCreate(Sender: TObject);
begin
// Add config
with JvMultiStringHolder1.MultipleStrings.Add do
begin
Name := 'config';
with Strings do
begin
Values['Server'] := 'localhost';
Values['User'] := 'Solnone';
Values['Access'] := 'ReadOnly';
end;
end;
// Add users
with JvMultiStringHolder1.MultipleStrings.Add do
begin
Name := 'users';
with Strings do
begin
Add('Solnone');
Add('May');
Add('John');
end;
end;

// Show
with JvMultiStringHolder1 do
begin
Memo1.Lines := ItemByName['config'].Strings;
Memo1.Lines.Add('------');
Memo1.Lines.AddStrings(ItemByName['users'].Strings);
end;
end;

{ Memo1
Server=localhost
User=Solnone
Access=ReadOnly
------
Solnone
May
John
}

Delphi JEDI CreateProcess 執行 Console 程式


需先安裝 JEDI VCL for Delphi
在 Form 上
放入 Jv Non-Visual -> TJvCreateProcess
放入 TEdit, TButton 來執行 CommandLine
放入 TMemo 來顯示 Console 訊息
放入 TActionManager 來建立一個 Action
在 ActionManager1 雙擊滑鼠左鍵開啟 Editing ActionManager
新增一個 New Action [Inc]
加入 Action1 OnExecute 事件
procedure TForm1.Action1Execute(Sender: TObject);
var
cmd: String;
path: String;
begin
with JvCreateProcess1 do
begin
case State of
psReady: begin
cmd := Edit1.Text;
commandLine := cmd;
path := ExtractFilePath(cmd);
CurrentDirectory := path;
Memo1.Clear;
Run;
end;
psRunning,
psWaiting: begin
JvCreateProcess1.CloseApplication;
end;
end;
end;
end;

加入 Action1 OnUpdate 事件
procedure TForm1.Action1Update(Sender: TObject);
begin
with JvCreateProcess1 do
begin
case State of
psReady: Button1.Caption := 'Run';
psRunning, psWaiting: Button1.Caption := 'Close';
end;
end;
end;


加入 JvCreateProcess1 OnRead 事件
procedure TForm1.JvCreateProcess1Read(Sender: TObject; const S: String;
const StartsOnNewLine: Boolean);
begin
Memo1.Lines.Add(S);
end;

修改屬性
Button1.Action = Action1
Edit1.Text = 'netstat -na'
JvCreateProcess1.StartupInfo.ShowWindow = swHide
JvCreateProcess1.StartupInfo.DefaultWindowState = False
JvCreateProcess1.ConsoleOptions = [coOwnerData, coRedirect]
Memo1.ScrollBars = ssBoth
Memo1.WordWrap = False

執行程式, 按下 Run Button, Memo1 會取得到 stdout
Active Connections

Proto Local Address Foreign Address State
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING
TCP ...

Delphi JEDI 取得 Windows Service Description

需先安裝 JEDI VCL for Delphi

uses
JclSvcCtrl;

在 Form 中放入 TMemo 顯示訊息
加入 Form1 OnCreate 事件

procedure TForm1.FormCreate(Sender: TObject);
var
SCManager: TJclSCManager;
I: Integer;
Service: TJclNtService;
begin
Memo1.Clear;
Memo1.WordWrap := False;
Memo1.ScrollBars := ssBoth;
SCManager := TJclSCManager.Create;
try
SCManager.Refresh(True);
for I := 0 to SCManager.ServiceCount -1 do
begin
Service := SCManager.Services[I];
Memo1.Lines.Values[Service.ServiceName] := Service.Description;
end;
finally
SCManager.Free;
end;
end;

{
AFD=AFD 網路支援環境
alerter=通知選取的使用者及電腦系統管理警示。...
ALG=提供網際網路連線共用和 Windows 防火牆的第三...
...
}

Delphi JEDI SingleInstance (單一執行程式)


在 Menu 中選 View -> Units... [Ctrl + F12]
選擇 Project1
uses JclAppInst
加入 JclAppInstances.CheckSingleInstance;
Project1 內容如下

program Project1;

uses
JclAppInst,
Forms,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
JclAppInstances.CheckSingleInstance;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

編譯,執行多次程式 Project1.exe
就只會有一個實體程式在執行中

Delphi JEDI Mouse Gesture 滑鼠手勢


需先安裝 JEDI VCL for Delphi

在 Form 中
放入 TMemo 顯示訊息
放入 Jv Non-Visual -> TJvMouseGestureHook
加入 JvMouseGestureHook1.OnouseGestureCustomInterpretation 事件

procedure TForm1.JvMouseGestureHook1MouseGestureCustomInterpretation(
Sender: TObject; const AGesture: String);
begin
Memo1.Lines.Add(AGesture);
end;

加入 Form1 OnCreate 事件

procedure TForm1.FormCreate(Sender: TObject);
begin
JvMouseGestureHook1.Active := True;
end;

執行程式,即可用滑鼠右鍵拖曳畫出方向
上 U
下 D
左 L
右 R
左下 1
右下 3
左上 7
右上 9

Delphi JEDI TJvLogFile


需先安裝 JEDI VCL for Delphi
在 Form 中
放入 Jv Non-Visual -> TJvLogFile

FileName = 'c:\log.txt'
AutoSave = True
SizeLimit = 1048576 //1M

放入 TTimer 元件,並加入 Timer1 OnTimer 事件

procedure TForm1.Timer1Timer(Sender: TObject);
begin
JvLogFile1.Add(DateTimeToStr(Now), 'Now', DateTimeToStr(Now));
end;

執行程式後,可用文字編輯器開啟 Log File 'c:\log.txt'

Delphi JEDI Validate


需先安裝 JEDI VCL for Delphi
在 Form 中
放入 TMemo 顯示訊息
放入 TEdit 作為驗證資料輸入欄
放入 TButton 執行驗證

放入 Jv Validators -> TJvValidationSummary
放入 Jv Validators -> TJvErrorIndicator
放入 Jv Validators -> TJvValidators

修改 JvValidators1 屬性
ValidationSummary = JvValidationSummary1
ErrorIndicator = JvErrorIndicator1

用滑鼠雙擊 JvValidators1 元件會顯示 JvValidator Item Editor...
或是在JvValidators1 元件上用滑鼠右鍵選擇 JvValidator Item Editor...
新增一個 Required Field Validator
修改 JvRequiredFieldValidator1 屬性
ControlToValidate = Edit1
PropertyToValidate = 'Text'
ErrorMessage = 'Not Empty'


加入 Form1 OnCreate 事件
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
Edit1.Clear;
end;

加入 Button1 onclick 事件
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Clear;
if not JvValidators1.Validate then begin
Memo1.Lines := JvValidationSummary1.Summaries;
end;
end;

執行程式,按下 Button1 作驗證

Delphi 使用 TJclLocaleInfo

需先安裝 JEDI VCL for Delphi

uses
JclLocales;

procedure TForm1.FormCreate(Sender: TObject);
var
info: TJclLocaleInfo;
begin
info := TJclLocaleInfo.Create;
try
with Memo1.Lines do
begin
Clear;
Add('CountryCode: ' + inttostr(info.CountryCode));
Add('CodePageANSI: ' + inttostr(info.CodePageANSI));
Add('EnglishLangName: ' + info.EnglishLangName);
Add('NativeLangName: ' + info.NativeLangName);
Add('LocalizedLangName: ' + info.LocalizedLangName);
Add('LocalizedCountryName: ' + info.LocalizedCountryName);
Add('ISOAbbreviatedLangName: ' + info.ISOAbbreviatedLangName);
Add('ISOAbbreviatedCountryName: ' + info.ISOAbbreviatedCountryName);
Add('DefaultLanguageId: ' + inttostr(info.DefaultLanguageId));
Add('LanguageIndentifier: ' + info.LanguageIndentifier);
end;
finally
info.Free;
end;
end;
{
CountryCode: 886
CodePageANSI: 950
EnglishLangName: Chinese
NativeLangName: 中文(繁體)
LocalizedLangName: 中文 (台灣)
LocalizedCountryName: 台灣
ISOAbbreviatedLangName: zh
ISOAbbreviatedCountryName: TW
DefaultLanguageId: 404
LanguageIndentifier: 0404
}

Deiphi 使用 JclDebug 來印出目前行號等資訊

需先安裝 JEDI VCL for Delphi
Menu 上 Project->Options->Linker->Map file 選擇 Detailed 按 OK

uses
JclDebug;

procedure TForm1.FormCreate(Sender: TObject);
begin
with Memo1.Lines do
begin
Clear;
Add('FileName: ' + __FILE__);
Add(Format('Module: %s, Procedure %s, Line: %d', [
__MODULE__,
__PROC__,
__LINE__
]));
end;
end;
{
FileName: Unit1.pas
Module: Unit1, Procedure TForm1.FormCreate, Line: 35
}

Delphi TJclSCManager 列出及控制 Service

需先安裝 JEDI VCL for Delphi

uses
JclSvcCtrl;

procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
FSCManager: TJclSCManager;
Service: TJclNtService;
begin
FSCManager := TJclSCManager.Create;
try
FSCManager.Refresh(True);
Memo1.Lines.Clear;
Memo1.WordWrap := False;
for I := 0 to FSCManager.ServiceCount -1 do
begin
Service := FSCManager.Services[I];
Memo1.Lines.Values[Service.ServiceName] := Service.DisplayName;
end;
if FSCManager.FindService('Dhcp', Service) then begin
if Service.ServiceState = ssRunning then begin
Service.Stop;
ShowMessage('Stop Dhcp');
end;
Service.Start;
ShowMessage('Start Dhcp');
end;
finally
FSCManager.Free;
end;
end;

使用 Delphi JCL TEvaluator 動態計算公式

需先安裝 JEDI VCL for Delphi

uses
JclExprEval;

procedure TForm1.FormCreate(Sender: TObject);
var
FEvaluator: TEvaluator;
begin
Memo1.Lines.Clear;
FEvaluator := TEvaluator.Create;
try
Memo1.Lines.Add(FloatToStr(FEvaluator.Evaluate('(3 + 5) * 10')));
finally
FEvaluator.Free;
end;
end;
{
80
}

2009年5月29日

Delphi JclFileUtils

需先安裝 JEDI VCL for Delphi

uses
JclFileUtils;

procedure TForm1.FormCreate(Sender: TObject);
var
TempFileStream: TJclTempFileStream;
TempPath: string;
begin
// 建立暫存檔
TempFileStream := TJclTempFileStream.Create('~');
try
Memo1.Lines.Add(TempFileStream.FileName);
TempFileStream.Write('12345', 5);
TempFileStream.Seek(0, soBeginning);
Memo1.Lines.LoadFromStream(TempFileStream);
finally
TempFileStream.Free;
end;

TempPath := PathGetTempPath;
Memo1.Lines.Add(TempPath);
// 刪除檔案到資源回收筒
FileDelete( TempPath + '\~*.tmp', True);
// 刪除目錄到資源回收筒
DeleteDirectory(TempPath + '\dir', True);
end;

Delphi dll name

Delphi - Call procedure in DLL Form from DLL Source.

function Sto_GetModuleName: String;
var
szFileName: array[0..MAX_PATH] of Char;
begin
GetModuleFileName(hInstance, szFileName, MAX_PATH);
Result := szFileName;
end;

Delphi Windows Service - Indy Time Server


實做 Windows Service, 拿 Indy Time Server 元件來當服務範例

用 Delphi 先建立一個 Service Application
File->New->Other...-> [New page] Service Application

放入 TIdTimeServer 元件
Indy Servers -> IdTimeServer

修改 TService Properties (屬性)
Name = 'DelphiTimeServer'
DisplayName = 'Delphi Time Server'

加入 TService Events (事件)
// OnStart

procedure TDelphiTimeServer.ServiceStart(Sender: TService;
var Started: Boolean);
begin
IdTimeServer1.Active := True;
end;

// OnStop

procedure TDelphiTimeServer.ServiceStop(Sender: TService;
var Stopped: Boolean);
begin
IdTimeServer1.Active := False;
end;

儲存所有檔案 File -> Save All
建立並切換到專案目錄
例如 C:\Borland\Delphi7\Projects\TimeServer

更改預設檔案名稱
Unit1.pas -> TimeServerU.pas
Project1.dpr -> TimeServer.dpr

Complie Project 按 [Ctrl + F9] 編譯執行檔
專案目錄產生執行檔 TimeServer.exe

開啟 DOS 視窗(CMD)並切換到專案目錄
Start->Run...->CMD
例如專案目錄為 C:\Borland\Delphi7\Projects\TimeServer
> cd C:\Borland\Delphi7\Projects\TimeServer

安裝 TimeServer 服務
> TimeServer /install
若安裝成功, 會有對話框 Service installed successfully

啟動服務 DelphiTimeServer
> sc start DelphiTimeServer
SERVICE_NAME: DelphiTimeServer
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE,NOT_PAUSABLE,IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0xb97071
WAIT_HINT : 0x1388
PID : 3764
FLAGS :

用 Delphi 建立 Time Client Application
File->New->Application

放入 TIdTime 元件
Indy Servers -> IdTime

修改 TIdTime Properties (屬性)
Host = 'localhost'

加入 TForm Events (事件)
// OnCreate

procedure TForm1.FormCreate(Sender: TObject);
begin
Showmessage(DateTimeToStr(IdTime1.DateTime));
end;

執行程式, 會有對話框顯示目前時間

停止服務 DelphiTimeServer
> sc stop DelphiTimeServer
SERVICE_NAME: DelphiTimeServer
TYPE : 10 WIN32_OWN_PROCESS
STATE : 3 STOP_PENDING
(STOPPABLE,PAUSABLE,ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x1388

移除 TimeServer 服務
> TimeServer /uninstall
若移除成功, 會有對話框 Service uninstalled successfully

Retro Video For Delphi 2: Delphi Transformer

Delphi7 Webservice

Turbo Delphi video demo

http://blogs.codegear.com/nickhodges/index.php?p=26687

Delphi Drop Files Components

http://mh-nexus.de/components.htm
下載並安裝 Misc component package
使用 TDropFiles 來讀取一個文字檔
在 Form 上放入 TMemo 和 TDropFiles 元件
在 DropFiles1 加入 Target 屬性為 Memo1
在 DropFiles1 加入 ondropFiles 事件

procedure TForm1.DropFiles1DropFiles(Sender: TObject; Files: TStrings; X,
Y: Integer);
var
FileName: string;
begin
FileName := Files[0];
if FileExists(FileName) then begin
Memo1.Lines.LoadFromFile(FileName);
end;
end;

執行程式後,可拖曳檔案總管中所列的文字檔
到程式 Memo 中

Delphi TNT Unicode Controls

http://www.yunqa.de/delphi/tntunicodecontrols/
Latest free version from TntWare 2.3.0

Delphi 7 SynEdit Export HTML

須安裝 Delphi SynEdit 開發 IDE 元件
http://synedit.sourceforge.net/
在 Form 上按右鍵選擇 View as Text
或是按 [Alt + F12] 編輯 Delphi Form (DFM)
換掉原有 code, 貼入下列 code

object Form1: TForm1
Left = 193
Top = 129
Width = 507
Height = 301
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object SynEdit1: TSynEdit
Left = 0
Top = 29
Width = 499
Height = 234
Align = alClient
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Courier New'
Font.Style = []
TabOrder = 0
Gutter.Font.Charset = DEFAULT_CHARSET
Gutter.Font.Color = clWindowText
Gutter.Font.Height = -11
Gutter.Font.Name = 'Courier New'
Gutter.Font.Style = []
Gutter.ShowLineNumbers = True
Gutter.Gradient = True
Highlighter = SynPasSyn1
Lines.Strings = (
'procedure TForm1.FormCreate(Sender: TObject);'
'begin'
' ShowMessage(IntToStr(123)); '
' ShowMessage(md5sum(''c:\boot.ini'')); // FileName'
'end;')
end
object ToolBar1: TToolBar
Left = 0
Top = 0
Width = 499
Height = 29
ButtonHeight = 21
ButtonWidth = 68
Caption = 'ToolBar1'
ShowCaptions = True
TabOrder = 1
object ToolButton1: TToolButton
Left = 0
Top = 2
Caption = 'Export HTML'
ImageIndex = 0
onclick = ToolButton1Click
end
end
object SynPasSyn1: TSynPasSyn
CommentAttri.Foreground = clGreen
IdentifierAttri.Foreground = clNavy
NumberAttri.Foreground = clTeal
StringAttri.Foreground = clMaroon
Left = 8
Top = 40
end
object SynExporterHTML1: TSynExporterHTML
Color = clWindow
DefaultFilter = 'HTML Documents (*.htm;*.html)|*.htm;*.html'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Courier New'
Font.Style = []
Highlighter = SynPasSyn1
Title = 'Exported to file'
UseBackground = False
Left = 8
Top = 72
end
object SaveDialog1: TSaveDialog
DefaultExt = 'htm'
Left = 8
Top = 104
end
end

再按 [Alt + F12] 編輯 Object Pascal
換掉原有 code, 貼入下列 code

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SynEditExport, SynExportHTML, SynEditHighlighter,
SynHighlighterPas, ComCtrls, ToolWin, SynEdit;

type
TForm1 = class(TForm)
SynEdit1: TSynEdit;
SynPasSyn1: TSynPasSyn;
ToolBar1: TToolBar;
ToolButton1: TToolButton;
SynExporterHTML1: TSynExporterHTML;
SaveDialog1: TSaveDialog;
procedure ToolButton1Click(Sender: TObject);
private
public
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ToolButton1Click(Sender: TObject);
begin
with SynExporterHTML1 do
begin
SaveDialog1.Filter := DefaultFilter;
if SaveDialog1.Execute then
begin
ExportAsText := True;
ExportAll(SynEdit1.Lines);
SynExporterHTML1.SaveToFile(SaveDialog1.FileName);
end;
end;
end;

end.

執行程式, 按 Export HTML

Delphi SynEdit 開發 IDE 元件

http://synedit.sourceforge.net/

使用 Pascal highlighter
在 Form 上放入 SynEdit -> TSynEdit 和 SynEdit Highlighters -> TSynPasSyn
在 Form OnCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
with SynPasSyn1 do
begin
// set color
CommentAttri.Foreground := clGreen;
IdentifierAttri.Foreground := clNavy;
NumberAttri.Foreground := clBlue;
StringAttri.Foreground := clBlue;
end;
// set Highlighter
SynEdit1.Highlighter := SynPasSyn1;
with SynEdit1.Lines do
begin
// add Pascal code
Add('// Delphi source code');
Add('function StrToInt(const S: string): Integer;');
Add('var');
Add(' E: Integer;');
Add('begin');
Add(' Val(S, Result, E);');
Add(' if E <> 0 then ConvertErrorFmt(@SInvalidInteger, [S]);');
Add('end;');
end;
end;

Delphi 使用 Microsoft Agent

Microsoft Agent sous Delphi
http://zewaren.developpez.com/delphi/ms-agents/

Delphi Indy 取得本機(localhost) IP

在 Form 上放入 Indy Misc -> TIdIPWatch

procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessage(IdIPWatch1.LocalIP);
end;

Delphi 使用 Indy 取得檔案 md5sum


uses
IdHashMessageDigest, IdHash;

function md5sum(FileName: string): string;
var
MyMD5: TIdHashMessageDigest5;
Digest: T4x4LongWordRecord;
Stream: TStream;
begin
if FileExists(FileName) then begin
MyMD5 := TIdHashMessageDigest5.Create;
Stream := TFileStream.Create(FileName, fmOpenRead);
try
Digest := MyMD5.HashValue(Stream);
Result := MyMD5.AsHex(Digest);
finally
Stream.Free;
MyMD5.Free;
end;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessage(md5sum('c:\boot.ini')); // FileName
end;

Delphi 使用 Indy 取得超過 2G FILE SIZE


uses IdGlobalProtocols;

procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessage(IntToStr(FileSizeByName('FILE_NAME')));
end;

Delphi 使用 Windows API FindFirstFile 取得超過 2G FILE SIZE


function FileSize(const FileName: String): Int64;
var
LHFile: THandle;
lpFindFileData: TWin32FindData;
PSIZE: PULargeInteger;
begin
Result := 0;
LHFile := Windows.FindFirstFile(PChar(FileName), lpFindFileData);
if (LHFile <> INVALID_HANDLE_VALUE) then
begin
Windows.FindClose(LHFile);
PSIZE := @Result;
PSIZE.LowPart := lpFindFileData.nFileSizeLow;
PSIZE.HighPart := lpFindFileData.nFileSizeHigh;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
FileName: string;
begin
FileName := 'FileName'; // FileName
ShowMessage(IntToStr(FileSize(FileName)));
end;

Delphi 使用 Windows API GetFileSizeEx 取得超過 2G FILE SIZE


function GetFileSizeEx(hFile: THandle; lpFileSize: PLargeInteger): BOOL; stdcall; external kernel32 name 'GetFileSizeEx';

function FileSizeEx(const FileName: String): Int64;
var
LHFile: THandle;
begin
Result := 0;
LHFile := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
if (LHFile <> INVALID_HANDLE_VALUE) then
begin
GetFileSizeEx(LHFile, @Result);
CloseHandle(LHFile);
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessage(IntToStr(FileSizeEx('FileName'))); // FileName
end;

Delphi 使用 TLHelp32 列出 目前執行緒

在 Form 上放入 TMemo

uses
TLHelp32;

procedure TForm1.FormCreate(Sender: TObject);
var
hProcessSnap: THandle;
ProcessEntry32: TProcessEntry32;

procedure ShowProcess32;
begin
with Memo1.Lines do begin
Add(Format(
'%s ProcessID: %d ParentProcessID: %d Threads: %d Priority: %d',
[
ProcessEntry32.szExeFile,
ProcessEntry32.th32ProcessID,
ProcessEntry32.th32ParentProcessID,
ProcessEntry32.cntThreads,
ProcessEntry32.pcPriClassBase
]));

end;
end;
begin
hProcessSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap = INVALID_HANDLE_VALUE) then Exit;
try
ProcessEntry32.dwSize := SizeOf(ProcessEntry32);
if Process32First(hProcessSnap, ProcessEntry32) then begin
ShowProcess32;
repeat
ShowProcess32;
until not Process32Next(hProcessSnap, ProcessEntry32);
end;
finally
CloseHandle(hProcessSnap);
end;
end;

Delphi MSXML DOM XPath


{
XPath 參考網頁
http://www.w3.org/TR/xpath
在 uses 中加入 msxml, msxmldom
}
uses
msxml, msxmldom;
{
在 Form 上放一個 TMemo
在 FormCreate 事件中加入
}

procedure TForm1.FormCreate(Sender: TObject);
var
DOMDocument: IXMLDOMDocument;
begin
with memo1.Lines do
begin
Clear;
Add('<?xml version="1.0" encoding="Big5"?>');
Add('<html lang="en">');
Add(' <head>');
Add(' <title>Extensible Markup Language (XML)</title>');
Add(' </head>');
Add(' <body>');
Add(' <a href="1">first</a>');
Add(' <a href="2">second</a>');
Add(' </body>');
Add('</html>');
end;

DOMDocument := CreateDOMDocument;
DOMDocument.loadXML(memo1.Lines.Text);

with DOMDocument, Memo1.Lines do
begin
Clear;
Values['title'] := selectSingleNode('/html/head/title/text()').nodeValue;
Values['All Tag Count'] := IntToStr(selectNodes('//*').length);
Values['body Tag child Nodes Count'] := IntToStr(selectNodes('/*/body/*').length);
Values['a Tag Count'] := IntToStr(selectNodes('//a').length);
Values['First a Tag Text'] := selectSingleNode('//a[1]/text()').nodeValue;
Values['First a Tag href'] := selectSingleNode('//a[1]/@href').nodeValue;
Values['href equal 2 Text'] := selectSingleNode('//a[@href=2]/text()').nodeValue;
end;
end;
{
title=Extensible Markup Language (XML)
All Tag Count=6
body Tag child Nodes Count=2
a Tag Count=2
First a Tag Text=first
First a Tag href=1
href equal 2 Text=second
}

Delphi 使用 XML Mapper 來建立 Transformation File,並顯示資料表

COPY 一個 msn 的 message file
放到 project 中 msnmsg.xml

使用 Tools->XML Mapper
File->Open-> msnmsg.xml
在左方 Document 中 Select Message[*]
按右鍵 Select All Children
Create->Datapacket from XML
Create->Transformation
File->Save->Transformation
存到 project 中 ToDp.xtr

在 Form 中加入元件
DataAccess->TXMLTransformProvider
DataAccess->TClientDataSet
DataAccess->TDataSource
Data Controls->TDBGrid
Data Controls->TDBNavigator
在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
DBGrid1.Align := alClient;
DBNavigator1.Align := alBottom;
XMLTransformProvider1.XMLDataFile := 'msnmsg.xml';
XMLTransformProvider1.TransformRead.TransformationFile := 'ToDp.xtr';
ClientDataSet1.ProviderName := 'XMLTransformProvider1';
DataSource1.DataSet := ClientDataSet1;
DBGrid1.DataSource := DataSource1;
DBNavigator1.DataSource := DataSource1;
ClientDataSet1.Active := True;
end;

Delphi TXMLDocument XPath

XPath 參考網頁
http://www.w3.org/TR/xpath
在 Form 上放一個 TMemo 和 Internet TXMLDocument
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
SNode: IDOMNodeSelect;
begin
with XMLDocument1.XML do
begin
Add('<?xml version="1.0" encoding="Big5"?>');
Add('<html lang="en">');
Add(' <head>');
Add(' <title>Extensible Markup Language (XML)</title>');
Add(' </head>');
Add(' <body>');
Add(' <a href="1">first</a>');
Add(' <a href="2">second</a>');
Add(' </body>');
Add('</html>');
end;
XMLDocument1.Active := True;
with XMLDocument1.DOMDocument, Memo1.Lines do
begin
Clear;
SNode := documentElement as IDOMNodeSelect;
Values['title'] := SNode.selectNode('/html/head/title/text()').nodeValue;
Values['All Tag Count'] := IntToStr(SNode.selectNodes('//*').length);
Values['body Tag child Nodes Count'] := IntToStr(SNode.selectNodes('/*/body/*').length);
Values['a Tag Count'] := IntToStr(SNode.selectNodes('//a').length);
Values['First a Tag Text'] := SNode.selectNode('//a[1]/text()').nodeValue;
Values['First a Tag href'] := SNode.selectNode('//a[1]/@href').nodeValue;
Values['href equal 2 Text'] := SNode.selectNode('//a[@href=2]/text()').nodeValue;
end;
end;
{
title=Extensible Markup Language (XML)
All Tag Count=6
body Tag child Nodes Count=2
a Tag Count=2
First a Tag Text=first
First a Tag href=1
href equal 2 Text=second
}

Delphi 寫 DLL 程式

在宣告中加入

function Echo(pw: PWideChar): PWideChar; stdcall; external 'Project2.dll';

在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
w: PWideChar;
begin
w := PWideChar(UTF8Decode(#$E4#$BD#$A0#$E5#$A5#$BD)); // 你好 UTF-8
MessageBoxW(0, Echo(w), w, MB_OK);
end;

按【Ctrl + Alt + F11】 叫出 Project Manager
按右鍵 Add New Project...
New DLL Wizard
產生 library Project2
在 begin 之前加入

function Echo(pw: PWideChar): PWideChar; stdcall; export;
const
c: array[0..1] of WideChar = (WideChar($56DE), WideChar($50B3)); // 回傳 Unicode
var
w: WideString;
begin
w := c;
w := w + ': ' + pw;
Result := PWideChar(w);
end;

exports Echo;

編譯 Project2.dll 和 程式 Project1.exe
Project-> Bulid All Projects
執行 Project1.exe

Delphi 使用 WSDLImp 來建立 WebService Client Source Code

在 $(Delphi)\bin 目錄中有 WSDLImp 這個程式,
可產生 WebService Client Source Code

>WSDLImp
...
Usage: WSDLIMP [options] <WSDL[File|URL]|UDDI BindingKey>

Code Generation Options:
-C Generate C++ code -P Generate Pascal code
-R:name1;name2;name3 - Make out parameters with these names the return type
[ -option{+|-} default shown ]
-Oa- Map ambiguous classes to arrays -Oo+ One out param becomes return
-Ob- Use XMLBinding Manager for Schemas -Oq- Quiet mode (Suppress Headers)
-Od+ Generate Complex Type Destructors -Og- Use OLE GUIDs for interface
-Of- Process Faults -Os- Generate Server skeleton code
-Oi- Ignore Schema errors -Ot- Output unused types
-Ok+ Map named arrays to classes -Ou+ Unwind Literal Parameters
-Ol- Generate Literal types -Ov+ Verbose Info. in file
-On- Declare Types in Namespace -Ow+ Map strings to WideStrings
-Ox- Collapse simple Aliases
Other options:
-D<path> Output directory path -=+ Output filename after'=' in URL
-U<url of UDDI Registry> UDDI Registry [NOTE: input must be UDDI bindingkey(s)
@<Resp> Response file with list of WSDL|UDDIBindingKey to import

Proxy/Server Authentication:
-user:userName -pass:Password [-proxy:Proxy]

>WSDLImp http://api.google.com/GoogleSearch.wsdl
...
Reading: http://api.google.com/GoogleSearch.wsdl
Writing: GoogleSearch.pas
----------------------------------------------------------------------

uses
GoogleSearch;

procedure TForm1.FormCreate(Sender: TObject);
var
gs: GoogleSearchPort;
sr: GoogleSearchResult;
ra: ResultElementArray;
r: ResultElement;
I: Integer;
begin
gs := GetGoogleSearchPort(False,'http://api.google.com/search/beta2');
sr := gs.doGoogleSearch(
'?', // Google SOAP Search API 的 Key, 2006-12-05 日停發
'台中市', // query
0 ,2, // start, maxResults
False, // filter
'countryTW', //restrict 台灣地區
False, // safeSearch
'lang_zh-TW', // lr 繁體字
'UTF-8', // ie
'UTF-8'); // oe
with Memo1.Lines do
begin
Clear;
Add(FloatToStr(sr.searchTime));
ra := sr.resultElements;
for I := Low(ra) to High(ra) do
begin
r := ra[I];
Add(r.title);
Add(r.URL);
Add(r.snippet);
end;
end;
end;
{
0.019577
<b>台中市</b>政府.全球資訊網
http://www.tccg.gov.tw/
提供市府介紹、市政公告、活動、新聞、社會福利、生活資訊等。
<b>台中市</b>教育局
http://www.tceb.edu.tw/
含教育局網路導覽、公告、討論區以及各類研習線上報名系統。

}

Delphi 以WideString來做字集轉換


function WideStringToStr(CodePage: UINT; WStr: WideString): string;
var
Len: Integer;
begin
Len := WideCharToMultiByte(CodePage, 0, PWChar(WStr), -1, nil, 0, nil, nil);
SetLength(Result, Len);
WideCharToMultiByte(CodePage, 0, PWChar(WStr), Len, PChar(Result), Len, nil, nil);
end;

function StrToWideString(CodePage: UINT; Str: string): WideString;
begin
SetLength(Result, Length(Str));
MultiByteToWideChar(CodePage, MB_COMPOSITE, PChar(Str), -1, PWChar(Result), Length(Str));
end;

Delphi 使用 convert 將 DFM 二進位檔轉成文字檔

使用 convert -i 參數時記得先 backup

>convert
...
Usage: convert.exe [-i] [-s] [-t | -b]
-i Convert files in-place (output overwrites input)
-s Recurse subdirectories
-t Convert to text
-b Convert to binary

>cd [Project]
>convert -i -s -t *.DFM

Delphi 畫貝塞爾(Bezier)曲線

在 Form Paint 事件中加入

procedure TForm1.FormPaint(Sender: TObject);
var
Points: array of TPoint;
begin
Canvas.Pen.Width := 3;
Setlength(Points, 4);
Points[0].X := 0;
Points[0].y := 0;
Points[1].X := 0;
Points[1].y := 100;
Points[2].X := 150;
Points[2].y := 50;
Points[3].X := 150;
Points[3].y := 150;
Canvas.PolyBezier(Points);

Points[0].X := 150;
Points[0].y := 150;
Points[1].X := 150;
Points[1].y := 200;
Points[2].X := 200;
Points[2].y := 250;
Points[3].X := 250;
Points[3].y := 250;
Canvas.PolyBezier(Points);
end;

Delphi 使用 TWebBrowser


在 Form 上放入 Internet -> TWebBrowser

procedure TForm1.FormCreate(Sender: TObject);
var
Browser: Variant;
Document: Variant;
begin
WebBrowser1.Align := alClient;
Browser := WebBrowser1.OleObject;
Browser.navigate('about:blank');
Document := Browser.document;
Document.open;
Document.writeln('<html>');
Document.writeln('<body bgcolor=#000000 text=#ffffff>');
Document.writeln('Hello World!');
Document.writeln('</body>');
Document.writeln('</html>');
Document.close;
end;

Delphi TADODataSet Save To File Load From File

TADODataSet 可以將資料庫 Table 保存到檔案中
放入 TADODataSet、TDataSource、TDBGrid

procedure TForm1.FormCreate(Sender: TObject);
begin
DataSource1.DataSet := ADODataSet1;
DBGrid1.DataSource := DataSource1;
DBGrid1.Align := alClient;
with ADODataSet1 do
begin
ConnectionString :=
'FILE NAME=C:\Program Files\Common Files\System\Ole DB\Data Links\DBDEMOS.udl';
CommandText := 'select * from country';
Active := True;
// 存入檔案
SaveToFile('country.adtg');
// 關掉連線
Close;
ConnectionString := '';
CommandText := '';
// 從檔案中載入資料
LoadFromFile('country.adtg');
end;
end;

Delphi 使用 ShellExecute 顯示 GoogleMaps

放入二個 TEdit 更名為 EdtLatitude EdtLongitude,再放入一個 TButton
在 Button1 Click 事件中加入

uses
ShellAPI;

procedure TForm1.Button1Click(Sender: TObject);
var
url: string;
begin
url := 'http://maps.google.com/maps?ll=' +
EdtLatitude.Text + ',' +
EdtLongitude.Text;
ShellExecute(Handle, nil, PAnsiChar(url), nil, nil, SW_SHOWNORMAL);
end;

執行程式後,輸入 Latitude 及 Longitude 按 Button1 後就可顯示 Google 的地圖了

Delphi 程式設計工具

GExperts: Programming Tools for Delphi and C++Builder
http://www.gexperts.org/

CnPack IDE 專家包(CnWizards)是一組集成在 Delphi/C++ Builder 的 IDE 中,用於增強 IDE 功能、提高 IDE 的可用性及開發效率的工具
http://www.cnpack.org

Delphi 多執行序控制


type
// 宣告執行序
TTestThread = class(TThread)
private
FStrings: TStrings;
procedure AddToStrings;
class procedure Buttonclick(Sender: TObject);
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean; Strings: TStrings);
end;

var
TestThread1, TestThread2: TTestThread;

// 列出執行序的 ThreadID
procedure TTestThread.AddToStrings;
begin
FStrings.Add('ThreadID: ' + IntToStr(ThreadID));
end;

class procedure TTestThread.Buttonclick(Sender: TObject);
begin
with Sender as TToolButton do
begin
if Down then begin
// 執行
TTestThread(Tag).Resume;
end else begin
// 暫停
TTestThread(Tag).Suspend;
end;
end;
end;

{
CreateSuspended 建立時先不執行
Strings 要列出訊息的 Strings
}
constructor TTestThread.Create(CreateSuspended: Boolean; Strings: TStrings);
begin
inherited Create(CreateSuspended);
FStrings := Strings;
end;

procedure TTestThread.Execute;
begin
// 當未停止時列出執行序的 ThreadID
while not Terminated do
begin
Synchronize(AddToStrings);
Sleep(1000);
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
ToolBar: TToolBar;
begin

// 建立 TMemo
with TMemo.Create(Self) do
begin
Parent := Self;
Align := alClient;
Clear;
// 印出主執行序 MainThreadID
Lines.Add(IntToStr(MainThreadID));
// 建立執行序,並在建立時就執行運作
TestThread1 := TTestThread.Create(False, Lines);
TestThread2 := TTestThread.Create(False, Lines);
end;

// 建立 TToolBar
ToolBar := TToolBar.Create(Self);
with ToolBar do
begin
Parent := Self;
ShowCaptions := True;
with TToolButton.Create(Self) do
begin
Parent := ToolBar;
Caption := 'TestThread2';
Tag := Integer(TestThread2);
onclick := TTestThread.Buttonclick;
Style := tbsCheck;
Down := True;
end;
with TToolButton.Create(Self) do
begin
Parent := ToolBar;
Caption := 'TestThread1';
Tag := Integer(TestThread1);
onclick := TTestThread.Buttonclick;
Style := tbsCheck;
Down := True;
end;
end;


end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// 停止執行序
with TestThread1 do
begin
if Suspended then begin
Resume;
Terminate;
end
end;
with TestThread2 do
begin
if Suspended then begin
Resume;
Terminate;
end
end;
TestThread1.Free;
TestThread2.Free;
end;

Delphi Thread


type
// 宣告執行序
TTestThread = class(TThread)
private
FStrings: TStrings;
procedure AddToStrings;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean; Strings: TStrings);
end;

// 列出執行序的 ThreadID
procedure TTestThread.AddToStrings;
begin
FStrings.Add('ThreadID: ' + IntToStr(ThreadID));
end;

{
CreateSuspended 建立時先不執行
Strings 要列出訊息的 Strings
}
constructor TTestThread.Create(CreateSuspended: Boolean; Strings: TStrings);
begin
inherited Create(CreateSuspended);
FStrings := Strings;
end;

procedure TTestThread.Execute;
begin
// 當未停止時列出執行序的 ThreadID
while not Terminated do
begin
Synchronize(AddToStrings);
Sleep(1000);
end;
end;

var
TestThread: TTestThread;

procedure TForm1.FormCreate(Sender: TObject);
begin
// 印出主執行序 MainThreadID
Memo1.Lines.Add('MainThreadID: ' + IntToStr(MainThreadID));
// 建立執行序,並在建立時就執行運作
TestThread := TTestThread.Create(False, Memo1.Lines);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// 停止執行序
TestThread.Terminate;
TestThread.Free;
end;

Delphi MSXML DOM XSLT 轉換


{
XSLT 參考網頁
http://www.w3.org/TR/xslt
在 uses 中加入 msxml, msxmldom
}
uses
msxml, msxmldom;
{
在 Form 上放一個 TMemo
在 FormCreate 事件中加入
}

procedure TForm1.FormCreate(Sender: TObject);
var
DOMDocument: IXMLDOMDocument;
Data: IXMLDOMDocument;
begin
// 資料
with memo1.Lines do
begin
Clear;
Add('<?xml version="1.0" encoding="Big5"?>');
Add('<data>');
Add(' <title>Extensible Markup Language (XML)</title>');
Add(' <text>first</text>');
Add(' <text>second</text>');
Add('</data>');
end;
Data := CreateDOMDocument;
Data.loadXML(memo1.Lines.Text);

// 樣板
with memo1.Lines do
begin
Clear;
Add('<?xml version="1.0" encoding="Big5"?>');
Add('<xsl:stylesheet version="1.0" ');
Add(' xmlns:xsl="http://www.w3.org/1999/XSL/Transform">');
Add('<xsl:template match="data">');
Add(' <html>');
Add(' <head>');
Add(' <title><xsl:value-of select="title"/></title>');
Add(' </head>');
Add(' <body>');
Add(' <xsl:for-each select="text">');
Add(' <li><xsl:value-of select="text()"/></li>');
Add(' </xsl:for-each>');
Add(' </body>');
Add(' </html>');
Add('</xsl:template>');
Add('</xsl:stylesheet>');
end;
DOMDocument := CreateDOMDocument;
DOMDocument.loadXML(memo1.Lines.Text);

// 轉換
Memo1.Lines.Text := Data.transformNode(DOMDocument.documentElement);
end;

{ Memo1

<html>
<head>
<META http-equiv="Content-Type" content="text/html">
<title>Extensible Markup Language (XML)</title>
</head>
<body>
<li>first</li>
<li>second</li>
</body>
</html>

}

使用 Delphi SHFileOperationW 刪除檔案到資源回收筒


uses
ShellAPI;

procedure TForm1.FormCreate(Sender: TObject);
var
FileOpStrucW: TSHFileOpStructW;
F1, F2: PWideChar;
begin
F1 := PWideChar(WideString('C:\f1.txt'));
F2 := PWideChar(WideString('C:\temp.txt'));
FileOpStrucW.Wnd := Application.Handle;
with FileOpStrucW do
begin
wFunc := FO_COPY; // 複製
pFrom := F1;
pTo := F2;
fFlags := 0;
end;
SHFileOperationW(FileOpStrucW);

with FileOpStrucW do
begin
wFunc := FO_DELETE; // 刪除
pFrom := F2;
pTo := nil;
fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION; // 直接丟進 RecycleBin
end;
SHFileOperationW(FileOpStrucW);
end;

JEDI VCL for Delphi


JEDI VCL for Delphi
http://sourceforge.net/projects/jvcl

下載後執行安裝
\jcl\Install.bat
\jvcl\install.bat

使用 JclSysInfo 取得環境變數

uses
JclSysInfo;

procedure TForm1.FormCreate(Sender: TObject);
begin
GetEnvironmentVars(Memo1.Lines);
ShowMessage(GetWindowsFolder);
end;

Delphi 以類別名稱來建立有建構參數的物件


type
// ...

TMyParent = class(TComponent)
public
function echo(name: string): string; virtual; abstract;
end;

TMyParentClass = class of TMyParent;

TMySub1 = class(TMyParent)
private
s: string;
public
constructor Create(AOwner: TComponent); override;
function echo(name: string): string; override;
end;

// ...

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
PClass: TPersistentClass;
Obj: TMyParent;
begin
RegisterClass(TMySub1);
PClass := FindClass('TMySub1');
Obj := TMyParentClass(PClass).Create(Self);
Caption := Obj.echo('Solnone');
UnRegisterClass(TMySub1);
end;

constructor TMySub1.Create(AOwner: TComponent);
begin
s := AOwner.GetNamePath + ' TMySub1 ';
end;

function TMySub1.echo(name: string): string;
begin
Result := s+ 'Hello ' + name;
end;

// Form1 TMySub1 Hello Solnone

使用 Delphi DCC32 Compiler


在 命令提示字元 (cmd) 中可以用 DCC32 來 Compiler Delphi 程式!
它的設定檔為 DCC32.CFG ,內容為預設參數,可用 notepad 編輯

-aWinTypes=Windows;WinProcs=Windows;DbiProcs=BDE;DbiTypes=BDE;DbiErrs=BDE
-u"C:\Delphi7\lib";"C:\Delphi7\lib\Obj"

在 cmd 中輸入 DCC32 --help 列出可用的參數

>dcc32 --help
Syntax: dcc32 [options] filename [options]

-A<unit>=<alias> = Set unit alias -LU<package> = Use package
-B = Build all units -M = Make modified units
-CC = Console target -N<path> = DCU output directory
-CG = GUI target -O<paths> = Object directories
-D<syms> = Define conditionals -P = look for 8.3 file names also
-E<path> = EXE output directory -Q = Quiet compile
-F<offset> = Find error -R<paths> = Resource directories
-GD = Detailed map file -U<paths> = Unit directories
-GP = Map file with publics -V = Debug information in EXE
-GS = Map file with segments -VR = Generate remote debug (RSM)
-H = Output hint messages -W = Output warning messages
-I<paths> = Include directories -Z = Output 'never build' DCPs
-J = Generate .obj file -$<dir> = Compiler directive
-JP = Generate C++ .obj file --help = Show this help screen
-K<addr> = Set image base addr --version = Show name and version
Compiler switches: -$<letter><state> (defaults are shown below)
A8 Aligned record fields P+ Open string params
B- Full boolean Evaluation Q- Integer overflow checking
C+ Evaluate assertions at runtime R- Range checking
D+ Debug information T- Typed @ operator
G+ Use imported data references U- Pentium(tm)-safe divide
H+ Use long strings by default V+ Strict var-strings
I+ I/O checking W- Generate stack frames
J- Writeable structured consts X+ Extended syntax
L+ Local debug symbols Y+ Symbol reference info
M- Runtime type info Z1 Minimum size of enum types
O+ Optimization

編譯 Project1.dpr

>dcc32 Project1.dpr
\Project1.dpr(14)
15 lines, 0.22 seconds, 342368 bytes code, 7657 bytes data.

使用 TStrings CommaText 和 DelimitedText 組合字串


procedure TForm1.FormCreate(Sender: TObject);
var
Strs: TStrings;
begin
Strs := TStringList.Create;
try
with Strs do
begin
Add('String'' 1');
Add('String" 2');
Add('String 3');
QuoteChar := '''';
Delimiter := ',';
end;
with Memo1.Lines do
begin
Clear;
Values['CommaText'] := Strs.CommaText;
Add('SQL Strings');
Add('INSERT INTO TABLE1 (FIELD1, FIELD2, FIELD3)');
Add('VALUES (' + Strs.DelimitedText + ')');
end;
finally
Strs.Free;
end;
end;

{
CommaText="String' 1","String"" 2","String 3"
SQL Strings
INSERT INTO TABLE1 (FIELD1, FIELD2, FIELD3)
VALUES ('String'' 1','String" 2','String 3')
}

Delphi 取出資料庫欄位值的方法

在 Form 上放入 TMemo 和 TQuery
在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
Index: Integer;
begin
with Query1, Memo1 do
begin
Lines.Clear;
DatabaseName := 'DBDEMOS';
SQL.Clear;
SQL.Add('SELECT NAME, CAPITAL, CONTINENT, AREA, POPULATION');
SQL.Add(' FROM COUNTRY');
SQL.Add(' WHERE NAME = ' + QuotedStr('Argentina'));
Active := True;
// 列出所有欄位名稱
Lines.Add('-- List Field Name --');
Lines.AddStrings(FieldList);
if IsEmpty then
Exit;
Lines.Add('-- Get Field Value --');
while not Eof do
begin
// 以 field name 取出值
Lines.Add(VarToStr(FieldByName('NAME').AsVariant));
Lines.Add(VarToStr(FindField('CAPITAL').AsVariant));
Lines.Add(VarToStr(FindField('CONTINENT').AsVariant));
Lines.Add(VarToStr(FieldValues['AREA']));
//
// 以 field index 取出 POPULATION 值
Index := FieldList.IndexOf('POPULATION');
Lines.Add(VarToStr(Fields[Index].AsVariant));
Lines.Add(VarToStr(FieldList[Index].AsVariant));
Next;
end;
end;
end;
{
-- List Field Name --
NAME
CAPITAL
CONTINENT
AREA
POPULATION
-- Get Field Value --
Argentina
Buenos Aires
South America
2777815
32300003
32300003
}

Delphi 使用 FindGlobalComponent 來取得 Form

FindGlobalComponent 可以在不使用 uses 的情況下來取得有被建立的 Form
先 new 一個 Form2
在 Form2 Create 事件中加入

procedure TForm2.FormCreate(Sender: TObject);
begin
(FindGlobalComponent('Form1') as TForm).Caption := 'Show From Form2';
end;

執行程式後 Form1 的 Caption 會被改成 Show From Form2

Delphi 使用 TShellChangeNotifier 得知目錄中的檔案異動

在元件面版 Samples 中有 TShellChangeNotifier 及 TShellListView
在 Form 上放入這二個元件
在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
with ShellListView1 do
begin
Align := alClient;
ViewStyle := vsReport;
Root := 'C:\'; // 要顯示的目錄
end;
with ShellChangeNotifier1 do
begin
WatchSubTree := False;
Root := ShellListView1.Root; // 要偵測的目錄
end;
end;

在 ShellChangeNotifier1 Change 事件中加入

procedure TForm1.ShellChangeNotifier1Change;
begin
ShellListView1.Refresh; // 更新 ListView
Application.ProcessMessages;
ShowMessage('Change');
end;

使用 Delphi TFrame


TFrame 可以將一些常用的元件事先做排版,或是寫入共用method 等
例如常要顯示資料庫中的 Table 時
選 Menu File->New->Frame 來加入一個 Frame2
可將 TTable,TDataSource,TDBGrid,TDBNavigator 放入 Frame2 中
先設好關連
DataSource1.DataSet := Table1;
DBGrid1.DataSource := DataSource1;
DBNavigator1.DataSource := DataSource1;

在 Form1 上放入二個以上的 Frame2 (在元件面版上 Standard -> Frames, 選擇 Frame2 後按 OK)
就可以分別設定 Frame 中 Table1 的 DatabaseName 和 TableName 來顯示不同的 Table

Delphi 的四捨五入

在 Form 上放入一個 TMemo

uses
Math;

// 參考 SimpleRoundTo 來寫的四捨五入,和 format 的結果相同
function MyRoundTo(const AValue: Extended; const ADigit: TRoundToRange = -2): Extended;
var
LFactor: Extended;
f: Extended;
begin
LFactor := IntPower(10, ADigit);
if AValue < 0 then
f := -0.5
else
f := 0.5;
Result := Trunc((AValue / LFactor) + f) * LFactor;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
with Memo1.Lines do
begin
Clear;
Add('RoundTo 0.12345 小數四位 = ' + FloatToStr(RoundTo(0.12345, -4)));
Add('RoundTo -0.12345 小數四位 = ' + FloatToStr(RoundTo(-0.12345, -4)));
Add('RoundTo 123450 捨十位 = ' + FloatToStr(RoundTo(123450, 2)));
Add('SimpleRoundTo 0.12345 小數四位 = ' + FloatToStr(SimpleRoundTo(0.12345, -4)));
Add('SimpleRoundTo -0.12345 小數四位 = ' + FloatToStr(SimpleRoundTo(-0.12345, -4)));
Add('SimpleRoundTo 123450 捨十位 = ' + FloatToStr(SimpleRoundTo(123450, 2)));
Add('MyRoundTo 0.12345 小數四位 = ' + FloatToStr(MyRoundTo(0.12345, -4)));
Add('MyRoundTo -0.12345 小數四位 = ' + FloatToStr(MyRoundTo(-0.12345, -4)));
Add(Format('Format 0.12345 小數四位 = %.4f', [0.12345]));
Add(Format('Format -0.12345 小數四位 = %.4f', [-0.12345]));
end;
end;

{ Memo1 的結果
RoundTo 0.12345 小數四位 = 0.1234
RoundTo -0.12345 小數四位 = -0.1234
RoundTo 123450 捨十位 = 123400
SimpleRoundTo 0.12345 小數四位 = 0.1234
SimpleRoundTo -0.12345 小數四位 = -0.1233
SimpleRoundTo 123450 捨十位 = 123500
MyRoundTo 0.12345 小數四位 = 0.1235
MyRoundTo -0.12345 小數四位 = -0.1235
Format 0.12345 小數四位 = 0.1235
Format -0.12345 小數四位 = -0.1235
}

Delphi TListView 的排序

在 Form 上放入 TListView 元件
在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
with ListView1 do
begin
ViewStyle := vsReport;
Columns.Add.Caption := 'A';
Columns.Add.Caption := 'B';

with Items.Add do
begin
Caption := '3';
SubItems.Add('3');
end;

with Items.Add do
begin
Caption := '2';
SubItems.Add('1');
end;
with Items.Add do
begin
Caption := '1';
SubItems.Add('2');
end;
end;
end;

在 TForm1 的 private 宣告中加入

private
SortColumn: TListColumn; // 排序欄位

在 TListView ColumnClick 事件中加入

procedure TForm1.ListView1ColumnClick(Sender: TObject;
Column: TListColumn);
begin
SortColumn := Column;
(Sender as TCustomListView).AlphaSort; // 排序
SortColumn.Tag := not SortColumn.Tag; // tag 紀錄正反排
end;

在 TListView Compare 事件中加入

procedure TForm1.ListView1Compare(Sender: TObject; Item1, Item2: TListItem;
Data: Integer; var Compare: Integer);
var
ix: Integer;
begin
if SortColumn.Index = 0 then
Compare := CompareText(Item1.Caption, Item2.Caption)
else begin
ix := SortColumn.Index - 1;
Compare := CompareText(Item1.SubItems[ix], Item2.SubItems[ix]);
end;
if Boolean(SortColumn.Tag) then begin
Compare := -Compare; // 反排
end;
end;

執行程式後,就可用滑鼠按 ListView 的 Column Header 來做正反排

Delphi ShellExecute 執行外部程式


uses
ShellAPI;

procedure TForm1.FormCreate(Sender: TObject);
begin
// 執行 notepad
ShellExecute(Handle, nil, 'notepad', nil, nil, SW_SHOWNORMAL);
// 打開 word 檔
ShellExecute(Handle, 'oppen', 'C:\a.doc', nil, nil, SW_SHOWNORMAL);
// 列印 excel 檔
ShellExecute(Handle, 'print', 'C:\a.xls', nil, nil, SW_SHOWNORMAL);
// 開網頁
ShellExecute(Handle, nil, 'http://www.borland.com/', nil, nil, SW_SHOWNORMAL);
// 寄信
ShellExecute(Handle, nil, 'mailto:name@host.com?subject=主旨&body=內文', nil, nil, SW_SHOWNORMAL);
end;

Delphi 單位換算 Convert Function


uses
StdConvs, ConvUtils;

在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
// 攝氏 23 -> 華氏 73.4
ShowMessage(FloatToStr(CelsiusToFahrenheit(23)));
// 華氏 73.4 -> 攝氏 23
ShowMessage(FloatToStr(FahrenheitToCelsius(73.4)));
// 攝氏 23 -> 華氏 73.4
ShowMessage(FloatToStr(Convert(23, tuCelsius , tuFahrenheit)));
// 1 年 -> 365.25 天
ShowMessage(FloatToStr(Convert(1, tuYears , tuDays)));
// 1 kg -> 1000 g
ShowMessage(FloatToStr(Convert(1, muKilograms , muGrams)));
// 1 公尺 -> 100 公分
ShowMessage(FloatToStr(Convert(1, duMeters , duCentimeters)));
end;

Delphi To-Do List

在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
Strings: TStrings;
begin
Strings := typename.Create;
try
// 在此按【Ctrl+Shift+T】叫出 Add To-Do Item
// 或是按滑鼠右鍵選 Add To-Do Item
// 在 Text: 輸入 Add Text to Strings
// 在 Priority: 輸入 1
// 在 Owner: 輸入 UserName
// 在 Category: 輸入 Normal
finally
Strings.Free;
end;
end;


procedure TForm1.FormCreate(Sender: TObject);
var
Strings: TStrings;
begin
Strings := typename.Create;
try
{ TODO 1 -oUserName -cNormal : Add Text to Strings}
finally
Strings.Free;
end;
end;

在功能表 View -> To-Do List 中可以看到所有的 To-Do Item
並可加以排序、修改、匯出 Html 報表等,做完的 Item 可以打勾變成 DONE

Delphi 動態取得及設定物件的屬性,使用 ObjAuto


uses
ObjAuto ,TypInfo;

在 Form 上放入一個 TMemo
將 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
PropList: PPropList;
Count, i: Integer;
PropInfo: PPropInfo;
PropName: string;
Value: Variant;
begin
ShowHint := True;
Memo1.Clear;

// 動態設定物件的屬性 Memo1.Hint := 'test SetPropValue';
SetPropValue(Memo1, 'Hint', 'test SetPropValue');

Count := GetPropList(Memo1, PropList); // 取得 TMemo 的屬性
for i := 0 to Count -1 do begin
PropInfo := PropList[i];
PropName := PropInfo.Name; // 屬性名稱
// 動態取得物件屬性的質 Value := Memo1.?;
Value := GetPropValue(Memo1, PropInfo.Name);
// 印出屬性及其質
Memo1.Lines.Values[PropName] := VarToStr(Value);
end;
ShowMessage(Memo1.Hint);
end;

{
Name=Memo1
Tag=0
Left=27
Top=8
Width=565
Height=322
Cursor=0
Hint=test SetPropValue
HelpType=htContext
HelpContext=0
TabStop=True
Align=alNone
Alignment=taLeftJustify
Anchors=akLeft,akTop
BevelEdges=beLeft,beTop,beRight,beBottom
...
}

Delphi 使用 TypInfo 列出元件的屬性

在 Form 上放入一個 TMemo

uses
TypInfo;

在 From Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
PropList: PPropList;
Count, i: Integer;
PropInfo: PPropInfo;
begin
Memo1.Clear;
Count := GetPropList(Memo1, PropList); // 取得 TMemo 的屬性
for i := 0 to Count -1 do begin
PropInfo := PropList[i];
// 印出屬性及類型
Memo1.Lines.Add(PropInfo.Name + ': ' + PropInfo.PropType^^.Name);
end;
end;

{
Name: TComponentName
Tag: Integer
Left: Integer
Top: Integer
Width: Integer
Height: Integer
Cursor: TCursor
Hint: String
HelpType: THelpType
HelpKeyword: String
...
}

Delphi 使用 TApplicationEvents 來處理 Exception

在 Form 上放入 TMemo 和 TApplicationEvents
在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
raise Exception.Create('Test Exception'); // 丟出例外
end;

在 ApplicationEvents Exception 事件中加入

procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
begin
Memo1.Lines.Add(E.Message); // 將例外印在 Memo1 上
end;

指定 Delphi 的編譯條件

在 Project -> Options -> Directories / Conditionals 中
有 Conditional defines 可以設定 編譯條件,有多個條件時以分號分隔
在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
{$IFDEF DEBUG}
ShowMessage('DEBUG Conditional');
{$ELSE}
ShowMessage('Normal');
{$ENDIF}
end;

執行程式後會顯示 'Normal'
在 Conditional defines 入框中輸入 DEBUG 按 ok 後重 build
Project -> Build Project1
再次執行程式後會顯示 'DEBUG Conditional'

Delphi 使用 TActionList

在 Form 上放入 TMemo, TToolBar, TActionList, TImageList
設定屬性 ToolBar1.Images := ImageList1
設定屬性 ActionList1.Images := ImageList1
Double Click ActionList1 開啟 Editing 對話框
在 Editing 中按 New Standard Action...【Ctrl+Ins】 來開啟 Standard Action Classes 對話框
選擇所有 Edit 分類中的 class (TEditCut, TEditCopy, TEditPaste...) ,按 ok 加入這些 Action
在 ToolBar1 上按右鍵加入五個 TToolButton
在 ToolBar1 中
設定屬性 ToolButton1.Action := EditCut1
設定屬性 ToolButton2.Action := EditCopy1
設定屬性 ToolButton3.Action := EditPaste1
設定屬性 ToolButton4.Action := EditUndo1
設定屬性 ToolButton5.Action := EditDelete1

執行程式後 ToolBar1 上的 Button 就會依照目前 focus 的元件來運作(Copy, Paste...)
不可用的 Button 會變成灰色

Deiphi 使用 TObjectList 來管理物件


uses
Contnrs;

在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
list: TObjectList;
Strings1, Strings2: TStrings;
begin
list := TObjectList.Create(True); // Owns Objects
try
Strings1 := TStringList.Create;
list.Add(Strings1);
Strings1.Add('select * from a ...');

Strings2 := TStringList.Create;
list.Add(Strings2);
(list.Items[1] as TStrings).Add('select * from b ...');
finally
list.Free; // Free list ( Strings1, Strings2 ... )
end;
end;

使用 Delphi 來讀取 Registry 的資料

使用 TRegistry 來讀取 Windows 啟動時執行的程式

uses
Registry;

在 Form 上放一個 TMemo
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
const
key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run'; // Registry Key
var
i: Integer;
Registry: TRegistry;
Strings: TStrings;
Name: string;
begin
Memo1.Clear;
Strings := TStringList.Create;
Registry := TRegistry.Create;
try
Memo1.Lines.Add('<< HKEY_CURRENT_USER >>');
Registry.RootKey := HKEY_CURRENT_USER;
Registry.OpenKey(key, False);
Registry.GetValueNames(Strings);
for i := 0 to Strings.Count -1 do
begin
Name := Strings[i];
Memo1.Lines.Values[Name] := Registry.ReadString(Name);
end;
Registry.CloseKey;
Memo1.Lines.Add('<< HKEY_LOCAL_MACHINE >>');
Registry.RootKey := HKEY_LOCAL_MACHINE;
Registry.OpenKey(key, False);
Registry.GetValueNames(Strings);
for i := 0 to Strings.Count -1 do
begin
Name := Strings[i];
Memo1.Lines.Values[Name] := Registry.ReadString(Name);
end;
Registry.CloseKey;
finally
Registry.Free;
Strings.Free;
end;
end;

使用 log4delphi

先到 log4delphi 下載 Binary Package
http://log4delphi.sourceforge.net/
我目前下載的是 log4delphi-0.7-bin

解壓縮後 設定 Delphi 的 Library path
Tools -> Environment Options -> Library -> Library path
加入 解壓目錄中的 \log4delphi-0.7\bin

log4delphi 的設定檔有一個範本檔在 log4delphi-0.7\example\log4delphi.properties
建立一個新專案並存檔,複製 log4delphi.properties 到專案目錄之中

編輯專案中的 log4delphi.properties

# LEVEL 設為 DEBUG,使用 fileAppender 來記錄 log
log4delphi.rootLogger=DEBUG, fileAppender
# …
log4delphi.appender.fileAppender=TFileAppender
# …
# log file 設為程式執行目錄下的 app.log
log4delphi.appender.fileAppender.File=app.log
log4delphi.appender.fileAppender.AppDir=true
# …
# 將 layout 換成 TPatternLayout 來紀錄時間等資訊
#log4delphi.appender.fileAppender.layout=TSimpleLayout
log4delphi.appender.fileAppender.layout=TPatternLayout
log4delphi.appender.fileAppender.layout.Pattern=%d{dd mmm yyyy hh:nn:ss:zzz} [%5p] %m%n
# …

儲存 log4delphi.properties
在 Form Unit 的 implementation 區中加入

uses
TConfiguratorUnit, TLoggerUnit;

var
logger : TLogger;

// 在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
logger.debug('Debug message');
logger.info('Info message');
logger.warn('Warn message');
logger.error('Error message');
logger.fatal('Fatal message');
end;

initialization
TConfiguratorUnit.doPropertiesConfiguration('log4delphi.properties');
logger := TLogger.getInstance; // Create or Get Instance

finalization
TLogger.freeInstances; // Free

執行程式後,程式執行目錄下 log 會存入 app.log

Delphi 的 TStrings

Delphi 的很多元件中都有 TStrings 的存在
在 Form 上放入 TValueListEditor, TMemo, TListBox, TComboBox, TRadioGroup, TCheckListBox, TListView, TQuery

uses
Printers;

在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
// ValueListEditor1.Strings 為 TStrings 子類別
with ValueListEditor1 do
begin
Values['TW'] := '臺灣'; // TW=臺灣
Values['CN'] := '中國'; // CN=中國
Strings.AddStrings(Printer.Printers); // 加列出印表機
// Printer.Printers 為 TStrings 子類別
Memo1.Lines := Strings; //
ListBox1.Items := Strings; //
RadioGroup1.Items := Strings; //
CheckListBox1.Items := Strings; //
ComboBox1.Items := Strings; //
ComboBox1.ItemIndex := 0;

Query1.SQL := Strings; // 測試用 Query1.SQL 也是 TStrings 子類別

with ListView1 do
begin
ViewStyle := vsReport;
Columns.Add.Caption := 'Caption';
Columns.Add.Caption := 'A';
Columns.Add.Caption := 'B';
with ListView1.Items.Add do
begin
Caption := '1';
SubItems := Strings; //
end;
end;
end;
end;

執行程式後除了 Query1 是不可見外,其它元件可以看到

Delphi 使用 DisableControls 加快對 DataSet 的操作

在 Form 上放一個 TTable、TDataSource、TDBGrid、TButton 和 TComboBox
在 Form Create 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
DataSource1.DataSet := Table1;
DBGrid1.DataSource := DataSource1;
Table1.DatabaseName := 'BCDEMOS';
Table1.TableName := 'BDESDD.DB';
Table1.Active := True;
end;

在 Button1 Click 事件中加入

procedure TForm1.Button1Click(Sender: TObject);
var
n: string;
begin
ComboBox1.Items.Clear;
with Table1 do
begin
DisableControls; // 讓 DataSource 等元件停止運作,可加快 Next 的運作
try
First;
while not Eof do
begin
n := FieldByName('NAME').AsString;
// 將所有不重複 NAME 的資料 加入 ComboBox1 中
// 判斷長度大於 0 而且尚未加入 ComboBox1 中
if (Length(n) > 0) and (ComboBox1.Items.IndexOf(n) = -1) then
begin
ComboBox1.Items.Add(n);
end;
// ...
Next;
end;
finally
EnableControls; // 讓 DataSource 等元件運作
end;
end;

end;

Delphi Variant 和 VarArrayCreate

在 Form 上放一個 TMemo
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
v: Variant;
t: TVarType;
I: integer;
begin
with Memo1.Lines do
begin
Clear;

t := VarType(v); // 取得 Variant Type
if t = varEmpty then begin
Add('Empty Type'); // 初始為 Empty Type
end;

if VarIsEmpty(v) then begin
Add('Is Empty'); // 初始值為 Empty
end;

if VarIsClear(v) then begin
Add('Is Clear'); // Clear
end;

v := VarArrayCreate([0, 3], varVariant); // 建立陣列 array[0..3] of Variant
v[0] := 'Hello World';
v[1] := 1234.56;
v[2] := Now;
v[3] := Null; // 設為 Null

if VarIsArray(v) then begin
Add('Is Array, Length: ' +
IntToStr(VarArrayHighBound(v, 1) - VarArrayLowBound(v, 1)));
end;

for i := VarArrayLowBound(v, 1) to VarArrayHighBound(v, 1) do
begin
Add(Format('v[%d]: %s',[i, QuotedStr(VarToStr(v[i]))])); // 轉成字串
end;

if VarIsStr(v[0]) then begin
Add('v[0] Is String');
end;
if VarIsFloat(v[1]) then begin
Add('v[1] Is Float');
end;

if VarIsType(v[2], varDate) then begin
Add('v[2] Is Date');
end;
if VarIsNull(v[3]) then begin
Add('v[3] Is Null');
end;

VarClear(v); // 清為 Empty
if VarIsClear(v) and VarIsEmpty(v) then begin
Add('Is Clear and Empty'); // Clear
end;
end;
end;

Delphi 設定預設印表機


procedure SetDefaultPrinter(NewPrintName: string);
var
buffer: array[0..255] of Char;
name: string;
begin
name := NewPrintName;
if AnsiPos(',', name) = 0 then begin
name := name + ',';
end;
StrPCopy(buffer, name);
WriteProfileString('windows', 'device', buffer);
StrCopy(buffer, 'windows');
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, Longint(@buffer));
end;

Delphi 處理大量資料時不讓 Form 凍結 Application.ProcessMessages

在處理大量資料時,若不想讓 Form 凍結無法移動,可以在迴圈中加入 Application.ProcessMessages 來處理 Windows Message
在 Form 上放一個 TMemo,一個 TButton
在 Button1 click 事件中加入

procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
Memo1.Clear;
Application.ProcessMessages;
for i := 1 to 500 do
begin
Memo1.Lines.Add(IntToStr(i));
Sleep(10);
Application.ProcessMessages;
end;
end;

Delphi TStringList QuickSort 排序

在 Form 上放一個 TMemo
在 implementation 區加入 function

// 字串反排
function DescCompareStrings(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := - AnsiCompareText(List[Index1], List[Index2]);
end;

// 在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
StringList: TStringList;
begin
StringList := TStringList.Create;
try
with StringList do
begin
Add('3');
Add('7');
Add('1');
Add('9');
Add('5');
end;

StringList.Sort; // 正排 會使用 QuickSort 來排序
Memo1.Lines := StringList; // 印到 Memo1

StringList.CustomSort(DescCompareStrings); // 使用反排 function
// CustomSort 會使用 QuickSort 來排序
Memo1.Lines.AddStrings(StringList); // 加到 Memo1
finally
StringList.Free;
end;
end;

{ Memo1

1
3
5
7
9
9
7
5
3
1

}

Delphi Projec Manager

View->Projec Manager 可以叫出專案管理視窗,或按【Ctrl+Alt+F11】
Projec Manager 中會有一個專案群組(Project Group),可以在專案群組中加入多個專案
按 Mouse 右鍵選 Add New Project… 可加入新的專案
按 Mouse 右鍵選 Save Project Group 可儲存專案群組
按 Mouse 右鍵選 View Project Group Source 可自行編輯

#------------------------------------------------------------------------------
VERSION = BWS.01
#------------------------------------------------------------------------------
!ifndef ROOT
ROOT = $(MAKEDIR)\..
!endif
#------------------------------------------------------------------------------
MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$**
DCC = $(ROOT)\bin\dcc32.exe $**
BRCC = $(ROOT)\bin\brcc32.exe $**
#------------------------------------------------------------------------------
PROJECTS = Project1.exe Project2.exe
#------------------------------------------------------------------------------
default: $(PROJECTS)
#------------------------------------------------------------------------------

Project1.exe: Project1.dpr
$(DCC)

Project2.exe: Project2.dpr
$(DCC)

Delphi OLEDB 使用 ErrorCode 做錯誤處理

在 Form 上放一個 TMemo,一個 TADOConnection 及一個 TADODataSet

uses
ComObj, OleDB;

在元件屬性 ADOConnection1.ConnectionString 中指定資料庫,例如 DBDEMOS.udl
在元件屬性 ADODataSet1.Connection 指定為 ADOConnection1
在元件屬性 ADODataSet1.CommandText 寫入一個不存在的 QUERY TABLE,例如
select * from x

在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
try
ADODataSet1.Active := True;
except
on E: EOleException do begin
Memo1.Lines.Add('ErrorCode: ' + IntToHex(E.ErrorCode, 8));
Memo1.Lines.Add(E.Message);
case E.ErrorCode of
DB_E_NOTABLE: begin
// The specified table does not exist
Memo1.Lines.Add('Table 不存在');
end;
DB_E_INTEGRITYVIOLATION: begin
// A specified value violated the integrity constraints
// for a column or table
Memo1.Lines.Add('違反完整性約束,可能為資料重複');
Memo1.Lines.Add('或沒有外鍵所參考的值存在');
end;
DB_E_ERRORSINCOMMAND: begin
// The command contained one or more errors
Memo1.Lines.Add('SQL Command 發生一或多個錯誤');
end;
// 可加入其它的 ErrorCode 來做處理
else ;
end;
end;
end;
end;

{ Memo
ErrorCode: 80040E37
Microsoft Jet 資料庫引擎無法找到輸入資料表或查詢 'x'。請確定它是存在的而且名稱沒有拼錯。
Table 不存在
}

Delphi Midas 常數及資源字串檔

Midas 的 resourcestring 定義在 unit MidConst 之中

{ App Server }
SProviderNotExported = 'Provider not exported: %s';

{ DBClient }
SNoDataProvider = 'Missing data provider or data packet';
SInvalidDataPacket = 'Invalid data packet';
SRefreshError = 'Must apply updates before refreshing data';
...
{ MConnect }
SSocketReadError = 'Error reading from socket';
SInvalidProviderName = 'Provider name "%s" was not recognized by the server';
SBadVariantType = 'Unsupported variant type: %s';
...

Delphi OLEDB ErrorCode

在使用 OLEDB 發生錯誤時,可以用 ErrorCode 來做錯誤處理
ErrorCode 定義在 Unit OleDB 中

// Invalid accessor
//
DB_E_BADACCESSORHANDLE = HResult($80040E00);
...
// Unable to write with a read-only accessor
//
DB_E_READONLYACCESSOR = HResult($80040E02);
...
// Given values violate the database schema
//
DB_E_SCHEMAVIOLATION = HResult($80040E03);
...
// A literal value in the command could not be converted to the
// correct type due to a reason other than data overflow
//
DB_E_CANTCONVERTVALUE = HResult($80040E07);
...
// The command contained one or more errors
//
DB_E_ERRORSINCOMMAND = HResult($80040E14);
...
// A specified value violated the integrity constraints for a column or
// table
//
DB_E_INTEGRITYVIOLATION = HResult($80040E2F);
...

Delphi TXMLDocument

在 Form 上放一個 Internet TXMLDocument
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
with XMLDocument1.XML do
begin
Add('<?xml version="1.0" encoding="Big5"?>');
Add('<html lang="en">');
Add(' <head>');
Add(' <title>Extensible Markup Language (XML)</title>');
Add(' </head>');
Add(' <body>');
Add(' </body>');
Add('</html>');
end;
XMLDocument1.Active := True;
with XMLDocument1.DOMDocument do
begin
ShowMessage('tagName: ' + documentElement.tagName); // html
ShowMessage('Attribute lang: ' + documentElement.getAttribute('lang')); // en
with documentElement.firstChild.firstChild do
begin
ShowMessage('nodeName: ' + nodeName); // title
ShowMessage('nodeValue: ' + firstChild.nodeValue); // Extensible Markup Language (XML)
end;
end;
end;

Delphi 取得系統預設地區和語言

在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
DefaultLCID: Integer;
begin
DefaultLCID := SysLocale.DefaultLCID;
ShowMessage(Languages.NameFromLCID[IntToStr(DefaultLCID)]);
end;

Delphi 列出所有的語言

在 Form 上放一個 TMemo
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
lang: TLanguages;
i: Integer;
begin
lang := Languages;
with Memo1.Lines do
begin
Clear;
Add('Name'#9'Ext'#9'ID'#9'LocaleID');
for i := 0 to lang.Count -1 do
begin
Add(Format('%s'#9'%s'#9'%s'#9'%d', [
lang.Name[i],
lang.Ext[i],
lang.ID[i],
lang.LocaleID[i]
]));
end;
end;
end;

叫用 Delphi ADO 元件設什時期的 ConnectionString 屬性設定


uses
AdoConEd;

在 Form 上放一個 TADOConnection
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
begin
AdoConEd.EditConnectionString(ADOConnection1);
end;

Delphi Bits 位元操作

在 Form 上放一個 TMemo
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
bit: TBits;
begin
with Memo1.Lines do
begin
Clear;
bit := TBits.Create;
try
bit.Size := 0;
bit.Bits[0] := True;
bit.Bits[1] := True;
bit.Bits[2] := False;
Add(IntToStr(bit.Size)); // 3
Add(IntToStr(bit.OpenBit)); // 2 first False
finally
bit.Free;
end;
end;
end;

Delphi 動態陣列

在 Form 上放一個 TMemo
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
a: array of String; // 動態字串陣列
i: Integer;
s: string;
begin
SetLength(a, 3); // a[0..2]
for i := Low(a) to High(a) do
begin
a[i] := IntToStr(i);
end;
s := '';
for i := Low(a) to High(a) do
begin
s := s + ',' + QuotedStr(a[i]);
end;
s[1] := '[';
s := s + ']';

with Memo1.Lines do
begin
Clear;
Add(s);
Add('Length: ' + IntToStr(Length(a)));
SetLength(a, 0); // Clear
Add('Length: ' + IntToStr(Length(a)));
end;
end;

使用 Delphi 的集合

在 Form 上放一個 TMemo
在 FormCreate 事件中加入

procedure TForm1.FormCreate(Sender: TObject);
var
s: set of Byte;
begin
s := []; // 空集合
with Memo1.Lines do
begin
Clear;
if s = [] then
begin
Add('空集合');
end;
Include(s , 3); // add 3
s := s + [1] + [5, 7]; // [1,3,5,7]
if 5 in s then begin
Add('5 in [1,3,5,7]');
end;
Exclude(s, 5); // remove 5
if not (5 in s) then begin
Add('5 not in [1,3,7]');
end;
end;
end;

2009年5月28日

Delphi Debug Log

在 Delphi 中用 Windows API OutputDebugString 來寫 Log
Delphi Menu 的 view -> Debug Windows -> Event Log (Ctrl + Alt + v)將顯示寫出的 Log

// 印出目前的時間到 Event Log 中
OutputDebugString(PChar( 'Now: ' + DateTimeToStr(Now) ));

Delphi Indy 取得設定網段中可用的 IP Address

在元件面板 Indy Misc 中有 TIdIPWatch 元件,放一個 TIdIPWatch 和 TMemo 在 Form 上

procedure TForm1.FormCreate(Sender: TObject);
begin
IdNetworkCalculator1.NetworkAddress.AsString := '192.168.0.48';
IdNetworkCalculator1.NetworkMask.AsString := '255.255.255.240';
Memo1.Lines.Clear;
Memo1.Lines.Values['NetworkClass'] := IdNetworkCalculator1.NetworkClassAsString;
Memo1.Lines.AddStrings(IdNetworkCalculator1.ListIP);
end;

執行後會列出可用的 IP Address

Delphi Indy 網路偵測

元件面板 Indy Misc 中有 TIdIPWatch 元件,放置一個 TMemo 和 TIdIPWatch 在 form 上,並將 IdIPWatch1.Active 屬性設為 True,在 IdIPWatch1.OnStatusChanged 事件中加入

procedure TForm1.IdIPWatch1StatusChanged(Sender: TObject);
begin
Memo1.Lines.Values['IsOnline'] := BooleanIdents[IdIPWatch1.IsOnline];
Memo1.Lines.Values['CurrentIP'] := IdIPWatch1.CurrentIP;
Memo1.Lines.Values['LocalIP'] := IdIPWatch1.LocalIP;
end;

執行程式後,當網路狀態改變時,就會觸發 OnStatusChanged 事件

Delphi Indy Base64 編解碼

元件面板 Indy Misc 中有二個元件寫上64的 TIdEncoderMIME 和 TIdDecoderMIME,可做 Base64 編解碼

// 編碼
IdEncoderMIME1.Encode('hello world!');
// 解碼
IdDecoderMIME1.DecodeString('aGVsbG8gd29ybGQh');

Delphi 用Indy元件取得UTF8編碼網頁資料


放入元件 Indy Clients -> IdHTTP,和一個memo元件
uses
IdURI;

在 FormCreate 事件中寫入

procedure TForm1.FormCreate(Sender: TObject);
var
url: string;
begin
url := 'http://www.wretch.cc/blog/blog.php?id=solnone&search='
+ TIdURI.ParamsEncode(UTF8Encode('Delphi 時間'));
Memo1.Lines.Text := UTF8Decode(IdHTTP1.Get(url));
end;

Delphi 的時間格式

在unit SysUtils 中,initialization 會執行 procedure GetFormatSettings 將作業系統的日期時間格式等,載入SysUtils 中的變數
var ShortDateFormat, LongTimeFormat, DateSeparator, TimeSeparator 等日期時間格式,來做為內定的日期時間格式。

程式中的 function DateTimeToStr, StrToDateTime 等轉換,若無指定,都將以 SysUtils 的內定日期時間格式來做轉換。

可以直接更改 SysUtils 中的 ShortDateFormat, LongTimeFormat, DateSeparator, TimeSeparator 等,就可以改掉內定的日期時間格式。

當作業系統的日期時間格式有更動時,內定的日期時間格式也會update。若不想變動內定日期時間格式,可以將在 unit Forms 中的 Application.UpdateFormatSettings 設定成 false,就不會再同步update 內定日期時間格式。

在 SysUtils 中有一個 record TFormatSettings,可以存入日期時間格式,程式中的 function DateTimeToStr, StrToDateTime 等轉換可以多傳入 TFormatSettings 參數來各自指定。

Delphi 使用 TStrings 的 Values


procedure TForm1.FormCreate(Sender: TObject);
var
s: TStrings;
begin
s := TStringList.Create;
with s do
begin
Clear;
Values['Sunday'] := '星期日';
Values['Monday'] := '星期一';
Values['Tuesday'] := '星期二';
ShowMessage(Text); // Sunday=星期日\r\nMonday=...
ShowMessage('Monday 是 ' + Values['Monday']); // Monday 是 星期一
Values['Sunday'] := ''; // 刪掉 Sunday
ShowMessage(Text); // Monday=星期一\r\n...
end;
s.Free;
end;

Delphi 字串分割


使用TStringList來分割字串,下面的範例是將字串 'a,b,c' 以 ',' 來分割

procedure TForm1.FormCreate(Sender: TObject);
var
s: TStrings;
begin
s := TStringList.Create;
try
s.Delimiter := ',';
s.DelimitedText :='a,b,c';
ShowMessage(s[0]);
ShowMessage(s[1]);
ShowMessage(s[2]);
finally
s.Free;
end;
end;

Delphi 使用資源檔


要使用資源檔,首先要用編輯器建立一個資源檔的腳本,附檔名為".rc"
內容為資源名稱、類別和檔案名稱,範例res.rc如下

READEME TXT "READEME.txt"
logo JPG "logo.jpg"
ok BMP "ok.bmp"

在${Delphi}\bin安裝目錄中有BRCC32.EXE這個程式,是用來將資源檔腳本中的檔案,
建立出一個資源檔,資源檔附檔名為".res"
在命令列中,先換目錄到資源檔腳本所在目錄,執行命令如下

Brcc32 res.rc

會產生res.res 資源檔
開啟 Delphi 在 unit 中加入資源檔 {$R 資源檔所在目錄\res.res}
在Form 中放入一個 Memo,在 FormCreate Event 中加入

procedure TForm1.FormCreate(Sender: TObject);
var
s: TResourceStream;
begin
s := TResourceStream.Create(HInstance, 'READEME','TXT');
try
Memo1.Lines.LoadFromStream(s);
finally
s.Free;
end;
end;

執行程式將會載入資源檔中的READEME.TXT到Memo中

Delphi 以類別名稱來建立物件


若想用父類別來操作,而不想 use 各子類別,則可以類別名稱來動態建立子類別物件

在 unit Classes 中,有RegisterClass, GetClass, FindClass 和 UnRegisterClass

先使用 RegisterClass 註冊所需動態建立的類別
然後才能使用 GetClass 或 FindClass 以類別名稱來找出註冊過的類別
再轉型為所需的父類別來建立並使用物件
若不再需要它,則可以使用 UnRegisterClass 來取消註冊

procedure TForm1.FormCreate(Sender: TObject);
var
PClass: TPersistentClass;
Strings: TStrings;
begin
PClass := FindClass('TStringList');
Strings := PClass.Create as TStrings;
try
Strings.Add('Hi');
finally
Strings.Free;
end;
end;

initialization
RegisterClass(TStringList);

finalization
UnRegisterClass(TStringList);

Delphi Unit 的結構

Delphi Unit 最簡單的結構如下

unit{ 單元開頭 } Unit1;

interface
{ 介面區 }

implementation
{ 實作區 }

end{ 單元結尾 }.

unit 為單元開頭,以 end. 為單元結尾,code寫在這兩行之中。
主要分為二節區,interfaceimplementation
  1. interface 區為對外公開的宣告
  2. implementation 區為不對外開放的實作 code 以及interface 區的實作 code
另外還有二個節區,initializationfinalization
  1. initialization 區為此 unit 初始化時執行的 code
  2. finalization 區為程式結束時執行的 code,主要目的是釋放 initialization 區所建立的資源

unit{ 單元開頭 } Unit1;

interface

{ 介面區 }


implementation

{ 實作區 }

initialization
{ 初始區 }

finalization
{ 結束區 }

end{ 單元結尾 }.


interfaceimplementation 區中,可以有一個 uses 來使用其它 unit 的資源,以 interface 中的 uses 為宣告中所要用到的資源,implementation 中的 uses 則是在實作時所要用到的資源,且未出現在 interface 中的 uses內。

unit Unit1;

interface

uses
Classes;

implementation

uses
Variants;

initialization

finalization

end.


interfaceimplementation 區中,在 uses 之後,可以有多個 const, resourcestring, type, var

unit Unit1;

interface

uses
Classes;

{… const, resourcestring, type, var …}

implementation

uses
SysUtils;

const { 常數 }
PI_SQUARE = PI * PI;

resourcestring { 資源字串 }
RS_ProductName = 'ProductName';

type { 定義 }
TMyClass = TObject;

var { 變數 }
Strings: TStrings;

initialization
Strings := TStringList.Create; { 建立 Strings }

finalization
FreeAndNil(Strings); { 釋放 Strings }

end.


interface區中, 宣告對外公開的 procedurefunction
implementation 區中,實作procedurefunction

unit Unit1;

interface

uses
Classes;

{… const, resourcestring, type, var …}

procedure AddString(s: String);
function GetPI_SQUARE: Double;

implementation

uses
SysUtils;

const { 常數 }
PI_SQUARE = PI * PI;

resourcestring { 資源字串 }
RS_ProductName = 'ProductName';

type { 定義 }
TMyClass = TObject;

var { 變數 }
Strings: TStrings;

procedure AddString(s: String);
begin
Strings.Add(s);
end;

function GetPI_SQUARE: Double;
begin
Result := PI_SQUARE;
end;

initialization
Strings := TStringList.Create; { 建立 Strings }

finalization
FreeAndNil(Strings); { 釋放 Strings }

end.

網誌存檔