FindFirstChangeNotificationで監視して変更があったらシグナルを受け取ることでできますが、ファイル自体を監視することはできなくディレクトリの監視しかできないようです。
なので対象ファイルのタイムスタンプをあらかじめ確保しておき、監視対象のディレクトリに変更があったときにその時点でのファイルのタイムスタンプと比較して変更を検知します。
すなわちファイルスタンプが変わらない変更に関しては検知できませんが、通常の使用であればそんなことはないと思うので、この方法で実装してみました。
詳しいことはソースにコメントしてあります。
#include "user32.as"
#include "kernel32.as"
#module
#include "hspext.as"
#define TRUE 1
#define FALSE 0
#define FILE_NOTIFY_CHANGE_FILE_NAME $00000001
#define FILE_NOTIFY_CHANGE_DIR_NAME $00000002
#define FILE_NOTIFY_CHANGE_ATTRIBUTES $00000004
#define FILE_NOTIFY_CHANGE_SIZE $00000008
#define FILE_NOTIFY_CHANGE_LAST_WRITE $00000010
#define FILE_NOTIFY_CHANGE_SECURITY $00000100
#define INVALID_HANDLE_VALUE $FFFFFFFF
#define INFINITE $FFFFFFFF
#define QS_ALLINPUT $000000FF
#define WAIT_OBJECT_0 $00000000
#define GENERIC_READ $80000000
#define FILE_SHARE_DELETE $00000004
#define FILE_SHARE_READ $00000001
#define FILE_SHARE_WRITE $00000002
#define OPEN_EXISTING $00000003
#define FILE_ATTRIBUTE_NORMAL $00000080
/*
モジュール内共用変数
pathFile : 監視対象ファイルのパス
pathDir : 監視対象ファイルがあるディレクトリ
hObj : 監視対象ディレクトリのシェルオブジェクト
fileInfo : 監視対象ファイルのタイムスタンプ情報
observing : 監視が進行中であるかのフラグ
*/
sdim pathFile
sdim pathDir
dim hObj
dim fileInfo
dim observing
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ディレクトリの監視を開始する
// (ファイルそのものの監視はできないっぽい?)
//
// 戻り値
// 0 : 失敗
// 1 : 成功
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#deffunc StartObservingFile str f
sdim pathFile, strlen(f)
sdim pathDir
pathFile = f
pathDir = getpath(pathFile, 32)
// 比較するためにファイルのタイムスタンプをとっておく
UpdateFileInfo
// 監視オブジェクト作成
dim hObj
hObj = FindFirstChangeNotification(pathDir, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SECURITY)
if (hObj == INVALID_HANDLE_VALUE) : return 0
observing == TRUE
return 1
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ファイルが変更されるまで待機する
//
// 第1引数 : ファイルが変更されたときのジャンプ先
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#deffunc stopEx label changed, \
local arr, local _stat
dim arr, 1
arr(0) = hObj
*@
// ウィンドウメッセージがくるかファイルが変更されるまで待機
if (observing == FALSE) {
_stat = MsgWaitForMultipleObjects(0, 0, FALSE, INFINITE, QS_ALLINPUT)
}else {
_stat = MsgWaitForMultipleObjects(length(arr), varptr(arr), FALSE, INFINITE, QS_ALLINPUT)
}
// MsgWaitForMultipleObjects が制御を返したら内容に応じた処理を行う
if (observing == TRUE && _stat == WAIT_OBJECT_0) {
// 監視対象ファイルが変更されたのかどうかを確認
CheckIfFileUpdated
FindNextChangeNotification hObj
// もし変更されたのであればあらかじめ指定されたラベルにジャンプ
if (stat == 1) : gosub changed
}
// ウィンドウメッセージはawaitで処理させる
// (DispatchMessageとかはHSP3だと不具合を起こす)
await 0
goto *@b
return
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 監視対象ファイルが変更されたのかを確認する
//
// 戻り値
// -1 : エラー
// 0 : ファイルは変更されていない
// 1 : ファイルは変更された
// 2 : ファイルは削除済み
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#deffunc local CheckIfFileUpdated \
local time
if (length(fileInfo) < 24) : return -1
exist pathFile
if (strsize == -1) : return 2
// 要素を24以上確保しないとクラッシュするので注意!
dim time, 24
fxtget time, pathFile
// タイムスタンプを比較して違っていた = ファイルは変更された
// (かなりの荒業だけど一番手っ取り早い)
if (time(8) != fileInfo(8)) : UpdateFileInfo : return 1
if (time(9) != fileInfo(9)) : UpdateFileInfo : return 1
if (time(10) != fileInfo(10)) : UpdateFileInfo : return 1
if (time(11) != fileInfo(11)) : UpdateFileInfo : return 1
if (time(12) != fileInfo(12)) : UpdateFileInfo : return 1
if (time(13) != fileInfo(13)) : UpdateFileInfo : return 1
if (time(14) != fileInfo(14)) : UpdateFileInfo : return 1
if (time(15) != fileInfo(15)) : UpdateFileInfo : return 1
return 0
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 比較のためにとっておくファイルスタンプを更新
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#deffunc local UpdateFileInfo
exist pathFile
if (strsize == -1) : return -1
// 要素を24以上確保しないとクラッシュするので注意!
dim fileInfo, 24
fxtget fileInfo, pathFile
return 1
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 監視を一時中断する
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#deffunc SuspendObserving
observing = FALSE
return
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 監視を再開する
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#deffunc ResumeObserving
observing = TRUE
return
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 監視を終了する
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#deffunc QuitObserving
if (hObj != 0 || hObj != INVALID_HANDLE_VALUE) : FindCloseChangeNotification hObj
hObj = 0
observing = FALSE
return
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 終了時処理 (自動で呼び出されます)
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#deffunc local TermObj onexit
QuitObserving
return
#global
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
screen 0
dialog "txt", 16
if (stat == 0) : dialog "ファイルが指定されませんでした" : stop
file = refstr
// 監視開始
StartObservingFile file
if (stat == 0) : dialog "監視を開始するための処理に失敗しました" : stop
objsize 100, 30
pos 0, 0
button gosub "監視を一時停止", *suspendob
pos 100, 0
button gosub "監視を再開", *resumeob
pos 200, 0
button gosub "監視対象を変更", *changeob
sdim buf
pos 0, 30
mesbox buf, ginfo_winx, ginfo_winy - 30, 4, 0
idMesbox = stat
gosub *readtext
title "ファイルの変更を監視中です"
// ----------------
// stopEx *hoge
//
// ・普段はHSP3のstopと同じ動作です
// ・ファイルが変更されたときに指定したラベルにジャンプします
// ----------------
stopEx *filechanged
stop // ←ねんのため
// 一時停止
*suspendob
title "監視は一時停止しています"
SuspendObserving
return
// 再開
*resumeob
title "監視は再開しました"
ResumeObserving
return
// 変更
*changeob
dialog "txt", 16
if (stat == 0) : return
file = refstr
title "監視対象が変更されました"
QuitObserving
StartObservingFile file
gosub *readtext
return
// ------------------
// ファイルが変わったとき
// ------------------
*filechanged
title "(" + gettime(4) + ":" + gettime(5) + ":" + gettime(6) + ") ファイルは変更されました"
/* Fall Through */
*readtext
exist file
if (strsize == -1) : dialog "ファイルが見つかりません" : return
sdim buf, strsize
notesel buf
noteload file
objprm idMesbox, buf
return
// ----------------------
// 必ず return !!!!!!!!!!
// ----------------------