Windows 95 ではMS−DOSのしがらみで"A"〜"Z"でドライブを表します。
これは便利な場合もありますが、かえって使いづらい場合もありますし、
プログラムも余計に記述する必要があります。ファイルから検索
(grep)ダイアログ等では、コンボボックス等で有効なドライブの一覧を表示し、
そのうちのひとつを選択出来るようにしたいものです。そのためには、その時点
で有効なドライブ、そのドライブタイプ、ドライブのボリューム名を取得する
必要があります。
上記の目的には GetLogicalDriveStrings, GetDriveType, GetVolumeInformation
のAPIを使用します(これらの詳細はオンラインヘルプを見て下さい)。
すべて簡単に使用できますが、困ったことに、すべての有効なドライブに対し、
GetVolumeInformation でボリューム名を取得すると2〜3秒ほどを要してしまいます。
単純な実装では、ダイアログを開いてから、ユーザがすぐにダイアログを操作
可能になりません。これでは使い勝手がいいアプリとは言えません。
筆者はこれを回避するために、マルチスレッドを使ってバックグラウンドでボリューム
名を取得するコードも書いてもみましたが、処理時間が長いことには変わり無いので、
プログラム起動直後にダイアログをオープンされたりすると、結局ユーザは待たされる
ことになります。この場合、マルチスレッドのオーバヘッドがあり、単純な実装方法
よりもかえって良くないとも言えます。
そこで、『すべての有効なドライブに対し、GetVolumeInformation
をコールしない』という方法で上記の問題を解決することにしました。
GetDriveType の帰り値が DRIVE_REMOVABLE, DRIVE_CDROM の時は
ボリューム名の取得を行なわないようにします。これは、FD、CD−ROMと
いったドライブはボリューム名の取得にかなりの時間を要する
からです。
コードは以下の様になります。
char drives[INFOBUF_SIZE]; char volumeName[INFOBUF_SIZE], fileSystem[INFOBUF_SIZE]; GetLogicalDriveStrings(INFOBUF_SIZE, drives); // 有効なドライブの一覧を取得 const char *ptr = drives; while( *ptr != '\0' ) { // 有効なドライブが残っている間 uint driveType = GetDriveType(ptr); if( driveType != DRIVE_REMOVABLE && // リムーバブルでなく、 driveType != DRIVE_CDROM ) // CD−ROMでもなければ { GetVolumeInformation(ptr, volumeName, INFOBUF_SIZE, 0, 0, 0, fileSystem, INFOBUF_SIZE); // ボリューム名を取得 printf("drive = %s, ", ptr); printf("volumneName = %s, ", volumeName); printf("fileSystem = %s\n", fileSystem); } ptr = strchr(ptr, '\0'); // 次のドライブ ASSERT(ptr); ptr += 1; }
高津戸敦氏から、ボリュームの名前を取得するのは GetVolumeInformation ではなく SHGetFileInfo
であるとのご指摘をいただきました。ヘルプをよく見てみると、関数名からは想像しづらいことに、
この関数はボリューム名を取得することができます。さらにFDやCD−ROMに対してもそんなに時間がかかりません。(^o^)
VC++や秀丸はFDやCD−ROMの場合にボリューム名が表示されないので、以前のコードで満足していましたが、
やはりドキュメントは関係なさそうでも、一通りよーく読まなきゃだめだということですね。
で、コードは以下のようになりました。
char drives[INFOBUF_SIZE]; GetLogicalDriveStrings(INFOBUF_SIZE, drives); // 有効なドライブの一覧を取得 const char *ptr = drives; while( *ptr != '\0' ) { // 有効なドライブが残っている間 uint driveType = GetDriveType(ptr); SHFILEINFO shFileInfo; SHGetFileInfo(ptr, 0, &shFileInfo, sizeof(SHFILEINFO), SHGFI_DISPLAYNAME); printf("drive = %s, ", ptr); printf("volumneName = %s, ", shFileInfo.szDisplayName); ptr = strchr(ptr, '\0'); // 次のドライブ ASSERT(ptr); ptr += 1; }
次のTips 津田伸秀 のホームページに戻る。
Last Updated on 25-Oct-1996, Copyright (C) 1996 by Nobuhide Tsuda, All Right Reserved.
このホームページに関するご質問、ご要望、バグレポート等は
Nobuhide_Tsuda@jsn.justnet.or.jp
までメールをいただければ幸いです。