Delphi 2010 以降で RTTI を無効にする
Delphi 2010 は デフォルトで RTTI が有効になっており、RTTI が有効のままコンパイルすると、RTTI を用いないコードのみで書かれたソースコードであっても EXE のサイズが肥大化します。
(恐らく)完全に RTTI をオフにする事はできませんが、*.dpr に以下のコードを記述する事により、RTTI を可能な限り利用しなくする事ができます。
program Project1;
{$RTTI EXPLICIT METHODS([]) FIELDS([]) PROPERTIES([])}
{$WEAKLINKRTTI ON}
...
|
プロジェクト内の各ユニットの先頭に記述しても、殆ど効果はないハズです。また、このコードの記述があっても、VCL/RTL の一部に RTTI に依存したコードが含まれるため、特定のユニットを uses すると暗黙的に RTTI が有効になります。
EXE サイズの肥大化は今となっては大した問題ではなく、RTTI 有効によって肥大化した EXE ファイルのサイズは以降どれだけ RTTI を利用しても極端にサイズが増加する事はありません。また、RTTI を利用する事による "速度面でのペナルティ" は無視できる程度のものだと思います (どういう使い方をするかにも依るでしょうが...)。
Delphi 2009 以降で半角/全角を考慮して文字幅を揃える
MECSUtils を利用し、MecsStringWidth() を使うのが最も簡単な方法だと思います。サンプルコードも MECSUtils リファレンス にあります。
但し、文字幅は揃うかもしれませんが、データのサイズはバラバラになります ので注意が必要です。何故そういった事になるのかが理解できない方は、トピック "39.Unicode" をご一読下さい。
DBX で Firebird に接続するには?
以下、簡単なサンプルコードです。
uses
..., DBXFirebird;
procedure TForm1.Button1Click(Sender: TObject);
var
DBXC: TSQLConnection;
QRY: TSQLQuery;
DataBase: String;
begin
DBXC := TSQLConnection.Create(Self);
try
QRY := TSQLQuery.Create(Self);
try
DBXC.LoginPrompt := False;
DBXC.DriverName := 'Firebird';
DBXC.ConnectionName := 'FBConnection';
DBXC.GetDriverFunc := 'getSQLDriverFIREBIRD';
DBXC.LibraryName := 'dbxfb.dll';
DBXC.VendorLib := 'fbclient.dll';
DBXC.Params.Clear;
DBXC.Params.Values['user_name' ] := 'SYSDBA'; // User Name
DBXC.Params.Values['password' ] := 'masterke'; // Password
DBXC.Params.Values['ServerCharSet'] := 'UTF8'; // CharSet
DataBase := '127.0.0.1:' +
IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) +
'DATA\DATA.FDB';
DBXC.Params.Values['DataBase' ] := DataBase; // Database
QRY.SQLConnection := DBXC;
DBXC.Connected := True;
QRY.SQL.Clear;
QRY.SQL.Add('Select * From MST_EMPLOYEE');
QRY.SQL.Add('Where ');
QRY.SQL.Add(' NAME = :_NAME ');
QRY.ParamByName('_NAME').AsString := Edit1.Text;
QRY.Open;
if QRY.IsEmpty then
ShowMessage('Empty')
else
ShowMessage(IntToStr(QRY.FieldByName('CODE').AsInteger));
QRY.Close;
DBXC.Connected := False;
finally
QRY.Free;
end;
finally
DBXC.Free;
end;
end;
|
Professional 版では Firebird ドライバが提供されない 事に注意して下さい。
See Also:
Firebird のデータベースファイルをバックアップ/リストアするには?
Delphi 2010 の DBX では対処できません。バックアップ/リストアには IBX Admin の機能を利用します。但し、IBX は Firebird を公式にサポートしていない事だけは覚えておいて下さい。
バックアップ
//バックアップ
IBBackupService1 := TIBBackupService.Create(nil);
try
IBBackupService1.LoginPrompt := False;
IBBackupService1.Protocol := TCP;
IBBackupService1.ServerName := 'localhost';
IBBackupService1.Params.Values['user_name'] := UserName;
IBBackupService1.Params.Values['password' ] := PW;
IBBackupService1.Attach;
if IBBackupService1.Active then
begin
IBBackupService1.DatabaseName := DatabaseName;
IBBackupService1.BackupFile.Add(BackupFile);
IBBackupService1.ServiceStart;
while IBBackupService1.IsServiceRunning do
Application.ProcessMessages;
end;
finally
if IBBackupService1.Active then
IBBackupService1.Detach;
IBBackupService1.Free;
end;
|
リストア
//リストア
IBRestoreService1 := TIBRestoreService.Create(nil);
try
IBRestoreService1.LoginPrompt := False;
IBRestoreService1.Protocol := TCP;
IBRestoreService1.ServerName := 'Localhost';
IBRestoreService1.Params.Values['user_name'] := UserName;
IBRestoreService1.Params.Values['password' ] := PW;
IBRestoreService1.Attach;
if IBRestoreService1.Active then
begin
IBRestoreService1.Options := IBRestoreService1.Options + [Replace];
IBRestoreService1.DatabaseName.Add(DatabaseName);
IBRestoreService1.BackupFile.Add(BackupFile);
IBRestoreService1.ServiceStart;
while IBRestoreService1.IsServiceRunning do
Application.ProcessMessages;
end;
finally
if IBRestoreService1.Active then
IBRestoreService1.Detach;
IBRestoreService1.Free;
end;
|
バックアップ/リストアの際には、DB へのコネクションが存在しない事を確認して下さい。コネクションがある場合、バックアップ/リストアは失敗してしまいます。
また、バックアップファイルは Firebird サーバ でのパスを指定する必要があります。Firebird サーバとクライアントが別の PC の場合、クライアント PC からクライアント PC のローカルフォルダへバックアップを行う事はできません。
See Also:
InterBase / Firebird のデータベースへ接続されているセッションが存在するかを調べるには?
"Firebird のデータベースファイルをバックアップ/リストアするには?" にあるように、InterBase / Firebird では DB に接続された状態でバックアップ/リストアする事はできません。例え可能であってもそれは避けるべきです。
function SessionExists: Boolean;
var
IBSP: TIBServerProperties;
i: Integer;
begin
IBSP := TIBServerProperties.Create(nil);
try
IBSP.LoginPrompt := False;
IBSP.Protocol := TCP;
IBSP.ServerName := 'Localhost';
IBSP.Params.Values['user_name'] := UserName;
IBSP.Params.Values['password' ] := PW;
IBSP.Options := [Database];
IBSP.Active := True;
IBSP.FetchDatabaseInfo;
result := False;
if IBSP.DatabaseInfo.NoOfAttachments > 0 then
for i:=0 to High(IBSP.DatabaseInfo.DbName) do
if AnsiUpperCase(IBSP.DatabaseInfo.DbName[i]) = AnsiUpperCase(DatabaseName) then
begin
result := True;
Exit;
end;
IBSP.Active := False;
finally
IBSP.Free;
end;
end;
|
上記コードは、データベースへ接続されているセッションが存在するかどうかを返します。
補足しますと、サーバへ接続されているセッション数は DatabaseInfo.NoOfAttachments で調べることができますが、これはあくまでも サーバに接続されているセッション数 であり、データベースへの接続セッション数ではありません。特定のデータベースのセッションが存在するかどうかは DatabaseInfo.DbName を調べる必要があります。
ここに、指定されたデータベースが存在すればセッションが存在するという事になります。
なお、上記コードではデータベース名を AnsiUpperCase で処理していますが、サーバが Linux 等の場合、この処理は不適切です。
See Also:
Indy 10 を使って GMail を送受信するには? (Delphi 2009 以降)
UTF-8、SSL を使って GMail を送受信するサンプルです。
Indy 10 のインストール
インストール方法は "62. Delphi 2009 に最新版の Indy10 をインストールする" を参考にして下さい。
また、POP3/SMTP に SSL を利用する場合には、"Indy用 OpenSSL DLL" が別途必要となります。アーカイブを解凍して得られる DLL をプロジェクトフォルダ以下に配置して下さい。
サンプルコード(送信)
procedure TForm1.IdMessage_InitializeISO(var VHeaderEncoding: Char; var VCharSet: string);
begin
VHeaderEncoding := 'B';
VCharSet := 'UTF-8';
end;
procedure TForm1.Button1Click(Sender: TObject);
var
SMTP: TIdSMTP;
SSL: TIdSSLIOHandlerSocketOpenSSL;
Msg : TIdMessage;
begin
SMTP := TIdSMTP.Create(nil);
try
SMTP.Host := 'smtp.gmail.com';
SMTP.Port := 587;
SMTP.Username := 'hoge@gmail.com'; // UserName
SMTP.Password := 'hogehoge'; // Password
SSL := TIdSSLIOHandlerSocketOpenSSL.Create;
try
SSL.Host := SMTP.Host;
SSL.Port := SMTP.Port;
SSL.Destination := SSL.Host + ':' + IntToStr(SSL.Port);
SMTP.IOHandler := SSL;
SMTP.UseTLS := utUseExplicitTLS;
SMTP.Connect;
Msg := TIdMessage.Create(SMTP);
try
Msg.OnInitializeISO := IdMessage_InitializeISO;
Msg.ContentType := 'text/plain';
Msg.CharSet := 'UTF-8';
Msg.ContentTransferEncoding := 'BASE64'; // BASE64 (7bit)
//Msg.ContentTransferEncoding := '8bit'; // RAW(8bit)
Msg.From.Name := 'hoge@gmail.com';
Msg.From.Address := 'hoge@gmail.com';
Msg.Recipients.EMailAddresses := 'hoge@gmail.com';
Msg.Subject := 'Unicode String (subject)';
Msg.Body.Text := 'Unicode String (body)';
SMTP.Send(Msg);
finally
Msg.Free;
end;
SMTP.Disconnect;
finally
SSL.Free;
end;
finally
SMTP.Free;
end;
end;
|
サンプルコード(受信)
procedure TForm1.Button2Click(Sender: TObject);
var
POP3: TIdPOP3;
SSL: TIdSSLIOHandlerSocketOpenSSL;
Msg : TIdMessage;
MsgCnt: Integer;
i: Integer;
begin
Memo1.Clear;
POP3 := TIdPOP3.Create(nil);
try
POP3.Host := 'pop.gmail.com';
POP3.Port := 995;
POP3.Username := 'hoge@gmail.com'; // UserName
POP3.Password := 'hogehoge'; // Password
SSL := TIdSSLIOHandlerSocketOpenSSL.Create;
try
SSL.Host := POP3.Host;
SSL.Port := POP3.Port;
SSL.Destination := SSL.Host + ':' + IntToStr(SSL.Port);
POP3.IOHandler := SSL;
POP3.UseTLS := utUseImplicitTLS;
POP3.Connect;
Msg := TIdMessage.Create(nil);
try
MsgCnt := POP3.CheckMessages;
for i:=1 to MsgCnt do
begin
POP3.RetrieveHeader(i, Msg);
Msg.NoDecode := (LowerCase(Msg.ContentTransferEncoding) <> 'base64') and
(LowerCase(Msg.ContentTransferEncoding) <> 'quoted-printable');
POP3.Retrieve(i, Msg);
Memo1.Lines.Add('Subject: ' + Msg.Subject);
Memo1.Lines.Add('Body:');
Memo1.Lines.Add(Msg.Body.Text);
end;
finally
Msg.Free;
end;
POP3.Disconnect;
finally
SSL.Free;
end;
finally
POP3.Free;
end;
end;
|
See Also:
Indy 10 を使ってメール(ISO-2022-JP)を送受信するには? (Delphi 2009 以降)
ISO-2022-JP を使って Mail を送受信するサンプルです。
Indy 10 のインストール
インストール方法は "62. Delphi 2009 に最新版の Indy10 をインストールする" を参考にして下さい。特に Delphi 2009 は最新版の Indy をインストールしないと、理不尽なコードを記述するハメになります。
サンプルコード(送信)
procedure TForm1.IdMessage_InitializeISO(var VHeaderEncoding: Char; var VCharSet: string);
begin
VHeaderEncoding := 'B'; // 念のために BASE64 エンコーディング
VCharSet := 'ISO-2022-JP';
end;
procedure TForm1.Button1Click(Sender: TObject);
var
SMTP: TIdSMTP;
Msg : TIdMessage;
begin
SMTP := TIdSMTP.Create(nil);
try
SMTP.Host := 'smtp.hogehoge.com';
SMTP.Port := 25;
SMTP.Connect;
Msg := TIdMessage.Create(SMTP);
try
Msg.OnInitializeISO := IdMessage_InitializeISO;
Msg.ContentType := 'text/plain';
Msg.CharSet := 'ISO-2022-JP';
Msg.ContentTransferEncoding := 'BASE64'; // 念のために BASE64 エンコーディング
Msg.From.Name := 'from@hogehoge.com'; // 送信者のメールアドレス
Msg.From.Address := 'from@hogehoge.com'; // 送信者のメールアドレス
Msg.Recipients.EMailAddresses := 'to@hogehoge.com'; // 送信先のメールアドレス
Msg.Subject := '件名です';
Msg.Body.Text := '本文です';
SMTP.Send(Msg);
finally
Msg.Free;
end;
SMTP.Disconnect;
finally
SMTP.Free;
end;
end;
|
所謂、"波ダッシュ問題" を解決するには一工夫必要になります。
uses
..., MECSUtils;
procedure TForm1.IdMessage_InitializeISO(var VHeaderEncoding: Char; var VCharSet: string);
begin
VHeaderEncoding := 'B'; // 念のために BASE64 エンコーディング
VCharSet := 'ISO-2022-JP';
end;
procedure TForm1.Button1Click(Sender: TObject);
var
SMTP: TIdSMTP;
Msg : TIdMessage;
begin
SMTP := TIdSMTP.Create(nil);
try
SMTP.Host := 'smtp.hogehoge.com';
SMTP.Port := 25;
SMTP.Connect;
Msg := TIdMessage.Create(SMTP);
try
Msg.OnInitializeISO := IdMessage_InitializeISO;
Msg.ContentType := 'text/plain';
Msg.CharSet := 'ISO-2022-JP';
Msg.ContentTransferEncoding := 'BASE64'; // 念のために BASE64 エンコーディング
Msg.From.Name := 'from@hogehoge.com'; // 送信者のメールアドレス
Msg.From.Address := 'from@hogehoge.com'; // 送信者のメールアドレス
Msg.Recipients.EMailAddresses := 'to@hogehoge.com'; // 送信先のメールアドレス
Msg.Subject := MecsMappingFix_UnicodeToJISX0208('件名です');
Msg.Body.Text := MecsMappingFix_UnicodeToJISX0208('本文です');
SMTP.Send(Msg);
finally
Msg.Free;
end;
SMTP.Disconnect;
finally
SMTP.Free;
end;
end;
|
サンプルコード(受信)
procedure TForm1.Button2Click(Sender: TObject);
var
POP3: TIdPOP3;
Msg : TIdMessage;
i, MsgCnt: Integer;
begin
Memo1.Clear;
POP3 := TIdPOP3.Create(nil);
try
POP3.Host := 'pop.hogehoge.com';
POP3.Port := 110;
POP3.Username := 'user_hoge'; // UserName
POP3.Password := 'pass_hoge'; // Password
POP3.Connect;
Msg := TIdMessage.Create(nil);
try
MsgCnt := POP3.CheckMessages;
for i:=1 to MsgCnt do
begin
POP3.RetrieveHeader(i, Msg);
Msg.NoDecode :=
(LowerCase(Msg.ContentTransferEncoding) <> 'base64') and
(LowerCase(Msg.ContentTransferEncoding) <> 'quoted-printable');
POP3.Retrieve(i, Msg);
Memo1.Lines.Add('Subject: ' + Msg.Subject);
Memo1.Lines.Add('Body:');
Memo1.Lines.Add(Msg.Body.Text);
end;
finally
Msg.Free;
end;
POP3.Disconnect;
finally
POP3.Free;
end;
end;
|
Indy 10 では ISO-2022-JP のメールを送信する際に文字コードの変換をする必要はありません。単純に String で受け渡し可能です。また、ISO-2022-JP は 7bit エンコーディングなので、本来 BASE64 で改めて 7bit 化する事に意味はありません(少なくとも仕様上は)。しかし、現実問題として Mail サーバ/クライアントの仕様により文字化けを起こす場合がありますので、なるべく BASE64 化するようにしてください。
See Also: