レガシー Windows API(概要)について

ここで紹介しているAPIは、Windows95、Windows NT3.5時代のAPI群であり、最新のAPIは含まれていないことに注しして欲しい。なお、当時の解説書は現在よりもより詳細に解説しているため、参考になるはずである。

  • レイアウトを変換する際、崩れているページがあります。
  • 概要およびSampleコードはありますが、APIの解説はありません。

ご要望があれば旧版のWin32 API(HELP形式)をお譲りします。問い合わせフォームより申し込みください。

Windows API ファイル マネージャ エクステンションの概要

Microsoft(R) Windows(TM) のファイル マネージャ エクステンションは、 ファイル マネージャにメニューとボタンを追加するダイナミック リンク ライブラリ (DLL) です。また、 ファイル マネージャ エクステンションは、 ボタンのヘルプ テキストを (ステータス バーに) 表示することもできます。

ファイル マネージャは、 エクステンションのリストを初期化ファイルで管理しており、 起動時にエクステンションをロードします。エクステンションDLLには、 ファイル マネージャが送ったコマンド メッセージや通知メッセージを処理するエントリ ポイントがあります。一度にインストールできるエクステンションDLL5つまでです。このトピックでは、 ファイル マネージャ エクステンションを作成してインストールする方法について説明します。

次に示すトピックでは、 ファイル マネージャ エクステンションについて説明しています。

ファイル マネージャ エクステンションの作成

エントリ ポイント関数の作成

エクステンションのロード

カスタム ボタンの追加

メニュー選択の処理

エクステンション メニューの初期化

エクステンション メニューの更新

ファイル選択の処理

エクステンションDLLの終了

エクステンションのインストール

エクステンション メッセージ

ファイル マネージャからのコマンドやメッセージの処理

[削除取り消し]コマンドの追加

ファイル マネージャ エクステンション関数

ファイル マネージャ エクステンションの作成

ファイル マネージャ エクステンションは、 標準のエントリ ポイントであるFMExtensionProcコールバック関数を持つDLLでなければなりません。エクステンションには、 ファイル マネージャのメッセージや構造体を定義しているWFEXT.Hヘッダー ファイルをインクルードしなければなりません。ファイル マネージャは、 次に示すメッセージをDLLFMExtensionProc関数に送ることによって、 エクステンションDLLと通信します。

メッセージ意味

199エクステンションのメニューの項目をユーザーが選択しました。値は、 選択されたメニュー項目の識別子です。

FMEVENT_HELPSTRING ユーザーは[拡張]メニューあるいはツールバーのコマンド項目を選択しています。ファイル マネージャは、 エクステンションにヘルプ文字列の表示を要求しています。

FMEVENT_HELPMENUITEM ユーザーが[拡張]メニューあるいはツールバーのコマンド項目を選択して、 F1キーを押しました。ファイル マネージャは、 エクステンションがコマンド項目に対して適切なWinHelpを呼び出すよう要求しています。

FMEVENT_INITMENU ユーザーがエクステンションのメニューを選択しました。エクステンションは、 メニューの項目を初期化しなければなりません。

FMEVENT_LOAD ファイル マネージャがエクステンションDLLをロードしようとしており、 DLLが供給するメニューに関する情報をDLLに要求しています。

FMEVENT_SELCHANGE ファイル マネージャのディレクトリ ウィンドウや[検索結果]ウィンドウでの選択が変化しました。

FMEVENT_TOOLBARLOAD ファイル マネージャがツールバーを作成しようとしており、 DLLがツールバーに追加するボタンに関する情報をDLLに要求しています。

FMEVENT_UNLOAD ファイル マネージャがエクステンションDLLをアンロードしようとしています。

FMEVENT_USER_REFRESH ユーザーが[ウィンドウ]メニューから[最新のファイル情報に更新]コマンドを選択しました、 エクステンションは、 必要ならばメニューの項目を更新します。

エントリ ポイント関数の作成

ファイル マネージャは、 FMExtensionProcコールバック関数によってエクステンションDLLと通信します。この関数は、 エクステンションのモジュール定義 (.DEF) ファイルでエクスポートしてください。前述のメッセージを受け取ったFMExtensionProc関数は、 次の表に示す処理を実行します。

処理動作

エクステンションの初期化 (FMEVENT_LOAD)

メニューの名前とハンドルをファイル マネージャに渡して、 メニュー項目の差分値を保存します。

メニューの初期化 (FMEVENT_INITMENU)

すべてのトップ レベルと任意のサブメニューのメニュー項目を初期化します。

ツールバーの初期化 (FMEVENT_TOOLBARLOAD)

コマンド識別子、 ヘルプ文字列識別子、 スタイル、 ビットマップ識別子などの、 ツールバーに追加するボタンに関する情報をファイル マネージャに渡します。

メニュー選択の処理

ユーザーがエクステンションのメニューから選択したコマンドを実行します。

ファイル選択の処理 (FMEVENT_SELCHANGE)

ユーザーがディレクトリ ウィンドウや[検索結果]ウィンドウから選択したファイルに関する情報をファイル マネージャに問い合わせます。

メニューの項目の更新 (FMEVENT_USER_REFRESH)

ユーザーが[ウィンドウ]メニューの[最新のファイル情報に更新]コマンドを選択したときに、 メニューを適切に変更します。

メニュー項目ヘルプ文字列の供給 (FMEVENT_HELPSTRING)

ファイル マネージャの指定されたメニューの指定されたコマンドに、 ヘルプ文字列を供給します。ファイル マネージャは、 ウィンドウの左下の領域にこの文字列を表示します。

WinHelpへのメニュー項目ヘルプ要求のパス (FMEVENT_HELPMENUITEM)

ファイル マネージャから渡されたウィンドウと、 メニュー項目を、 WinHelpに渡します。

エクステンションDLLの終了 (FMEVENT_UNLOAD)

割り当てたメモリを解放し、 終了する準備をします。

FMExtensionProc関数は次のように定義されています。

LONG WINAPI FMExtensionProc(hwnd, wMsg, lParam)
HWND hwnd;
WORD wMsg;
LONG lParam;
hwnd
パラメータは、 ファイル マネージャ ウィンドウを識別します。エクステンションは、 ダイアログ ボックスやメッセージ ボックスを表示するときの親ウィンドウとして、 このウィンドウを指定しなければなりません。また、 このハンドルは、 問い合わせメッセージをファイル マネージャに送るのにも使われます。uMsgパラメータは、 上記のファイル マネージャ メッセージのいずれかを示します。lParamパラメータは、 メッセージによって異なる値を示します。FMExtensionProcの戻り値は、 uMsgパラメータの値によって異なります。

ファイル マネージャには、 階層 (カスケード) メニューを追加できます。また、 メニュー項目は、 灰色表示、 使用不能、 チェックなどの状態を設定できます。メニュー項目にはテキストしか使えません。オーナー描画メニューやビットマップ メニューはサポートされていません。また、 チェック マークのビットマップの変更もサポートされていません。

ファイル マネージャは、 FMExtensionProc関数を呼び出したとき、 関数が戻るまで、 (ファイル システムの変更を) ディレクトリ ウィンドウに反映しません。これによって、 エクステンションは、 ファイル マネージャに余分な再描画を行わせずに、 大量のファイル処理を実行できます。エクステンションがファイル マネージャにFM_REFRESH_WINDOWSメッセージを送ってディレクトリ ウィンドウを再描画させる必要はありません。FM_REFRESH_WINDOWSについて詳しくは、 エクステンション メッセージを参照してください。

エクステンションのロード

ファイル マネージャは、 まず、 FMEVENT_LOADメッセージをFMExtensionProc関数に送ります。FMEVENT_LOADメッセージのlParamパラメータは、 エクステンションが供給するメニューに関する情報 (メニュー名やメニュー ハンドルなど) をファイル マネージャが取得するために使われるFMS_LOAD構造体を指すポインタです。FMS_LOAD構造体の説明は構造体を参照してください。

また、 ファイル マネージャは、 FMS_LOAD構造体を使って、 メニュー項目の差分値をエクステンションに渡します。ファイル マネージャは、 自分自身のメニュー項目識別子との重複を避けるため、 エクステンションが供給するメニューのメニュー項目識別子に差分値を加算します。ファイル マネージャによってロードされた後でメニューを変更するエクステンションDLLは、 差分値を使わなければなりません。たとえば、 メニュー項目を削除する場合、 エクステンションDLLは、 メニュー項目識別子に差分値を加算して、 DeleteMenu関数のidItemパラメータとして渡さなければなりません。

このメッセージに対してエクステンションがFALSEを返すと、 ファイル マネージャは、 FreeLibrary関数を呼び出して、 エクステンションDLLとの通信を終了します。エクステンションの初期化に問題が発生したためエクステンションをロードしないようにファイル マネージャに通知できるのはこのときだけです。

カスタム ボタンの追加

ファイル マネージャ エクステンションは、 FMEVENT_TOOLBARLOADメッセージに対してボタン情報を返すことによって、 ファイル マネージャのツールバーにカスタム ボタンを追加できます。ファイル マネージャは、 FMEVENT_LOADメッセージでエクステンションがカスタム メニューを正常にインストールできたときだけ、 このメッセージをエクステンションのFMExtensionProc関数に送ります。カスタム ボタンは、 カスタム メニューのメニュー コマンドのアクセラレータとして使ってください。

FMEVENT_TOOLBARLOADメッセージのlParamパラメータは、 FMS_TOOLBARLOAD構造体を指すポインタです。ファイル マネージャ エクステンションは、 ボタンの個数やボタンのイメージを示すビットマップの識別子など、 カスタム ボタンに関する情報をこの構造体にコピーしなければなりません。また、 エクステンションは、 EXT_BUTTON構造体の配列のアドレスも設定しなければなりません。この構造体には、 対応するボタンのコマンド識別子を設定します。ボタンがメニュー コマンドのアクセラレータならば、 ボタンの識別子と対応するメニュー コマンド識別子は同じでなければなりません。FMS_TOOLBARLOAD構造体とEXT_BUTTON構造体の説明は、 構造体を参照してください。

ボタンのイメージを示すビットマップは、 ビットマップ リソースでなければなりません。エクステンションは、 エクステンションのDLLファイルにあるリソースの識別子をFMS_TOOLBARLOAD構造体にコピーしなければなりません。

ビットマップには、 各ボタンのイメージをまとめて設定します。ビットマップの高さは常に15ピクセルです。また、 各ボタン イメージの幅は16ピクセルでなければならないため、 ビットマップの幅は常に16ピクセルの倍数です。ボタン イメージは、 左から右に設定してください。たとえば、 EXT_BUTTON構造体の配列で指定した第1のボタンのイメージは、 ビットマップのいちばん左のイメージです。

エクステンションは、 文字列リソースの識別子をEXT_BUTTON構造体のidsHelpメンバに指定することによって、 1行のヘルプ テキストを提供できます。ユーザーがボタンを選択すると、 ファイル マネージャは、 文字列リソースを取得してツールバーに表示します。

メニュー選択の処理

エクステンションのメニュー用に定義するメニュー リソースでは、 1から99までのメニュー項目識別子を使ってください。ユーザーが項目を選択すると、 エクステンションは、 コマンド通知を受け取ります。このコマンド通知は、 リソース定義ファイル (ファイル名拡張子が.RCのファイル) で定義されている、 選択されたメニュー項目の識別子です。コマンド通知は、 識別子と差分値の和ではありません。エクステンションDLLFMExtensionProc関数は、 コマンド通知を処理することによってコマンドを実行します。

エクステンション メニューの初期化

ユーザーがファイル マネージャのメニュー バーからエクステンションのメイン メニュー項目を選択すると、 ファイル マネージャは、 エクステンションDLLFMEVENT_INITMENUメッセージを送ります。エクステンションは、 このメッセージを使って、 自分のメニュー項目を処理できます。たとえば、 エクステンションは、 チェック マークの付加、 項目の使用不能、 項目の灰色表示などをこのメッセージで行うことができます。

ユーザーがエクステンションのメニューのサブメニューを選択しても、 ファイル マネージャはFMEVENT_INITMENUメッセージを送りません。エクステンションDLLは、 サブメニューの項目も含めて、 全項目を同時に初期化しなければなりません。

エクステンション メニューの更新

ユーザーが[ウィンドウ]メニューの[最新のファイル情報に更新]コマンドを選択すると、 ファイル マネージャは、 FMEVENT_USER_REFRESHメッセージをエクステンションDLLに送ります。エクステンションは、 このメッセージのときに、 自分のメニュー項目を更新できます。

ファイル選択の処理

ユーザーがディレクトリ ウィンドウや[検索結果]ウィンドウからファイル名を選択すると、 ファイル マネージャは、 FMEVENT_SELCHANGEメッセージをエクステンションDLLに送ります。エクステンションは、 このメッセージを処理するときに、 問い合わせメッセージをファイル マネージャに送って、 ユーザーの選択に関する詳細な情報を取得できます。詳しくは、 エクステンション メッセージを参照してください。

ユーザーは選択を頻繁に変更するため、 エクステンションは、 FMEVENT_SELCHANGEメッセージを処理したらすぐに戻って、 ユーザーの選択操作を遅らせないようにしてください。

エクステンションDLLの終了

ファイル マネージャは、 終了するとき、 各エクステンションDLLにFMEVENT_UNLOADメッセージを送ってから、 FreeLibrary関数を呼び出してDLLを解放します。各DLLは、 自分が割り当てたメモリを解放しなければなりません。

エクステンションのインストール

ファイル マネージャは、 WINFILE.INI初期化ファイルの[AddOns]セクションに設定されているエクステンションをインストールします。各設定には、 エントリと値があります。エントリは、 エクステンションの名前を示す文字列です。エントリに割り当てる値は、 エクステンションDLLのパスを示す文字列です。WINFILE.INIに設定を追加するには、 WritePrivateProfileString関数を使ってください。

[AddOns]
MyExtension=C:\NT\SYSTEM\MYEXT.DLL

ファイル マネージャは、 エクステンションDLLが見つからなくてもエラー メッセージを表示しないため、 エクステンションDLLを削除すればエクステンションをインストール解除できます。しかし、 エクステンションDLLをインストールするアプリケーションは、 エクステンションの設定をWINFILE.INIから削除するインストール解除オプションを用意してください。

エクステンション メッセージ

エクステンションは、 次に示すメッセージを送って、 ファイル マネージャから情報を取得できます。ファイル マネージャが正しく応答するのは、 FMExtensionProc関数から送られたメッセージだけです。

メッセージ説明

FM_GETDRIVEINFOファイル マネージャは、 アクティブなウィンドウのドライブ情報を返します。エクステンションは、 FMS_GETDRIVEINFO構造体を指すポインタを渡します。ファイル マネージャは、 この構造体にドライブ情報を設定します。

FM_GETFILESELファイル マネージャは、 アクティブなファイル マネージャ ウィンドウ (ディレクトリ ウィンドウか[検索結果]ウィンドウ) で選択されているファイルに関する情報を返します。エクステンションは、 FMS_GETFILESEL構造体を指すポインタを渡します。ファイル マネージャは、 この構造体にファイル情報を設定します。

FM_GETFILESELLFNFM_GETFILESELメッセージと同じですが、 選択されているファイルの名前が長い場合があります。

FM_GETFOCUSファイル マネージャは、 入力フォーカスを持つウィンドウの種類を識別する値を返します。

FM_GETSELCOUNTファイル マネージャは、 ディレクトリ ウィンドウと[検索結果]ウィンドウで選択されているファイルの個数を返します。

FM_GETSELCOUNTLFNFM_GETSELCOUNTメッセージと同じですが、 個数には長い名前のファイルも含まれます。

FM_REFRESH_WINDOWSファイル マネージャは、 アクティブなウィンドウまたはすべてのウィンドウを再描画します。このメッセージは、 ファイル マネージャの[ウィンドウ]メニューの[最新のファイル情報に更新]コマンドに似ています。

FM_RELOAD_EXTENSIONSファイル マネージャは、 エクステンションをすべて再ロードします。ファイル マネージャは、 まず、 各エクステンションにFMEVENT_UNLOADメッセージを送って、 エクステンションをすべてアンロードします。それから、 各エクステンションを再ロードして、 各エクステンションにFMEVENT_LOADメッセージを送ります。エクステンションは、 WINFILE.INIファイルから自分の設定を削除した後FM_RELOAD_EXTENSIONSメッセージを送ることによって、 自分自身をインストール解除できます。ほかのアプリケーションやプログラム (インストール プログラムなど) も、 PostMessage関数を呼び出してこのメッセージをポストできます。

ファイル マネージャからのコマンドやメッセージの処理

次に示すコードは、 サンプル エクステンションDLLのFMExtensionProc関数です。この例は、 ファイル マネージャが送るメニュー コマンドや通知メッセージをエクステンションが処理する方法を示しています。

HINSTANCE hinst;

HMENU hmenu;
WORD wMenuDelta;

BOOL fMultiple = FALSE;

BOOL fLFN = FALSE;


LONG WINAPI FMExtensionProc(hwnd, wMsg, lParam)

HWND hwnd;

WORD wMsg;

LONG lParam;

{

CHAR szBuf[200];

INT count;


switch (wMsg) {

case FMEVENT_LOAD:

#define lpload((LPFMS_LOAD) lParam)

/* Save the menu-item delta value. */

wMenuDelta = lpload->wMenuDelta;

/* Fill the FMS_LOAD structure. */

lpload->dwSize = sizeof(FMS_LOAD);
lstrcpy(lpload->szMenuName, "&Extension");

/* Return the handle of the menu. */

hinst = GetModuleHandle("ext.dll");
lpload->hMenu = GetSubMenu(LoadMenu(hinst,
MAKEINTRESOURCE(MYMENU)), 0);

return (LONG)TRUE;

case FMEVENT_UNLOAD:

/* Perform any cleanup procedures here. */

break;

case FMEVENT_INITMENU:

/* Copy the menu handle. */

hmenu = (HMENU) lParam;

/*
* Add check marks to menu items as appropriate.
* Add menu-item delta values to menu-item
* identifiers to specify the menu items to check.
*/

CheckMenuItem(hmenu, wMenuDelta + IDM_MULTIPLE,
fMultiple ? MF_BYCOMMAND | MF_CHECKED :
MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem(hmenu, wMenuDelta + IDM_LFN,
fLFN ? MF_BYCOMMAND | MF_CHECKED :
MF_BYCOMMAND | MF_UNCHECKED);
break;

case FMEVENT_TOOLBARLOAD:
{
static EXT_BUTTON extbtn[] = {
{1, 0, 0},
};

/* Fill the FMS_TOOLBARLOAD structure. */

#define lptbld ((LPFMS_TOOLBARLOAD) lParam)

lptbld->dwSize = sizeof(FMS_TOOLBARLOAD);
lptbld->lpButtons = (LPEXT_BUTTON) &extbtn;
lptbld->cButtons = 1;
lptbld->cBitmaps = 1;
lptbld->idBitmap = ID_BUTTONBITMAP;

return (LONG)TRUE;

}

case FMEVENT_USER_REFRESH:
MessageBox(hwnd, "User refresh event",
"Hey!", MB_OK);
break;

case FMEVENT_SELCHANGE:
break;

/*
* The following messages are generated when the user
* chooses items from the extension menu.
*/

case FMEVENT_HELPSTRING:
#define lphs ((LPFMS_HELPSTRING)lParam)
if (lphs->idCommand == -1)
lstrcpy(lphs->szHelp, "Help for extension menu");
else
wsprintf(lphs->szHelp, "Help for item %d", lphs->idCommand);

break;

case FMEVENT_HELPMENUITEM:

wsprintf(szBuf, "Help for %d", lParam);
MessageBox(hwnd, szBuf, "WinHelp call", MB_OK);

/*
* Use: WinHelp(hwnd, "ExtHelp.hlp", HELP_CONTEXT, lParam);
*/

break;

case IDM_GETFOCUS:
wsprintf(szBuf, "Focus %d", (INT) SendMessage(hwnd,
FM_GETFOCUS, 0, 0));
MessageBox(hwnd, szBuf, "Focus", MB_OK);
break;

case IDM_GETCOUNT:
count = (INT) SendMessage(hwnd,
fLFN ? FM_GETSELCOUNTLFN : FM_GETSELCOUNT,
0, 0);

wsprintf(szBuf, "%d files selected", count);
MessageBox(hwnd, szBuf, "Selection Count", MB_OK);
break;

case IDM_GETFILE:
{
FMS_GETFILESEL file;

count = (INT) SendMessage(hwnd,
fLFN ? FM_GETSELCOUNTLFN : FM_GETSELCOUNT,
FMFOCUS_DIR, 0);

while (count >= 1) {

/*
* Selection indices are zero-based (0 is
* first).
*/

count--;
SendMessage(hwnd, FM_GETFILESEL, count,
(LONG) (LPFMS_GETFILESEL) &file);
wsprintf(szBuf, "file %s\nSize %ld",
(LPSTR) file.szName, file.dwSize);
MessageBox(hwnd, szBuf, "File Information",
MB_OK);

if (!fMultiple)
break;
}
break;
}

case IDM_GETDRIVE:
{
FMS_GETDRIVEINFO drive;

SendMessage(hwnd, FM_GETDRIVEINFO, 0,
(LONG) (LPFMS_GETDRIVEINFO)&drive);
wsprintf(szBuf,
"%s\nFree %ld\nTotal %ld\nVolume %s\nShare %s",
(LPSTR) drive.szPath, drive.dwFreeSpace,
drive.dwTotalSpace, (LPSTR) drive.szVolume,
(LPSTR) drive.szShare);
MessageBox(hwnd, szBuf, "Drive Info", MB_OK);
break;
}

case IDM_LFN:
MessageBox(hwnd, "IDM_LFN", "Hi", MB_OK);
fLFN = !fLFN;
break;

case IDM_MULTIPLE:
MessageBox(hwnd, "IDM_MULTIPLE", "Hi", MB_OK);
fMultiple = !fMultiple;
break;

case IDM_REFRESH:
case IDM_REFRESHALL:
SendMessage(hwnd, FM_REFRESH_WINDOWS,
wMsg == IDM_REFRESHALL, 0);
break;

case IDM_RELOAD:
PostMessage(hwnd, FM_RELOAD_EXTENSIONS, 0, 0);
break;
}
return 0L;
}

[削除取り消し]コマンドの追加

ファイル マネージャは、 [ファイル]メニューの ([削除]コマンドの下の)[削除取り消し]コマンドを追加するためのフックをサポートしています。「修復」ダイナミック リンク ライブラリをWINFILE.INIファイルで指定すると、 ファイル マネージャは、 起動時に[削除取り消し]コマンドを[ファイル]メニューに追加します。ユーザーが[削除取り消し]コマンドを選択すると、 ファイル マネージャは修復DLLを呼び出します。

WINFILE.INIファイルの[settings]セクションには、 次のように、 修復DLLへの参照を指定してください。

[settings]
UNDELETE.DLL=C:\MYDIR\OTHER.DLL

修復DLLには、 標準エントリ ポイントのUndeleteFile関数がなければなりません。DLLのモジュール定義 (.DEF) ファイルのEXPORTS文でこの関数の名前を指定して、 この関数をエクスポートしてください。

UndeleteFile関数の定義を次に示します。

DWORD APIENTRY UndeleteFile(hwndParent, lpszDir)
HWND hwndParent;
LPSTR lpszDir;

hwndParentパラメータは、 DLLが作成するダイアログ ボックスの親ウィンドウを識別します。lpszDirパラメータは、 使用すべき初期ディレクトリ (C:\TEMPなど) を示します。

ファイル マネージャ エクステンション関数

ファイル マネージャ エクステンションに関する関数を次に示します。

FMExtensionProc

UndeleteFile

▲ページトップに戻る

【本を読んでもよくらからない】 … 個別指導でわかりやすくお教えします