レジストリを活用しよう!

 レジストリ――正体はWindowsフォルダにあるUser.datとSystem.datのことです。これらのファイルはあらゆるアプリケーション、そしてOSと常にアクセスし、ありとあらゆる情報を格納しています。
 レジストリは非常に便利な存在です。ユーザーひとりひとりの情報を格納することにプログラマ側は気を使わずに済み、同じメーカーのアプリケーション同士の情報を交換しあい、ときには他メーカーのアプリケーションの情報を取得し、むちゃくちゃな方法として一種のグローバル変数として使う方法もあります。

 レジストリを操作する方法は、3つあります。ひとつはWin32APIを使う方法。ふたつめは、CWinAppクラスのメンバ関数を使う方法、みっつめはCRecentFileListクラスを使う方法です。これらを使ってレジストリにアクセスする方法を見ていきましょう。

Win32APIを使ってみる
 まずはじめに、winreg.hヘッダーファイルを読み込んでおかないと、このレジストリ関連のAPIは使えません。簡単な方法は、「ビルド」−「設定」−「C/C++」−「プリコンパイル済みヘッダー」で、「プリコンパイル済みヘッダーを使用しない」を選択すればそれでOKです。

 さて、実際のレジストリ操作ですが、まずRegSetValueEx関数で新しくキーを作るか、RegOpenKeyEx関数で既存のキーを開きます。このとき、成功すればそのキーへのハンドルを取得できます。レジストリへの操作は、このハンドルを使います。ファイルに似てますね。
 ハンドルを取得したら、RegSetValueEx関数で値を設定したり、RegQueryValueEx関数で値を取得したりします。
 操作を行ったら、キーへのハンドルを使って、そのキーを閉じます。そのためにRegCloseKey関数を用います。これも、ファイル操作に近いものです。

 Win32APIを使う以外の2つの方法は、HKEY_CURRENT_USERにしかアクセスできません。そのため、他のキーにアクセスするためにはWin32APIを使う必要があります。また、MFCに頼らないインストーラなどを作る場合にも必要でしょう。
 ここでは、他のふたつの方法ではアクセスできないレジストリについての情報を書いておきます。

 HKEY_CLASSES_ROOTでは、まず拡張子を設定できます。フォルダの「オプション」−「ファイルタイプ」で表示されるデータは、このレジストリが元になっています。自分のアプリケーションが独自のファイルタイプを持つ場合には、この部分に自分の拡張子を書き加えます。また、ShellNewというキーを加えると、フォルダ上の右クリック−新規作成で表示されます。
 その下にはOLE全般のCLSIDが書き込まれてます。これは、HKEY_CLASSES_ROOT上のCLSIDにさらに詳しく書かれてます。OLEの情報はすべてここで管理されているので、むやみに変えないようにしましょう。

 HKEY_CURRENT_USERには、現在ログインしているユーザーの各設定情報が書き込まれています。「ログイン」というのはウィンドウズNTでは普通のもので、1台の機械を何人もの人が使う場合、最初にユーザー名とパスワードを入力します。インターネットへのログインとほぼ同じです。そうやってログインした場合、各ユーザーごとにカスタマイズの内容は異なることになるので、ユーザーごとの情報は個別に取って置かれます。このHKEY_CURRENT_USERには、現在しているユーザーの情報が書かれているので、ソフトウェアはこの部分にアクセスするだけで済みます。現在ログインしているユーザーを調べる必要がなければ、他のユーザーの設定を変更する恐れもありません。
 さて、その内容ですが、Software以外はウィンドウズの設定です。例えば音を鳴らしたり、画面の色の設定があったりします。ちなみに、ウィンドウズの設定はSoftware\Microsoft\Windows\CurrentVersionにも書かれています。
 そのSoftwareには、各メーカー名が書かれており、その中に各アプリケーションの設定が書き込まれています。後で書く残りのふたつの方法は、この部分にのみ書き込みます。逆に言えば、Win32APIを使ってアクセスする必要のない部分ですね。

 HKEY_LOCAL_MACHINEには、そのコンピューターの設定が書き込まれています。ユーザーごとに変わることのないハードウェアの設定やアプリケーションのインストール場所、ウィンドウズのフォルダの位置などが書き込まれています。
 この部分で重要なのはSOFTWAREです。ここにもやはり各アプリケーションの設定が書き込まれています。インストールするときにこの部分に各設定(どこにインストールするかとか、バージョンとか)を書き込んでおくことで、バージョンアップのセットアップなどで確実な情報を得ることができます。
 また、ここでもSoftware\Microsoft\Windows\CurrentVersionには、ウィンドウズの各設定が書き込まれています。この部分には、いくつかアプリケーションの設定を登録する場所があります。例えばAppPathsに書き込むことで、パスが通っていなくてもそのアプリケーションが起動されるようになります。また、UnInstallに書き込むことで、コントロールパネルの「登録と削除」に情報が加えられます。

 HKEY_USERSには、各ユーザーの情報が書き込まれています。ウィンドウズ95をひとりで使っている場合には、ここには.Defaultしかありません。これは、基本的にHKEY_CURRENT_USERの内容と同じです。複数人数で使っている場合には、各ユーザーの情報があります。ウィンドウズNTでは、基本的に他のユーザーがこのレジストリにアクセスすることはできません。

 HKEY_CURRENT_CONFIGには、HKEY_LOCAL_MACHINE_Configの中身と同じ内容が書き込まれていると思います。ちょっとよくわかんないかも。ごめん。

 HKEY_DYN_DATAには、ハードウェアやドライバの設定が書き込まれています。ほとんどがバイナリー形式なので、下手に書き加えない方がいいでしょう。

 と、以上のようにWin32APIを使ってアクセスする部分は、HKEY_CLASSES_ROOTHKEY_LOCAL_MACHINEがほとんどです。簡単なライブラリを作っておくと便利でしょう。

CWinAppクラスのメンバ関数を使う
 CWinAppクラスには、レジストリを扱う便利なメンバ関数が揃っています。これを使わない手はありません。実際にどう使うか、見てみましょう。

 アプリケーションの各情報は、ウィンドウズ3.1までイニシャライゼーションファイル(拡張子がiniのファイル)を使っていました。ですが、Win32では、それらはレジストリのHKEY_CURRENT_USER\SOFTWAREに蓄えられています。CWinAppクラスは、デフォルトとしてなぜかイニシャライゼーションファイルへの書き込みを行うようにしています。それをまずはレジストリに書き込むようにします。そのために、SetRegistryKeyメンバ関数を使います。


	SetRegistryKey( _T( "KAB-Software Develop-studio" ) );
	

 こうすることで、各データはイニシャライゼーションファイルではなく、HKEY_CURRENT_USER\SOFTWARE\KAB-Software Develop-studio\MadoKAB(アプリケーションの名前です)へと書き込まれるようになりました(逆に言えば、HKEY_CURRENT_USER\SOFTWARE以外には書き込めないということです。それ以外はWin32APIを用います)。

 さて、実際の読み書きはWriteProfileStringメンバ関数GetProfileStringメンバ関数を用いて、値の書き込み&読み込みを行います。Win32APIを使うよりもずっと簡単です。ただ、操作できるのは整数と文字列だけです。バイナリーデータ等はWin32APIでないとムリです。
※一応、バイナリーデータ等を扱うメンバ関数がCWinAppクラスにもインプリメントされているらしいのですが、一応ヘルプファイルに載っていないので、使わないようにしましょう。
 また、これらのメンバ関数はWin32APIにも同じものがあるので、関数のスコープに注意してください。明示的にWin32APIを呼び出したいときには、スコープ解決演算子(::のこと)を使ってください。

 これらのメンバ関数を使うときの注意として、CWinAppクラスのオブジェクトへのポインタを取得する方法というのがあります。ドキュメントやビューからこれらのメンバ関数を使うときには、グローバル変数のを使うか、AfxGetApp関数を使ってCWinAppクラスへのポインタを取得しておきましょう。例としてはこんな感じでしょうか。


	CWinApp* pApp = AfxGetApp();
	i = pApp->GetProfileInt( _T( "Settings\\Global" ), _T( "Open" ), 0 );
	

 SetRegistryKeyメンバ関数は一度使ってしまえばいいので、InitInstanceメンバ関数の中で行ってしまいましょう。
 あと、他のアプリケーションの情報を書き換えないよう注意しましょう。無断で他のデベロッパーのアプリケーション情報を利用していると、そのアプリケーションの仕様が変わったときに困ったことになるので、とりあえず「使いますよ」くらいのことは言っておいた方がいいでしょう(相手がMSとかだとちょっとムリかも……)。

CRecentFileListクラスを使う
 さて最後に、CRecentFileListクラスという便利なクラスを使ってみましょう。あ、afxadv.hヘッダーファイルを読み込んでおきましょうね。
 このクラスは、ほとんどのアプリケーションに見られる「最近使ったファイル」の情報を扱うためのクラスです。「ファイル」の下の方につらつらとありますね。元々はファイルの情報を扱うためのものですが、いろいろなことに使えるんで便利に利用しましょう。

 まず最初に、前述のSetRegistryKeyメンバ関数を使ってあることが前提です。これも一回使っていればいいので、InitInstanceメンバ関数の中ですでに使っていればそれで問題ないでしょう。
 次にコンストラクタを使ってCRecentFileListクラスを構築します。


	CRecentFileList MList( 0, _T( "Settings\\MRU" ), _T( "%d" ), 20 );
	

 詳しいことはオンラインヘルプを見てください。こうすることで、HKEY_CURRENT_USER\SOFTWARE\KAB-Software Develop-studio\MadoKAB(アプリケーションの名前です)\Settings\MRUキーにデータが書き込まれるようになりました。データの名前は各数字が使われます。
 そのあと、実際に操作をする前にReadListメンバ関数を使って、実際のレジストリからデータを読み込んでおきます。これをしておかないと、オブジェクトの中身が空のままです。
 読み込んだあとは、各操作ができます。実際には配列を操作するのに似ています。
 操作したあとは、WriteListメンバ関数を使ってレジストリに書き込みます。これも忘れるとなんの意味もありません。

 このクラスはなかなか便利で、色々なリストをレジストリに書き込むときに重宝します。もしこれを手動でするとなると、forを使ってループを作り、各数字をitoaを使って文字に変換してWriteProfileStringメンバ関数を使わなければならないでしょう。それに比べれば、非常に便利なクラスといえます。

 しかし、いくつか問題点もあるので注意しておきましょう。その多くは、これが「最近使ったファイル」を操作するために作られたことに起因します。
 まず、データの読み込みや削除はどのインデックスでもできますが、値の追加は必ずいちばん最初に挿入されます。そして、おのおのの値がずらされ、規定の数をオーバーすると、いちばん最後の値が削除されます。これは、好きなように順番を変えたい配列を書き込むには適しません。
 また、「最近使ったファイル」のように、同じ値がふたつあるとひとつにまとめられます。配列中に同じ値が複数存在するようなものも、向かないということです(注:これは、格納する文字列がファイル名の場合のみです。Add()の中で、そのファイル名が適正なものかチェックされるためです)
 これらの問題から、普通の配列と同様に使う場合には注意が必要ということになります。

 あと、他に注意すべき点がいくつかあります。このクラスで扱ったキーは、完全に作り変えられます。そのキーの中に他の値があった場合でも、それらはすべて削除されて、このクラスの値だけが残るようになります。このクラスを使う場合には、別にキーを用意する必要があるということです。
 また、GetSizeメンバ関数は、そのときの実際の値の数ではなく、最初にコンストラクタに渡した引数の値(上の例では20)が返ってきます。そのため、実際の値の数はそのつどチェックすべきでしょう。

 こう見ると使いにくそうですが、うまく使えば非常に便利なものです。ぜひ使いましょう。

まとめ  さて、以上をまとめると……
・OS全体に関わるデータはWin32APIを使う。主にインストール時にお世話になる。
・アプリケーションの各設定はCWinAppクラスのメンバ関数を使う。
・リスト形式の設定をレジストリに書き込むときはCRecentFileListクラスが便利。
 というところになるでしょうか。レジストリは慣れるとひじょーに便利なので、がんがん使っていきましょう。

Update Room
 色々とおまけです。

HKEY_CLASSES_ROOTに簡単に書き込む
 MFCの中にはHKEY_CLASSES_ROOTに簡単に書き込むこめる関数があります。その名はSetRegKey()。ですが、これstatic関数なので他のファイルから使用することができません
 関数の定義はDocmgr.cppの76行目くらいにあると思うので、コピーして自分のアプリケーションで使ってしまいましょう(笑)。

アプリケーション名以外のキーを使いたい!!
 CWinAppのメンバを使ってレジストリに書き込むと、必ずアプリケーション名のキーを使用することになります。ですが、実際には変えたい場合もあるでしょう(実行ファイルの名前が同じでバージョンの違うものとか)。
 実は、このキーの部分はCWinApp::m_pszProfileNameという部分に格納されています。デフォルトではアプリケーション名ですが、ちゃんと変えることができます。実際にはCWinApp::SetRegistryKey()のあとくらいに、次のコードを書き込めばOKです。


	free( (void *)m_pszProfileName );
	m_pszProfileName = _tcsdup( cKeyStr );
//	cKeyStrには指定したいキーの名前が入っています。
	

 こうすることで、書き込むキーは「Software\(SetRegistryKey())\(m_pszProfileName)」となります。この文字列は動的に作製しなければならないので、その辺を注意してください。
(C)KAB-studio 1997, 1998 ALL RIGHTS RESERVED.