AFsoft WebSite(エーエフソフト・ウェブサイト)
 

オペレーティング・システムについて

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
19:メモ帳ソフトを作ってみよう(5)
 
◆設定の読み込み・書き込み
メモ帳ソフト作成の最後に、このソフトの位置・縦横の大きさ・開く又は保存を行ったファイル名、を終了時に覚えるようにして、起動時に前回の設定内容を読み出すようにしてみましょう。
 
よくあるパターンとして3つの手法があります。
 1.専用データファイルの読み書き
 2.INIファイルの読み書き
  (拡張子が".ini"のファイル;プロファイルファイル)
 3.レジストリの読み書き
 
終了時の作業は、メインフォーム Form1 の OnClose イベントハンドラ内で行います。この中で、設定内容の書込処理を行うようにします。起動時の作業は、メインフォーム Form1 の OnCreate イベントハンドラ内、又は、OnShow イベントハンドラ内で行います。フォーム Form1 の位置・縦横の大きさは、
 ・Form1.Left(画面左上点のスクリーン画面上での横の位置)
 ・Form1.Top(画面左上点のスクリーン画面上での縦の位置)
 ・Form1.Width(画面横幅)
 ・Form1.Height(画面縦高さ)
で設定・取得できます。
スクリーン画面
(0,0)→(+)

(+)

Form1.Left

↓Form1.Top
←− Form1.Width −→


Form1.Height





 
設定の書き込みは、この4つのプロパティ内容を保存し、設定の読み込みは、この4つのプロパティへ内容を設定する事で可能となります。フォームのプロパティを設定する場合には、OnCreateイベント時にはまだフォームやコンポーネントの準備は出来ていませんので、OnShow イベントハンドラで行うようにします。
 
まずは、作業をしやすいように、フォーム Form1 の OnClose イベントハンドラと、OnShow イベントハンドラをプログラムの上の方へ移動させます。
 
コードエディタ画面で
procedure TForm1.FormClose(〜
・・・
end;
の範囲を選択します。

[CTRL]+[X]キーで切り取り(カット)します。

・・・
var
 Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
の直後に[CTRL]+[V]で貼り付け(ペースト)します。

コードエディタ画面で
procedure TForm1.FormShow(〜
・・・
end;
の範囲を選択します。

[CTRL]+[X]キーで切り取り(カット)します。

・・・
var
 Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
の直後に[CTRL]+[V]で貼り付け(ペースト)します。

TForm1 クラス定義部分も同様にカット&ペーストを行います。
 
コードエディタ画面で
procedure FormClose(〜
の行を選択し、[CTRL]+[X]キーで切り取り(カット)します。

・・・
type
 TForm1 = class(TForm)
  Memo1: TMemo;
  ・・・
  FindDialog1: TFindDialog;
の直後に[CTRL]+[V]で貼り付け(ペースト)します。

コードエディタ画面で
procedure FormShow(〜
の行を選択し、[CTRL]+[X]キーで切り取り(カット)します。

・・・
type
 TForm1 = class(TForm)
  Memo1: TMemo;
  ・・・
  FindDialog1: TFindDialog;
の直後に[CTRL]+[V]で貼り付け(ペースト)します。
 
専用データファイルやINIファイルを作成する場合は、アプリケーションプログラム(今回の場合は「MemoCyo.exe」)のある同じフォルダ内に作成するのが良いでしょう。そのためには起動したアプリケーションプログラムのフルパス・ファイル名を取得する必要がありますが、それは「ParamStr(0)」又は「Application.ExeName」で取得する事が出来ます。どちらでも構いません。
そのうち、パス名だけを切り取る関数 ExtractFilePath を利用して変数 AppPath に入れます。この変数は色々な所で利用する可能性がありますので、TForm1 クラス定義の Private宣言部分内で指定しておく事にします。また、専用データファイルやINIファイルの変数名も、FormShow イベントハンドラ内、FormClose イベントハンドラ内の双方で利用しますので、同じく、TForm1 クラス定義の Private宣言部分内で指定しておきます。
type
 TForm1 = class(TForm)
  Memo1: TMemo;
  StatusBar1: TStatusBar;
  ・・・
 private
  { Private 宣言 }
  fname : string ;
  AppPath, iname : string ;
 public
  { Public 宣言 }
 end;
 
(1)専用データファイルの読み書き
コードエディタ画面で FormShow イベントハンドラを下記のように変更します。
// 起動時
procedure TForm1.FormShow(Sender: TObject);
var
 F : TextFile ;
 a : integer ;
begin
 fname := '' ;
 AppPath := ExtractFilePath(ParamStr(0)) ; // ソフトのあるフォルダ
 iname := AppPath + 'MemoCyo.dat' ;
 // 設定ファイルを読み込む
 if (FileExists(iname)) then begin
  AssignFile(F, iname); // ファイル名割当て
  try
   FileMode := 0; // 読込み専用モード
   Reset(F);   // 読込みモードでファイルオープン
   ReadLn(F, a); Form1.Left := a ;
   ReadLn(F, a); Form1.Top := a ;
   ReadLn(F, a); Form1.Width := a ;
   ReadLn(F, a); Form1.Height:= a ;
   ReadLn(F, fname);
  except
   ;
  end;
  CloseFile(F); // ファイルクローズ
 end;
 
 Form1.Caption := 'めも帳';
end;
テキストファイルの読み込みは、
1)AssignFile で ファイル変数(F)にファイル名を割り当て
2)FileMode := 0 の指定
3)Reset でファイルを開く
4)Read、ReadLn 等でファイル内のデータを読み込み
5)CloseFile で最後にファイルを閉じる
という順序で行います。2)を省くと読み取り専用ファイルが読めなくなる等の不具合が生じますので注意して下さい。変数 a を利用して一旦入れていますが、仮にファイルの内容が不正状態の場合には、変数 a の内容に異常値が入っている場合には各プロパティに値を入れないようにする、というような処理を後で行い易くするためです。ReadLn は、改行コード分も読み込む為であり、書き込みの際の WriteLn に対応させています。読み込みに失敗した場合のため例外処理を行っています。
 
コードエディタ画面で FormClose イベントハンドラを下記のように変更します。
// 終了時
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
 F : TextFile ;
begin
 FindDialog1.CloseDialog ; // 検索ダイアログを閉じる
 
 // 設定ファイルを書き込む
 AssignFile(F, iname); // ファイル名割当て
 try
  ReWrite(F); // 書込みモードでファイルオープン
  WriteLn(F, Form1.Left);
  WriteLn(F, Form1.Top );
  WriteLn(F, Form1.Width );
  WriteLn(F, Form1.Height);
  WriteLn(F, fname);
  CloseFile(F); // ファイルクローズ
 except
  CloseFile(F); // ファイルクローズ
  // 例外発生時、ファイルが中途半端になっている可能性があるので
  // ファイルを削除する
  if (FileExists(iname)) then
   DeleteFile(iname);
 end;
end;
テキストファイルの書き込みは、
1)AssignFile で ファイル変数(F)にファイル名を割り当て
2)ReWrite でファイルを開く
3)Write、WriteLn 等でファイルへデータを書き込み
4)CloseFile で最後にファイルを閉じる
という順序で行います。WriteLn は、変数値の書き込みの後に改行コードを追加して書き込みます。
この場合のデータファイル「MemoCyo.dat」の内容は
153
216
585
359
C:\Documents and Settings\〜\My Documents\abcde.txt
のようになります。
 
なお、
   ReadLn(F, a); Form1.Left := a ;
   ReadLn(F, a); Form1.Top := a ;
   ReadLn(F, a); Form1.Width := a ;
   ReadLn(F, a); Form1.Height:= a ;
の部分の「Form1.」と書くのが面倒であれば、
   with Form1 do begin
    ReadLn(F, a); Left := a ;
    ReadLn(F, a); Top := a ;
    ReadLn(F, a); Width := a ;
    ReadLn(F, a); Height:= a ;
   end;
のように「with」を利用してオブジェクト名でまとめて書く事も出来ます。但しその内部で他のオブジェクトを扱っている場合には、その他のオブジェクトと混乱しないよう注意が必要です。
 
(2)INIファイルの読み書き
TIniFileで INIファイルを扱う場合には、最初の uses節で「IniFiles」ユニットを指定しておく必要があります。コードエディタ画面で下記のように追加します。
unit Unit1;
 
interface
 
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ComCtrls, Menus, Printers, IniFiles, Unit2 ;
・・・
 
コードエディタ画面で FormShow イベントハンドラを下記のように変更します。
// 起動時
procedure TForm1.FormShow(Sender: TObject);
var
 ini : TIniFile ;
begin
 fname := '' ;
 AppPath := ExtractFilePath(ParamStr(0)) ; // ソフトのあるフォルダ
 iname := AppPath + 'MemoCyo.ini' ;
 // 設定INIファイルを読み込む
 ini := TIniFile.Create(iname);
 try
  Form1.Left := ini.ReadInteger('Form', 'X', 100) ;
  Form1.Top := ini.ReadInteger('Form', 'Y', 100) ;
  Form1.Width := ini.ReadInteger('Form', 'W', 300) ;
  Form1.Height:= ini.ReadInteger('Form', 'H', 300) ;
  fname := ini.ReadString('Sets', 'FNAME', '') ;
 except
  ;
 end;
 ini.Free;
 
 Form1.Caption := 'めも帳';
end;
TIniFileクラスのオブジェクト ini を用意します。ini は変数ではなくオブジェクトですので、宣言をしただけでは使えません。最初に Create メソッドを行ってオブジェクトを作成する必要があります。整数値は ReadInteger メソッドを利用して読み込みます。文字列値は ReadString メソッドを利用して読み込ます。オブジェクトが不要になったら、Free メソッドで解放します。
 
コードエディタ画面で FormClose イベントハンドラを下記のように変更します。
// 終了時
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
 ini : TIniFile ;
begin
 FindDialog1.CloseDialog ; // 検索ダイアログを閉じる
 
 // 設定INIファイルを書き込む
 ini := TIniFile.Create(iname);
 try
  ini.WriteInteger('Form', 'X', Form1.Left);
  ini.WriteInteger('Form', 'Y', Form1.Top );
  ini.WriteInteger('Form', 'W', Form1.Width );
  ini.WriteInteger('Form', 'H', Form1.Height);
  ini.WriteString('Sets', 'FNAME', fname);
 except
  ;
 end;
 ini.Free;
end;
こちらも同様に、TIniFileクラスのオブジェクト ini を用意します。最初に Create メソッドを行ってオブジェクトを作成します。整数値は WriteInteger メソッドを利用して書き込みます。文字列値は WriteString メソッドを利用して書き込ます。オブジェクトが不要になったら、Free メソッドで解放します。
この場合のINIファイル「MemoCyo.ini」の内容は
[Form]
X=391
Y=220
W=364
H=326
[Sets]
FNAME=C:\Documents and Settings\〜\My Documents\test.txt
のようになります。
 
INIファイルは、ファイルの開け閉めを行うので、かなり多数の設定を読み書きする場合(特に書き込み時)には遅くなるため、余り推奨される方法ではありませんが、書き込み時は上記のようなファイル内容になるようにテキストファイルの書き込み手法を利用するパターンもあります。
 
(3)レジストリの読み書き
レジストリを扱う場合には、TRegistry、TRegistryIniFile、TRegIniFile、のうちのいずれかを利用しますが通常は TRegistry を利用すると思われるので、ここでは、TRegistry について記述します。
TRegistry でレジストリを扱う場合には、最初の uses節で「Registry」ユニットを指定しておく必要があります。コードエディタ画面で下記のように追加します。
unit Unit1;
 
interface
 
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ComCtrls, Menus, Printers, Registry, Unit2 ;
・・・
 
変数 iname は必要ありませんので、TForm1クラス定義での Private 宣言部分で指定しないで下さい。AppPath の指定も必要ありませんが、後で利用するかもしれませんのでそのままにしておきます。
コードエディタ画面で FormShow イベントハンドラを下記のように変更します。
// 起動時
procedure TForm1.FormShow(Sender: TObject);
var
 reg : TRegistry ;
begin
 fname := '' ;
 AppPath := ExtractFilePath(ParamStr(0)) ; // ソフトのあるフォルダ
 // 設定レジストリ情報を読み込む
 reg := TRegistry.Create;
 try
  reg.RootKey := HKEY_CURRENT_USER; // デフォルト状態
  if reg.OpenKey('\Software\AFsoft\MemoCyo\Form', False) then begin
   Form1.Left := reg.ReadInteger('X') ;
   Form1.Top := reg.ReadInteger('Y') ;
   Form1.Width := reg.ReadInteger('W') ;
   Form1.Height:= reg.ReadInteger('H') ;
   reg.CloseKey;
  end;
  if reg.OpenKey('\Software\AFsoft\MemoCyo\Sets', False) then begin
   fname := reg.ReadString('FNAME') ;
   reg.CloseKey;
  end;
 except
  ;
 end;
 reg.Free ;
 
 Form1.Caption := 'めも帳';
end;
TRegistryクラスのオブジェクト reg を用意します。reg は変数ではなくオブジェクトですので、宣言をしただけでは使えません。最初に Create メソッドを行ってオブジェクトを作成する必要があります。次に、RootKey プロパティを指定します。標準(デフォルト)状態で HKEY_CURRENT_USER となりますから指定する必要はありませんが一応指定しています。次に、OpenKey メソッドを利用してレジストリのキーを開きます。第1引数は通常「\Software\会社名\製品名\キーの名前」となります。第2引数を True にするとそのキーが無い場合、キーを作成します。読み込み時には通常、キー作成は行いませんので False にします。指定したキーがあれば OpenKey メソッドは True を返します。
整数値は ReadInteger メソッドを利用して読み込みます。文字列値は ReadString メソッドを利用して読み込ます。そのキーが不要になったら CloseKey メソッドでキーを閉じます。最後に、オブジェクトが不要になったら、Free メソッドで解放します。
 
コードエディタ画面で FormClose イベントハンドラを下記のように変更します。
// 終了時
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
 reg : TRegistry ;
begin
 FindDialog1.CloseDialog ; // 検索ダイアログを閉じる
 
 // 設定レジストリ情報を書き込む
 reg := TRegistry.Create;
 try
  reg.RootKey := HKEY_CURRENT_USER; // デフォルト状態
  if reg.OpenKey('\Software\AFsoft\MemoCyo\Form', True) then begin
   reg.WriteInteger('X', Form1.Left);
   reg.WriteInteger('Y', Form1.Top );
   reg.WriteInteger('W', Form1.Width );
   reg.WriteInteger('H', Form1.Height);
   reg.CloseKey;
  end;
  if reg.OpenKey('\Software\AFsoft\MemoCyo\Sets', True) then begin
   reg.WriteString('FNAME', fname);
   reg.CloseKey;
  end;
 except
  ;
 end;
 reg.Free ;
end;
こちらも同様に、TRegistryクラスのオブジェクト reg を用意します。最初に Create メソッドを行ってオブジェクトを作成します。次に、RootKey プロパティを指定します。標準(デフォルト)状態で HKEY_CURRENT_USER となりますから指定する必要はありませんが一応指定しています。次に、OpenKey メソッドを利用してレジストリのキーを開きます。第1引数は通常「\Software\会社名\製品名\キーの名前」となります。第2引数を True にするとそのキーが無い場合、キーを作成します。整数値は WriteInteger メソッドを利用して書き込みます。文字列値は WriteString メソッドを利用して書き込ます。そのキーが不要になったら CloseKey メソッドでキーを閉じます。最後に、オブジェクトが不要になったら、Free メソッドで解放します。
 
 
メニュー「ファイル」→「すべて保存」をクリックしてプログラムの保存を行い、メニュー「プロジェクト」→「MemoCyo を再構築」をクリックしてプログラムのコンパイル(再構築)を行い、正常終了したら、メニュー「実行」→「実行」をクリックして下さい。動作確認を行って下さい。
 
 
 
INIファイルは、Windows3.1時代によく利用されていた手法です。Windows95時代以降は、レジストリを利用しましょう、という事になっていますが、レジストリが多くなってくると Windowsが重くなるという事もありましたし、レジストリを編集するには、レジストリエディタを利用しますが、全く関係のない所を操作してしまうと下手をすれば Windowsが起動しなくなる危険性もあります。また、他のPCへ環境を移したい場合には、レジストリエディタのエクスポート/インポートを利用する事になりますが、テキストファイル/INIファイルを利用する方が気軽であるという場合も多いです。
どの手法を利用するのかは自由ですが、便宜や状況に応じて使い分けてより良く運用を行って下さい。
 
バッチファイル
BASIC
C言語のお勉強
拡張子な話
DOSプログラム
Delphi
>Delphi入門編
 01 02 03 04
 05 06 07 08
 09 10 11 12
 13 14 15 16
 17 18 19 20
シェアウェア
Script!World
データベース
 
お問い合わせ 
本サイトはリンクフリーです
リンクバナー
(C)Copyright 1999-2015. By AFsoft All Rights Reserved.