お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"INI ファイルを使った履歴コンボボックス"





 レジストリに履歴を記憶するコンボボックスをどこかで見かけたことが
 あるんですが 自分自身、フリーソフトなどでレジストリを触るアプリを
 あんまりインストールしたく無いものですから INI ファイルへ
 記憶するようにしてみました。

 最初、INI からの履歴のロード/セーブをそれぞれ自動で行うために
 constructor / destructor で TComboBox の items にアクセスしてみたら
 エラーが起きてうまくいきませんでした。TComboBox の TComboBoxStrings の
 各メソッドが親ウインドウのハンドルを使おうとするためだそうです。
 (MES6 で本田さんに教えてもらいました。m(__)m)

 そんなもんですから、それぞれ Loaded と WndProc を override して
 INI からのロード/セーブを自動化しています。
 THisComboBox に履歴を追加する時だけは、自分で AddHistory しないと
 ダメですが。(^^;

unit HCmbBox;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  StdCtrls, IniFiles;


type
    THisComboBox = class(TComboBox)
    private
        FHistoryMax     : Integer;      //ヒストリ数の上限
        FIniFileName    : String;       // ini ファイル名
        FIniSection     : String;       // ini セクション名
        procedure       ReloadFromINI(Value: String);
    protected
        procedure       Loaded; override;
        procedure       WndProc(var Message: TMessage); override;
    public
        constructor     Create(AOwner: TComponent); override;
        procedure       AddHistory;
        procedure       LoadFromINI;
        procedure       SaveToINI;
        property        IniFileName: String     read FIniFileName
                                                write ReloadFromINI;
    published
        property        HistoryMax: Integer     read FHistoryMax
                                                write FHistoryMax;
        property        IniSection: String      read FIniSection
                                                write FIniSection;
    end;

procedure Register;

implementation

function RemoveFirstStr(SubStr: String; var S : String): String;
 (* S から最初の SubStr までを取得/削除する *)
var
    i : integer;
begin
    i := Pos( SubStr, S );
    if i=0 then begin
        Result := S;
        S := '';
        Exit;
    end;
    Result := Copy( S, 1, i-1 );
    Delete( S, 1, i );
end;

procedure THisComboBox.ReloadFromINI(Value: String);
 (* Value の INI ファイルから履歴を読み直す *)
begin
    FIniFileName := Value;
    LoadFromINI;
end;

procedure THisComboBox.LoadFromINI;
 (* INI からコンボボックスの items へロード *)
var
    idx : Integer;
    S : String;
begin
    // FIniFileName の FIniSection から履歴を読み出し
    with TIniFile.Create( FIniFileName ) do begin
        try
            ReadSectionValues( FIniSection, Self.Items );
        finally
            Free;
        end;
    end;

    // FHistoryMax 以上のアイテムは削除
    for idx := Items.Count-1 downto FHistoryMax do
        Items.Delete( idx );
    //履歴から 'ident_name=' を削除する
    for idx := 0 to Items.Count-1 do begin
        S := Items[idx];
        RemoveFirstStr( '=', S );
        Items[idx] := S;
    end;
end;

procedure THisComboBox.SaveToINI;
 (* コンボボックスの items を INI へセーブ *)
var
    idx : Integer;
begin
    with TIniFile.Create( FIniFileName ) do begin
        try
            // FIniSection をまるごと削除
            try
                EraseSection( FIniSection );
            except
                //
            end;
            //履歴を書き出す
            for idx := 0 to Items.Count-1 do
                WriteString(
                    FIniSection,
                    format( '%s%d', [FIniSection, idx] ), 
                    Items[idx]
                );
        finally
            Free;
        end;
    end;
end;

procedure THisComboBox.Loaded;
begin
    inherited Loaded;
    if not ( csDesigning in ComponentState ) then begin
        LoadFromINI;
    end;
end;

procedure THisComboBox.WndProc(var Message: TMessage);
begin
    if Message.MSG=WM_DESTROY then begin
        if not ( csDesigning in ComponentState ) then
            SaveToINI;
    end;
    inherited WndProc( Message );
end;

constructor THisComboBox.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);

    FHistoryMax := 10;
    FIniSection := ClassName;
    FIniFileName := ChangeFileExt( ParamStr( 0 ), '.INI' );
end;

procedure THisComboBox.AddHistory;
 (* THisComboBox.Text を items に履歴として追加 *)
var
    idx : Integer;
begin
    if Text='' then Exit;

    idx := Items.IndexOf( Text );
    Items.Insert( 0, Text );
    if idx<>-1 then
        Items.Delete( idx+1 );
    ItemIndex := 0;

    for idx := Items.Count-1 downto FHistoryMax do
        Items.Delete( idx );
end;

procedure Register;
begin
    RegisterComponents('Samples', [THisComboBox]);
end;

end.


(PXC07042) - とらじ -       URL
http://member.nifty.ne.jp/trazi

Original document by 寅次            氏 ID:(PXC07042)


ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum