[戻る] [Top]

Windows Programming TIPS With MFC

アプリケーションの設定のiniファイルへの保存

アプリケーションはさまざまな設定を保存しておきたくなりますが、思わぬところに保存されたりすることがあります。

そのあたりを整理したうえで、アプリケーション設定をアプリケーションと同じところなど、自由な場所を指定してiniファイルをおく方法を紹介します。

MFCの標準の動作

MFCはWindowsで推奨されている標準的な2つ(※見方によっては3つ)の方法での設定保存をサポートしています。

そしてそれらは、それぞれに別の方法があるのではなく、初期設定によってCWinAppのProfile関係の関数の内部で自動的に切り替えられますので、初期設定さえしてしまえば使う側はあまり意識せずに使用することができるようになっています。

1つ目はレジストリを使う方法です。最近のアプリケーションではこの方法がもっとも一般的といえるでしょう。

この方法を採る場合、 アプリケーションの初期化コードの中でSetRegistryKeyを呼び出します。この引数で与えたキーの下に設定が保存されます。ウィザードで作成したアプリケーションではInitinstanceのなかでこの関数が呼び出される形で生成されているはずです。必ず、SetRegistryKeyの引数部分をアプリケーションの名前などに書き換えて使用するようにしましょう。

2つ目の方法はWindowsフォルダ内ののiniファイルを使う方法です。これはWindows3.1などアプリケーションが設定をレジストリに保存することが一般的でなかったときの標準的な方法でした。

この場合、上記レジストリの場合のSetRegistryKeyの呼び出しを"しない"ようにします。そうすると、exe名と同じで拡張子が.iniのファイルが作成されその中に設定が保存されるようになります。以上のような初期設定を行ったうえで、CWinAppのWriteProfileInt,WriteProfileStringなどを使用すれば書き込むことができ、GetProfileIntGetProfileStringを使用することで読み出すことができます。

以上2つが、特殊なことをせずにMFCを使用した場合に簡単にできる設定の保存方法です。

※見方によって3つというのは、最近のWindowsにはiniファイルをレジストリにマッピングすることができる機能があることを指しています。この設定がされている場合iniファイルに書き込むのと同様の方法を行うと指定されたレジストリに保存されると言う動作になります。通常はこの方法を使う必要はないとおもいます。

Windowsフォルダ以外に場所にiniファイルを置く方法

実際には、iniファイルがWindowsフォルダにあるのはそのアプリケーションを使う側から考えるとあまり歓迎されません。レジストリに書くのが最近ではもっとも一般的ですし使う側からも受け入れやすいと思いますので、とくに事情がなければその方法を採るのがよいでしょう。

しかし、"他のマシンへの移行を簡単にしたい"とか、"UIで設定できる以外の部分をユーザーに書き換えさせたいがレジストリでは他の大事な設定もあるのでiniファイルのほうが都合が良い"など---また、"レジストリに保存したくない"という単なる好みもあるでしょう;-)。。---といった理由でiniファイルにしたいことがあるでしょう。そしてその場合前述のようにWindowsフォルダに起きたくないということは多いでしょう。そのような場合は以下のような手順を採ることで指定のiniファイルに設定を保存することができます。

1.通常のiniファイルを使用する方法どおり、SetRegistryKeyを呼び出さないようにする。

2.初期化処理内で、CWinApp::m_pszProfileNameメンバ変数に使用したいiniファイルのフルパスを指定する。

3.あとは通常通りProfile系関数を使用して読み書きする。

以上のようにそれほど難しいことはしなくても対応できます。

ただし注意点すべき点が一点あります。

2の手順のときにCWinApp::m_pszProfileNameにすでに値が設定されていたら---通常はされていると思います---その文字列をfreeすること、設定する場合は、strdupなどであとでfreeされてもいい領域に確保された文字データを渡すことです。

もともとフレームワークはstrdupでここにアプリケーション名から生成したiniファイル名を設定します。よってこれを入れ替えることで指定したファイルにかかれるようにしているわけです。よって、もともとフレームワークが想定した状態で値をセットする必要があるということです。そうでないと、終了時にフレームワークがこの領域をfreeしに行きそこでアプリケーションエラーが発生してしまうことがあります。

この方法を使用する場合、iniファイルをexeのあるフォルダにexeのファイル名と同じで拡張子がiniのファイルとして設定したいことが割合多いと思います。

最後にこの場合のサンプルコードを示しておきます。C????App::InitInstance()内の適当と思われる位置にこのコードを挿入することでそのような動作となると思います。
---
// Application Profile path
TCHAR path[_MAX_PATH+1];
GetModuleFileName( NULL, path, _MAX_PATH );
PathRenameExtension( path, TEXT(".ini") );
free((void*)m_pszProfileName);
m_pszProfileName=_tcsdup(path);
----
また、exe名を使用するのではなく固定名を使用したいこともあるでしょう。
----
TCHAR path[_MAX_PATH+1];
GetModuleFileName(NULL, path, _MAX_PATH);
PathRemoveFileSpec(path);
PathAppend(path, "abc.ini");
free((void*)m_pszProfileName);
m_pszProfileName=_tcsdup(path);
----
------

更新履歴