Iniファイルの読み書きの方法です。実数値を読み込んだ際に、書き込んだ違う値になっているかもしれません。これは、2進数で表すことができない数値を書き込んだからです。
サンプルプログラムのダウンロードは→[Delphi FAQ用サンプル] Ini ファイルの読み書き
2025年5月 2日(金) 21:52 JST
Iniファイルの読み書きの方法です。実数値を読み込んだ際に、書き込んだ違う値になっているかもしれません。これは、2進数で表すことができない数値を書き込んだからです。
サンプルプログラムのダウンロードは→[Delphi FAQ用サンプル] Ini ファイルの読み書き
タスクバーの位置や大きさを知るにはどうしたらよいのでしょうか? タスクバーの大きさを知るためには、SHAppBarMessage APIを使います。 このAPIでタスクバーの大きさがわかるのですが、このAPIで得られる値はなぜかタスクバーが画面をはみ出していることを示しています。
タスクバーの大きさを知りたい理由が、タスクバー以外の部分の画面の大きさを知るということであれば、SystemParametersInfo APIで知ることができるので、こちらを使うとよいでしょう。
サンプルプログラムのダウンロードは→[Delphi FAQ用サンプル] タスクバーの大きさを知る
TMemoの入力行数を制限できる方法。
TMemoを拡張して行数を制限できる新しいMemoコンポーネントを作成します。
新しいTMemoをTMemoExとします。このTMemoExには、1つのプロパティ、3つの変数と3つのメンバー関数を追加します。
interface TMemoEx = class(TMemo) private FMaxLines: Integer; // 内部処理用 mLimitLineProc: Boolean; mOldPos: Integer; mOldText: String; protected procedure Change; override; procedure DoEnter; override; public constructor Create(AOwner: TComponent); override; property MaxLines: Integer read FMaxLines write FMaxLines default 0; end; implementation constructor TProMemo.Create(AOwner: TComponent); begin inherited; mOldPos := 0; mOldText:= ''; FMaxLines := 0; end; procedure TProMemo.DoEnter; begin inherited; mOldPos := SelStart; mOldText := Text; end; procedure TProMemo.Change; begin if (mLimitLineProc) then Exit; // 再入時 // 現在の行数 > 最大行数 if (FMaxLines <> 0) and (SendMessage(Handle, EM_GETLINECOUNT, 0, 0) > FMaxLines) then begin mLimitLineProc := true; // 再入時用 Text := mOldText; SelStart := mOldPos; mLimitLineProc := false; // 再入時用 end; mOldPos := SelStart; mOldText := Text; inherited; end;
通常 Memo1.Lines.Count というように処理すると思います。実際にデータが入っている行数を取得する分にはこれで十分だと思います。
しかし、最終行に改行コードが入っていると、見た目にはもう一行空行が存在することになります。
たとえば、新規にフォームに追加したTMemoは“Memo1[改行コード]”といったTextを持っています。このとき Memo1.Lines.Count では“1”が取得できますが、Windows API のEM_GETLINECOUNT を使えば、表示しているままの“2”が取得できます。
些細なことかもしれませんが、Memoの行数を制限したい場合などには有効に働きます。
そのほか、コントロールの横幅が内容よりも小さくワードラップする場合には、TMemo の Count プロパティは論理行(エディタ的、改行コード+1)を返すようですが、Windows API を用いると物理行(ワープロ的、見た目どおり)を返すようです。
テキストファイルを操作してプログラムの動作記録をとりませんか?ログをとっておくと後からデバッグを行うときにとっても便利。
ログの書き出し用にコンポーネントを作成すると使い回しが利いてさらに便利。
テキストファイルにログを書き込みための手順は以下のようになる。
以下にサンプルでログ出力用のサンプルのソースを掲載するので参考に。
unit FileLogger; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TFileLogger = class(TComponent) private FFile: TextFile; FFilename: String; FSeparator: String; FDateFormat: String; FTimeFormat: String; protected procedure Loaded; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Report(sMsg: String); published property Filename: String read FFileName write FFileName; property Separator: String read FSeparator write FSeparator; property DateFormat: String read FDateFormat write FDateFormat; property TimeFormat: String read FTimeFormat write FTimeFormat; end; procedure Register; implementation procedure Register; begin RegisterComponents('Sample', [TFileLogger]); end; { TFileLogger } constructor TFileLogger.Create(AOwner: TComponent); begin inherited Create(AOwner); // フォーマットの初期化 FDateFormat := 'yyyy/mm/dd'; FTimeFormat := 'hh:nn:ss'; FSeparator := #9; end; destructor TFileLogger.Destroy; begin inherited; CloseFile(FFile); end; procedure TFileLogger.Loaded; var sFileName: String; begin inherited; if (csDesigning in ComponentState) then Exit; // ファイルポインタの初期化 if (FFilename <> '') then sFilename := FFileName else sFilename := FormatDateTime('yyyymmdd', Date) + '.txt'; AssignFile(FFile, sFilename); if FileExists(sFilename) then Reset(FFile) else Rewrite(FFile); Append(FFile); end; procedure TFileLogger.Report(sMsg: String); var s: String; begin s := FDateFormat + FSeparator + FTimeFormat + FSeparator; s := FormatDateTime(s, Now) + sMsg; Writeln(FFile, s); Flush(FFile); end; end.
以上のコードがログ出力サンプルコンポーネントです。