Visual Basic 6.0 中級講座 |
8.ini
今回はiniの話です。iniはアプリケーションの設定やちょっとした情報を保存するのに便利なものです。通常は一度アプリケーションを終了させると記憶させておいたデータはファイルに保存しない限り消えてしまうのですが、iniに保存しておけば大丈夫です(iniもファイルですけど・・・)。iniは「イニ」と読む人が 多いようです。本当は「Initialize」(イニシャライズ:初期化)の略なので「初期化ファイル」と呼ぶ人もいます。
概要 ・iniファイルを使えば、設定を保存しておくことができる。 ・iniファイルを読み書きするにはAPIを使う。 |
1.はじめに
具体的な説明に入る前に知っておいた方がいいことがあります。Microsoft社(マイクロソフト社)はアプリケーションがその設定や情報を保存するなどの目的でINIを使用することを推奨していません。Microsoft社によるとそのような目的には「レジストリ」を使うようにとのことです。この意図からVBにはレジストリを操作するメソッドはあってもiniを操作するメソッドは無いのです。
念のために説明しておくと、レジストリ とはWindowsやその他のアプリケーションの情報を一括管理している巨大なデータベースのことです。このデータベースの中を見るには、「スタート」ボタンから「ファイル名を指定して実行」で「Regedit」と入力してください。ただし、レジストリの中をよくわからない人がいじるとWindowsが起動しなくなったりしますので要注意です 。
マイクロソフトがレジストリを推奨しているとは言え、iniはレジストリよりも手軽に使えて便利なので現在でも多くのアプリケーションがiniを使用しています。なんといってもiniは単なるテキストファイルの一形式ですので「持ち運びに便利」、「編集しやすい」、「わかりやすい」などの 利点が挙げられます。
2.iniの仕様
iniのプログラムを始める前にiniとはどういうものなのかもう少し詳しくに見ていきましょう。
iniの実体はテキストファイルです。だからINIを作るにはテキストファイルを作れば良いわけです。さらにiniには決まった構造があります。次の例を見てください。
[Data]
USERNAME = VBSchool [Window] TOP = 0 |
■iniの構造
この中で [ ]で囲まれているのは「セクション」と呼ばれるものです。 = で結ばれているものの左側は「キー」、右側は「(キーの)値」と呼ばれます。それから、この例には登場しませんが行頭に ; をつけるとその行全体コメントとなります。
「キー」や「値」などの呼び方はいろいろ違う場合もあるようですが構造はこれだけなので難しくありません。
具体例を挙げると上の例ではDataとWindowの2つのセクションがあるわけです。セクションは自分で勝手に作って構いません。DataセクションにはUSERNAMEとLANGUAGEの2つのキーがあり、USERNAMEキーの値はVBSchoolです。キーも自分で作って構いません。構造さ えちゃんとなっていれば後は自由ということです。
あとはプログラムからこのiniにアクセスして値を読んだり書いたりできれば良いわけです。 必要があればもちろんメモ帳で開くなどして人間が直接値を編集することもできます。
3.値を読む
では、いよいよiniファイルをプログラムから読み込む例を作ってみましょう。まずは上の例と同じiniIを作ってください。作り方は上の例をテキストファイルにコピーするだけです。テキストファイルの名前は vbschool.ini としておきましょう。
プログラムにコマンドボタンを一つ貼り付けて次のように記述してください。
'A
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long |
Private Sub Command1_Click()
MsgBox "@" & GetINIValue("USERNAME", "Data", App.Path & "\vbschool.ini") & "@" 'B End Sub |
Public Function GetINIValue(KEY As String, Section As String, ININame As String) As String
Dim Value As String * 255
End Function |
■リスト1:iniファイルの読み込み
できたら、プログラムを保存してください。そして、プログラムと同じ場所(フォルダ)に vbschool.ini をおいてください。
よければプログラムを開始させてコマンドボタンを押してみましょう。DataセクションのUSERNAMEキーの値を見事に取得したことでしょう。
それでは解説しましょう。Bの部分はiniファイルのどこを読むか指定している部分です。iniファイルの中から読み込む場所を指定するには先ほど説明したセクション名とキー名を使用します。この例ではDataセクションのUSERNAMEキーを指定しています。
たとえばこの部分をGetINIValue("LANGUAGE", "Data", App.Path & "\vbschool.ini") のようにすれば、今度は DataセクションのLANGUAGEキーの値を読むことができるわけです。すばらしく簡単ですね。
iniファイルの読み込みにはAの部分で定義しているGetPrivateProfileString関数を使用しますが、扱いやすくするために自作のGetINIValue関数を用意しています。この関数では引数は順番にキーの名前、セクション名、INIファイルのフルパス を指定するとキーの値を返すようにプログラムされています。
この関数は引数をほとんどそのままAPI関数であるGetProvateProfileString関数に渡しているだけでがいくつかの処理を追加してあります。まず、GetPrivateProfileString関数を呼び出すときに第4引数 として値を受け取る変数を指定しています。この変数はあらかじめ領域を確保しておく必要があるので今回は固定長で宣言しています。
上記の例ではとりあえず255文字分の領域を確保していますが、この「255」には特に根拠はありません。このくらい確保すれば大丈夫かなといった程度のものです。また、可変長で宣言してスペースかなにかをセットして領域を確保しておくという手法もあります。
第3引数はエラー時に第4引数に格納される文字列です。ここでいうエラー時とは指定されたセクションやキーが存在しない場合などを指します。
関数の呼出し後キーの値は第4引数にセットされるわけですが、例によって255文字に満たなかった部分はNULLで満たされるのでNULLを除去する必要があります。それがDの部分です。今回はInStr関数で最初のNULLを探し出して、そこから左にある部分を切り抜くようにしてみました。
VB6であれば、Dの部分は GetINIValue = Replace(Value, vbNullChar, "") と書いてもOKです。
4.値を書く
値を読むだけだけでもiniの使い道はありますが、やはり値を書き込むことができれば使い道はぐんと広がります。
今度は値を書くプログラムです。2つ目のコマンドボタンを配置して次のようにプログラムを書き足してください。色がついている部分が書き足す部分です。
Private Declare Function GetPrivateProfileString
Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName
As String, ByVal lpKeyName
As Any, ByVal lpDefault
As String, ByVal lpReturnedString
As String, ByVal nSize
As Long, ByVal lpFileName
As String) As Long 'E Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long |
Private Sub Command1_Click() MsgBox "@" & GetINIValue("USERNAME", "Data", App.Path & "\vbschool.ini") & "@" End Sub |
Private Sub Command2_Click() MsgBox SetINIValue("HELLO", "USERNAME", "Data", App.Path & "\vbschool.ini") 'F End Sub |
Public Function GetINIValue(KEY
As String, Section As String, ININame
As String) As String Dim Value As String * 255 Call GetPrivateProfileString(Section, KEY, "ERROR", Value, Len(Value), ININame) GetINIValue = Left$(Value, InStr(1, Value, vbNullChar) - 1) End Function |
Public Function SetINIValue(Value
As String, KEY As String, Section
As String, ININame As String)
As Boolean Dim Ret As Long Ret = WritePrivateProfileString(Section, KEY, Value, ININame) 'G SetINIValue = CBool(Ret) 'H End Function |
■リスト2:iniファイルへの書き込みとiniファイルの読み込み
今度も構造はさっきと一緒ですね。実行して2つ目のコマンドボタンをクリックするとTrueと表示されるはずです。 Falseと表示される場合はなにかエラーが発生した場合です。成功した場合はvbschool.iniのDataセクションのUSERNAMEがHELLOに変わっているので確認してみてください。
この例はWritePrivateProfileStringという関数を使っているだけ なので見ただけでわかると思いますがHの部分は少しだけ見慣れない形かもしれませんので説明しておきましょう。この部分はAPI関数の処理が成功したか失敗したかをTrueまたはFalseで返しています。WritePrivateProfileString関数もGetPrivateProfileString関数も失敗時には 0 、成功時には 0以外の値を返します。VBのCBool関数は0をFalse, 0以外をTrueに変換するのでこの2つの関数からの戻り値をCBool関数を通して成功、失敗を表すTrue,False を返せるわけです。
発展学習 発展学習では意欲的な方のために現段階では特に理解する必要はない項目を解説します。 以上の例ではiniファイルを読み書きすることはできるのですが、iniファイルを読み書きするための関数(GetIniValue,
SetIniValue)の引数が多いし長くなってスマートではありません。
|
5.キーを作る
読み書きだけできればとりあえずの用はたりるのですが、キーの作り方も解説しておきます。といってもこれもかんたんで書き込む例と一緒です。
書き込む時の例では G 部分で書き込み処理を行っていましたね?
もういちど、Gの部分だけ下に書きます。
Ret = WritePrivateProfileString(Section, KEY, Value, ININame) 'G
このWritePrivateProfileString関数のカッコの中は左から順に、セクション名、キー名、書き込む値、iniのファイル名となっています。このときにもし、存在しないセクションやキーに値を書き込もうとしたらどうなるでしょうか?
エラーになりそうな気もしますが、実は存在しないセクションやキーを指定すると、そのセクションやキーは自動的に作成されるのです。ですから、新しいセクションやキーを作るのも簡単というわけですね。
ただ、存在しないiniファイルを指定した場合は、そのファイルは作成されないので注意してください。
6.応用事例:位置復元プログラム
それでは、iniの知識を応用してあなたのプログラムに簡単な機能を追加してみましょう。プログラムを開始すると前回終了した位置と同じ位置にWindow(ウィンドウ)を表示する機能を作ります。
まずは、いままでの説明に出てきた2つの関数、GetINIValueとSetINIValueをプログラムにコピーして貼り付けてください。この作業で次のような状態になっているはずです。コメントは私が新たに追加したものです 。
Option Explicit Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long |
'■GetINIValue '■機能:INIから値を取得する。 Public Function GetINIValue(KEY As String, Section As String, ININame As String) As String Dim Value As String * 255 Call GetPrivateProfileString(Section, KEY, "ERROR", Value, Len(Value), ININame) GetINIValue = Left$(Value, InStr(1, Value, vbNullChar) - 1) End Function |
'■SetINIValue '■機能:INIに値を設定する。 '■備考:指定されたセクションやキーが存在しない場合は新たに作成される。 Public Function SetINIValue(Value As String, KEY As String, Section As String, ININame As String) As Boolean Dim Ret As Long Ret = WritePrivateProfileString(Section, KEY, Value, ININame) SetINIValue = CBool(Ret) End Function |
■リスト3:iniファイルへの読み書き用の関数を用意した状態
次に記録するiniの名前を設定します。ここでは ReWindow.ini という名前にします。この部分はフォームの宣言セクションに次のように書きます。
Private Const INI_REWINDOW As String = "ReWindow.ini"
Constは定数を定義するキーワードで以後プログラムの中で INI_REWINDOW と記述すると "ReWindow.ini" と置き換えて解釈されます。定数を使うメリットはあとでiniの名前を変更したくなった時にこの部分を変えるだけですむことと打ち間違えによるエラーがなくなることです。ときどきプログラムの中に直接固定されたファイル名や数字を書き込む人がいますがそのようにすると訂正する時に大変ですし 思わぬエラーの原因になります。
ここまで完成したら、次はiniに値を書き込む処理を記述します。具体的な記述に入る前にiniの構造を決めておきましょう。今回はフォームの座標を記録するのですから、フォームのLeftプロパティ、Topプロパティ、Widthプロパティ、Heightプロパティの4つを記録できれば良いわけです。そこでiniの構造は次のようにします。
[Location] LEFT = 0 TOP = 0 WIDTH = 2000 HEIGHT = 2000 |
■ReWindow.iniの構造
今は仮に0とか2000とかの初期値を設定してあります。みなさんはプログラムを一旦セーブして、プログラムと同じフォルダにこのiniを作っておいてください。名前はもちろん「ReWindow.ini」です。
では、具体的な記述に入ります。今回はプログラムが終了した時、つまりウィンドウが閉じたタイミングでその時のウィンドウの座標をiniに記録すればよいのですからフォームのUnloadイベントに記述します。
Private Sub Form_Unload(Cancel As Integer) '●INIに現在の座標を書き込む SetINIValue Left, "LEFT", "LOCATION", App.Path & "\" & INI_REWINDOW SetINIValue Top, "TOP", "LOCATION", App.Path & "\" & INI_REWINDOW SetINIValue Width, "WIDTH", "LOCATION", App.Path & "\" & INI_REWINDOW SetINIValue Height, "HEIGHT", "LOCATION", App.Path & "\" & INI_REWINDOW End Sub |
■リスト4:フォームを閉じるときにフォームの位置と大きさをiniに記録する。
第4引数のiniの名前を指定する個所は INI_REWINDOWではなく、 App.Path & "\" & INI_REWINDOW となります。この部分を単にINI_REWINDOWと記述するとiniのフルパスではなくファイル名だけを指定していることになり、このような指定の仕方をするとWritePrivateProfileString関数 はWindowsフォルダの中から該当のiniファイルを探そうとしてしまいます。
ですから通常はここにはフルパスを指定することになるでしょう。その時にApp.Pathを使用するとプログラムと同じフォルダのフルパスを簡単に取得できるので便利です。
ここまで終われば後は簡単。最後はフォームのLoadイベントにiniの値を読み込んでプロパティにセットするコードを記述すれば完成です。この部分は次のようになります。
Private Sub Form_Load() '●INIから座標を読み込んでセットする。 Left = GetINIValue("LEFT", "LOCATION", App.Path & "\" & INI_REWINDOW) Top = GetINIValue("TOP", "LOCATION", App.Path & "\" & INI_REWINDOW) Width = GetINIValue("WIDTH", "LOCATION", App.Path & "\" & INI_REWINDOW) Height = GetINIValue("HEIGHT", "LOCATION", App.Path & "\" & INI_REWINDOW) End Sub |
■リスト5:フォームを開いたときにフォームの位置と大きさをiniから読み込んでセットする。
完成したら試してみてください。フォームを移動させたり大きさを変えたりしてプログラムを終了します。もう一度開始すると最後に指定された位置と大きさでウィンドウが表示されるでしょう?
念のために完成版の全コードを下に示しておきます。
Private Declare Function GetPrivateProfileString
Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName
As String, ByVal lpKeyName
As Any, ByVal lpDefault
As String, ByVal lpReturnedString
As String, ByVal nSize
As Long, ByVal lpFileName
As String) As Long Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long Private Const INI_REWINDOW As String = "ReWindow.ini" |
'■GetINIValue '■機能:INIから値を取得する。 Public Function GetINIValue(KEY As String, Section As String, ININame As String) As String Dim Value As String * 255 Call GetPrivateProfileString(Section, KEY, "ERROR", Value, Len(Value), ININame) GetINIValue = Left$(Value, InStr(1, Value, vbNullChar) - 1) End Function |
'■SetINIValue '■機能:INIに値を設定する。 '■備考:指定されたセクションやキーが存在しない場合は新たに作成される。 Public Function SetINIValue(Value As String, KEY As String, Section As String, ININame As String) As Boolean Dim Ret As Long Ret = WritePrivateProfileString(Section, KEY, Value, ININame) SetINIValue = CBool(Ret) End Function |
Private Sub Form_Load() '●INIから座標を読み込んでセットする。 Left = GetINIValue("LEFT", "LOCATION", App.Path & "\" & INI_REWINDOW) Top = GetINIValue("TOP", "LOCATION", App.Path & "\" & INI_REWINDOW) Width = GetINIValue("WIDTH", "LOCATION", App.Path & "\" & INI_REWINDOW) Height = GetINIValue("HEIGHT", "LOCATION", App.Path & "\" & INI_REWINDOW) End Sub |
Private Sub Form_Unload(Cancel
As Integer) '●INIに現在の座標を書き込む SetINIValue Left, "LEFT", "LOCATION", App.Path & "\" & INI_REWINDOW SetINIValue Top, "TOP", "LOCATION", App.Path & "\" & INI_REWINDOW SetINIValue Width, "WIDTH", "LOCATION", App.Path & "\" & INI_REWINDOW SetINIValue Height, "HEIGHT", "LOCATION", App.Path & "\" & INI_REWINDOW End Sub |
■リスト6:プログラム全体。前回閉じたときの位置にフォームを復元する。
7.おまけ
読み込み・書き込み・キーやセクションの作成。この3つができれば困ることはなさそうですが、他にもiniを操作する便利なAPI関数が提供されています。そのうちの2つを紹介しておきます。
MSDNライブラリを活用して使い方やその他のini操作関数も探してみてください。
GetPrivateProfileSectionNames | iniの全セクション名を返す |
GetPrivateProfileSection | セクション内の全キー名と値を返す |
■表1:その他のini操作関数
8.最後に
今回は中級編の割にはかんたんだったかもしれませんね。iniを使って最近開いたファイルをメニューに表示させる処理なんかもできますし、基本通りアプリケーション中の各種設定を保存することもできます。私自身はiniの最大の利点はアプリケーションの設定をUSBメモリやフロッピーディスクに入れて 簡単に持ち運べる点、そして、いざとなったらiniを直接開いて設定を変更できる点にあると思います。みなさんもいろいろ活用してください。