Delphi私家版FAQ

鮮度は多分こっちのFAQの方が高いです(^^;
# 最近あまりメンテしていません(^^;
# それに書籍リストにある'Delphi Q&A 120選', 'Delphi 3 Q&A 150選'の方がおそらく有用です(^^;


略号について : D1 = Delphi 1, D2 = Delphi 2, D3 = Delphi3/3.1

Q.VBのSendKeysに相当するルーチンはありますか。

Windows APIのSendMessageかPostMessageでWM_KEYDOWN/WM_KEYUP/WM_CHARなどを送って代用する手があります。
また、村松 真さんの作成したSendKeys.LZHがあります。
# D1日本語版のCD-ROMの\extras\examplesにも格納されています。
# ついでですがこのディレクトリにあるhelpme.txtは必読でしょう。
ページ先頭へ

Q.TMemoに32K bytes以上のテキストが格納できません。

A.これはWindowsのMemoコントロールを元にしているための制限です。
ちなみにDelphi 2以降で作成したプログラムの場合、NT上では事実上無制限になりますが、 Win95上では相変わらず同様の制限が付きまといます。 これはDelphiに限らず標準コントロールを使うプログラム一般に関係する問題です。
なお、32KB以上のデータを読み込めるRichEditコントロールでも、 そのままでは編集を行った時点で問題が発生します。 この場合はMaxLengthプロパティを十分に大きな値(100000000とか)に設定することで回避できます。

ページ先頭へ

Q.255文字以上の文字列を扱うにはどうしたらいいのでしょう。

A.C同様にNull charを終端とする文字配列(array [0..?] of char)を使います。 それへのポインタ型はpcharとして定義されています。文字列型との相互変換用として はstrpas, strpcopyがあります。
なお、Delphi 2以降では文字列の制限は大幅に緩和されて、 メモリの空きさえあれば最長2GBまでの文字列が使用できるようになっています。
ページ先頭へ

Q.実行ファイルのサイズが随分大きいようですが。

A. Delphiの採用しているVCL自体が巨大なので、サイズに関してはある程度あきらめざるを得ません。 APIを直接呼び出すだけのプログラムなら10KB程度のものを作ることも可能ですが、そのかわり茨の道が待っています。
Delphi 1の場合は、リンク時のオプションで'サイズと読み込み時間の最適化'を選択すれば数十KBは小さくなります。 なお、あまり知られていませんが同様の処理を行うコマンドラインプログラムw8loss.exeは、 Delphi以外で作ったWin3.1プログラムにも効く事があります。 古いBorland C++をお持ちならbc.exeあたりで試すと面白いかも知れません。(事前にバックアップはしておくこと)
なお、w8lossにはいくつかコマンドラインオプションがあります。 マニュアルでこのプログラムについて一切触れられていないのは不思議です。
Delphi3以降では、実行時にパッケージを使用する設定にすれば、実行ファイルは最小10KBほどになります。 ただし使用するユニットによりますが、実行時には他に1MBほどの共通パッケージファイルが必要になります。
ページ先頭へ

Q.VBのコントロール配列の様なものはありますか。

A.ハンドラを共通化するためなら、プロパティシートで同じハンドラを選ぶだけです。 ハンドラ内でコントロールを区別するにはSenderのNameプロパティやTagプロパティを 使うと便利です。また、FormやPanel上においたコントロールはForm.Components[]や Panel.Components[]で参照できます。
ページ先頭へ

Q.VBのDoEventsのような手続きはありますか。

A.Application.ProcessMessagesを使用します。詳しくはDelphiのヘルプでProcessMessagesの項目を参照してください。
ページ先頭へ

Q.プログラムのアイドル時に実行する手続きを定義したいのですが。

A.Application.OnIdleにTIdleEvent型の手続きを設定します。詳しくはDelphiのヘルプでOnIdleの項目を参照してください。
ページ先頭へ

Q.プログラムを他のマシンで動かすとフォームのレイアウトが崩れてしまいます。

A. 設計時とフォントサイズなどの環境が異なるマシンに持っていくと、 レイアウトが崩れたりフォームにスクロールバーがでたりします。
特にDelphi 1では標準で選択されているフォームのフォントがTrueTypeではないため深刻な問題になります。
これを回避するにはFormのプロパティのScaledかAutoScrollをfalseにするかBorderStyleをbsSizeable 以外に設定することで回避できます。
Delphi2以降では標準のフォントとして選択されているのがTrueTypeフォントなので、 アプリケーションによってはScaled=True, AutoScroll=Falseの方がいいかもしれません。
ページ先頭へ

Q.フォームの最小・最大寸法をコントロールしたいのですが。

A.FormのWM_GETMINMAXINFOメッセージのハンドラを定義し、ハンドラ内で msg.MinMaxInfo^.ptMinTrackSize、ptMaxTrackSizeの値を変更します。
フォームのクラス定義の部分で、
type
  TForm1 = class(TForm)
  (省略)
  private
    procedure WmGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
      message WM_GETMINMAXINFO;
  end;

実装部で、
procedure TForm1.WmGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
begin
  with msg.MinMaxInfo^.ptMinTrackSize do begin (* 最小サイズ制限 *)
    x := 60;
    y := 100;
  end;
  with msg.MinMaxInfo^.ptMaxTrackSize do begin (* 最大サイズ制限 *)
    x := 400;
    y := 200;
  end;
  with msg.MinMaxInfo^.ptMaxSize do begin (* 最大化時サイズ制限 *)
    x := 400;
    y := 200;
  end;
end;
なお、コンポーネント化したものも用意してあります。 ページ先頭へ

Q.フォームをStayOnTopに指定しているのにアイコン化したときは反映されません。

A.アイコン時にはApplicationオブジェクトのウィンドウが表示されていること になっているので、Application.Handleに対してShowWindow APIを使用します。
95やNT4では通常はタスクバーに格納されてしまうのであまり関係ありませんね(^^;
ページ先頭へ

Q.VBXを使ったプログラムを人のマシンに持っていったら動きません。

A.VBXを使ったプログラムを実行する場合、再配布可能モジュールのBIVBX11.DLLが必要になります。一緒に配布/インストールしてください。
ページ先頭へ

Q.メディアの入っていないドライブにアクセスしたときのエラーメッセージを消したいのですが。

A.APIのSetErrorModeを使います。なお用がすんだら必ず元のモードに戻しましょう。 こんな感じです。
function IsDriveReady(drive : char) : boolean;
var
  oldmode : word;
  searchrec : tSearchRec;
begin
  drive := upcase(drive);
  oldmode := SetErrorMode(SEM_FAILCRITICALERRORS);  (* ここと *)
  result := DiskSize(ord(drive)-$40) <> -1;
{$IFDEF WIN32}
  if result and (GetDriveType(pchar(drive+':\')) in [DRIVE_REMOTE, DRIVE_CDROM]) then begin 
{$ELSE}
  if result and (GetDriveType(ord(drive)-$41) = DRIVE_REMOTE) then begin
{$ENDIF}
    result := FindFirst(drive+':\*.*',$3f, searchrec) = 0;
    FindClose(searchrec);
  end;
  SetErrorMode(oldmode);                            (* ここね *)
end;
# 96/03/29: Win32に対応するための変更を加えました。
ページ先頭へ

Q.TMemoのタブ幅を変えたいのですが。

A.本来はTMemoの派生クラスをコンポーネントとして作るべきですが、とりあえず以下 の様にすれば大丈夫です。等幅フォント以外では文字数は目安にしかなりませんが。
procecure MemoTabChange(memo : TMemo; width : integer);
var
  tabwidth : longint;
begin
  tabwidth := width * LoWord(GetDialogBaseUnits) div 2;
  memo.Perform(EM_SETTABSTOPS, 1, longint(@tabwidth));
  memo.Invalidate;
end;
ページ先頭へ

Q.ヒントWindowの書体やサイズを変えたいのですが。

A.以下のコードを参考にしてください。ボーランドのmassangeanaさんのものです。
type TMyHint = class(THintWindow)
  constructor Create(AOwner : TComponent); override;
  end;
constructor TMyHInt.Create(AOwner : TComponent);
begin
  inherited Create(AOwner);
  Canvas.Font.Name := 'MS 明朝'
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  HintWindowClass := TMyHint;
  Application.ShowHint := FALSE;
  Application.ShowHint := TRUE;
end;
# 96/04/02: Delphi 2.0でもそのまま使できることを確認。
ページ先頭へ

Q.海外製のコンポーネントを組み込もうとすると"version mismatch"になります。

A.日本語版でVCL一部コントロールにメンバが追加され、同名の型の宣言が異なってしまうとこうなります。 回避方法としては英語版のライブラリを使うことが考えられます(Delphi2ではCD-ROMに入っています)。 英語版同士でもbugfixついでにメンバを追加したりして、同様の現象がおきているようです。
Delphi3以降ではVCLが基本的に日米共通になったため、この問題はまず起きなくなりました。
ページ先頭へ

Q.いろんなコンポーネントをインストールしたらエラーが出るようになりました。

A.リンクするライブラリのパスが長くなりすぎるとこの問題が起こります。 目安としてはDelphi1で128文字まで、Delphi2で倍程度が上限です。 複数のコンポーネントを一つのディレクトリにまとめるなどして対処しましょう。
ページ先頭へ

Q.Delphi 1.0付属のAcrobat readerがWindows NT上で動かないのですが。

どうしてもこのバージョンのAcrobat readerを使いたければ、 acroread.iniをacroexch.iniにコピーした後、acroexch.iniに以下の行を加えます。
[AdobeViewer]
AtmOption=1
もっとも、 Adobeから最新のAcrobat Readerを持ってくるのが 一番まともな解決方法だと思います。第一、この当時のバージョンでは日本語も表示できません。
ページ先頭へ

Q.DelphiはWin-OS/2上で動きますか。

A.大体正常に動作しますが、OS/2のバージョンによってはプロジェクト実行でGPFが 出た後"プロセスがまだ生きている"とエラーを出してDelphiが終了できなくなります。 英語版Warpのユーザーの間では"Fixpack #5 problem"として知られている問題で、 それ以前のバージョンなら大丈夫という話ですが、日本語版で相当するのがどれか は不明です。なお、GPFが出た時点で「無視」を選択すると結構回避できます。
また、auto saveをoffにし 〔最初に統合デバッガをoffしてBuild→実行、次に統合デバッガをonして実行〕 という手順を踏めば回避できるようです。
他に、シームレスモードはDelphi自身をアイコン化した場合に復活できないとか、 コンポーネントの位置合わせがおかしいなどの問題もあるようです。
また、Acrobat readerがフォントが見つからないといって きますが、Win-OS/2設定のWIN_ATMをONにするといいようです。
基本的にOS/2側の問題ですから、なんとかIBMには対応して欲しいものです。
Delphi2以降についてはもちろん動きません。
ページ先頭へ

Q.付属のエディタが不満なのですが。

A.組込みの3パターン以外のキーカスタマイズを始めから考えていないようなので、 とりあえず慣れるしかないでしょう。VBを思えば充分天国です。 '(O)オプション/(T)ツール'で外部ツールとして他のエディタを指定する事は出来ますが、 フォーム側の変更が自動反映されるわけでもないのでたいして役に立ちません。
なお英語版ですが、MultiEdit for Windowsの次のバージョン(7.1?)はDelphiの環境に もぐり込む機能がつくそうです。(結局出たのかなあ、これ...)
ページ先頭へ

Q.ところでDelphiでWindows以外のプログラムは作れますか。

A. Delphi 1とBorland Pascal 7両方のライブラリソースをもっていればDOSで無理矢(以下略)
CIS DELPHI forum LIB 1にdelphdos.zipというファイルが... ゴニョゴニョ
でも面倒だから、 どうしてもDelphiでの拡張文法使いたい人以外は BP7をそのまま使った方がいいかも。

ページ先頭へ

Q.Windows 95上だとDelphi 1.0のエディタで日本語が入りません。

A.Windows 95が腐っているからです。win.iniの[IME Compatibility]セクションに
DELPHI=0x00010003
という行を追加すると救われるようです。(0x00000002で充分?)
ページ先頭へ

Q.環境変数の参照のしかたがわからないのですが。

A.Delphi1では、delphi\source\rtl70\windos.pasにGetEnvVarという関数が定義されています。 このunitをusesするか、必要な関数の部分だけ切り出して使うのがいいでしょう。
Delphi2以降では、Windows APIの GetEnvironmentVariable を使用すれば環境変数が参照できます。 戻り値をStringとして得たければ以下のような関数を定義すればいいでしょう。
function GetEnv(name : string) : string;
const
  ENVMAX = 1024;
begin
  setlength(result, ENVMAX);
  GetEnvironmentVariable(pchar(name), pchar(result), ENVMAX-1);
  setlength(result, strlen(pchar(result)));
end;

ページ先頭へ

Q.Delphiのプログラムからマシンの時計を設定したいのですが。

A.Delphi1では、delphi\source\rtl70\windos.pasにSetDate,SetTimeという手続きがありますので、それを使うのがいいでしょう。
Delphi2以降ではSetSystemTime APIを使用します。 なお、NTの場合はシステム時間特権を持っているユーザーしか時計を設定できなくなっていますからご注意ください。
ページ先頭へ

Q.samplesのDirectoryOutlineコンポーネントですが、 ルートディレクトリでクリックするとChangeメソッドが実行されません。

A.バグです(^^;。
また、参照しようとするディレクトリ下のサブディレクトリ数の二乗に比例して読み込みとディレクトリの移動に時間がかかるという問題もあり、100ディレクトリ位になると一見ハングアップしたかのように見えます。 Delphi1の場合、unitのソース(delphi\source\samples\diroutln.pas)にこの差分を当てて(context diff形式ですからborlandのではなくunix系のpatchを使ってください)コンポーネントを再インストールすると修正されるはずです。
なお、FileCtrl unitのSelectDirectory関数にも、 初期ディレクトリとしてルートを指定した場合にルートではなくそのドライブの カレントディレクトリを見に行ってしまうという似たようなバグがあります。

ページ先頭へ

Q.Cのsprintfの感覚でformat('%05d',[1])のように書いたのですが、結果が'00001'になりません。

A.Format族の関数/手続きの形式文字列の仕様はprintf系のそれと微妙に異なります。 質問のような結果を得たい場合には、 format('%.5d',[1]) のように指定します。 おそらく先に数値として解釈するようなロジックになっているのでしょう。
その代わりprintfにはできない「n番めの引数を表示」のような指定も可能ですから、 形式文字列だけの入れ替えで表示する語順を入れ替えるような処理 (英語のメッセージから日本語のメッセージに変更する場合など、 しばしば必要があります)も実現可能です。
ページ先頭へ

Q.Delphiの各バージョンで条件コンパイルをしたいのですが。

A.Delphi 2.0以降では'WIN32'というシンボルが定義されているので、これを使って
{$IFDEF WIN32}
  Delphi 2.0での処理;
{$ELSE}
  Delphi 1.0での処理;
{$ENDIF}
のように記述すれば良いでしょう。
また、より細かくバージョンをチェックしたい場合には、 各バージョン毎に定義されている以下のシンボルを参照するとよいでしょう。
Delphi 1.0
VER80
Delphi 2.0
VER90
C Builder 1.0
VER93
Delphi 3.0
VER100
なお、2.0以降でコマンドラインアプリケーションとしてコンパイルされる場合には'CONSOLE'というシンボルも定義されるので、 その場合だけメッセージ表示にWriteLnを使うなどという書き方もできます。
ページ先頭へ

Q.Delphi 1.0のソース印刷をWindows 95上で実行するとDelphiが落ちてしまいます。

A.例によって3.1と95の非互換性が原因のようです。 DELPHI.INIの[Editor]セクションに
NoWidthCheck=1
を追加するととりあえず落ちることだけはなくなるようです。
ページ先頭へ

Q.自分の書いたソースが機械語レベルでどういうコードにコンパイルされているか確認したいのですが。

レジストリを以下のように設定すると、
HKEY_CURRENT_USER\\Software\Borland\Delphi\2.0\Debugging\EnableCPU=1
'表示'メニューに'CPU'という項目が増えます。
レジストリエディタを使うのが面倒なら、以下のコードをコンパイルして使うのも可です。
program EnableCPUView;
{$APPTYPE CONSOLE}
uses registry;
var
  regini : tRegIniFile;
begin
  regini := tRegIniFile.create('HKEY_CURRENT_USER');
  regini.WriteString('\Software\Borland\Delphi\2.0\Debugging','EnableCPU','1');
  regini.free;
end.
この後、ソースの適当な個所にブレークポイントを設定してプログラムを実行し、 止まった所でこの項目を選択すると、 該当位置からの逆アセンブルリストのウィンドウが登場します。
また、ここから機械語レベルでのステップ実行も可能です。 活用しましょう :-)
Delphi 3.0の場合は上記の2.0を3.0に読み替えてください。
ページ先頭へ

Q.アプリケーションの自分が書いた部分以外で発生する例外を処理したいのですが。

A. Application.OnExceptionにTExceptionEvent型の手続きを設定します。 詳しくはDelphiのヘルプでOnExceptionの項目を参照してください。
ページ先頭へ

Q.Delphiで書いたプログラムだけ、NT4のタスクマネージャにアイコンが表示されません。

A. NT4のタスクマネージャは他の同種のプログラムと異なり、アイコンをWindows classのGCL_HICONから取得していますが、 Delphiで作成するアプリケーションではこれを設定していません。 表示させたければ、FormCreateあたりに以下のコードを追加しておけばいいでしょう。
Delphi1の場合:
  SetClassWord(Application.Handle, GCW_HICON, Application.Icon.Handle);
Delphi2以降の場合:
  SetClassLong(Application.Handle, GCL_HICON, Application.Icon.Handle);
毎回書くのも面倒なので、Delphi3ならこのコードを含むフォームをリポジトリに登録してしまうのも手です。
ページ先頭へ

Q.Delphi3のコード補完ウィンドウにでてくる候補をソートしたい。

A. コード補完ウィンドウが表示されている状態で右クリックすると、 表示順序を'スコープ順'と'名前順'に切り替えることができます。この'名前順'がソートされた状態です。
#意外とみんな気付かずに使いにくいと文句をいっているみたい。
ページ先頭へ

Q.Oracleに接続するプログラムをIDEから起動しようとするとAccess Violationで固まるのですが。

A. 原因はOracle側にあります。 Oracle installerでSQL*Netのバージョンを確認してください。 この問題が起こっているのなら、多分バージョン2.3.3.0.0でしょう。 これ以外のバージョン(2.3.2.1.*、2.3.3.0.1、2.3.4.*あたり)を入手して(こういう時のための保守契約です)入れ替えれば問題は解決するはずです。
(マルチスレッドを考慮せずにクラッシュしているDLLがあるようです。解決まで数ヶ月費やした‥‥)
ページ先頭へ


このページに関する連絡は anakata@mix.or.jpSGR03043@niftyserve.or.jp のいずれかへ。
HOME