喫茶XRAYトップページ

[スレッド全体
]

[4136] plFolderWatcherについて返信 削除
2011/1/5 (水) 21:38:57 たてぐや
 plFolderWatcherを、Directoryを別々にして複数動かしたいと思い、作成し
ました。フォーム上にplFolderWatcherを必要数だけ置くと、べたべたなソース
になってしまうので、以下のようにしました。長くて済みません。
var
  FolderWatch : array[0..15] of TplFolderWatcher;

procedure TFrmSet.FormCreate(Sender: TObject);
{=====================================================================
初期化
======================================================================}
var
  p : integer;
  Options : TplFolderEventOptions;
begin
  Options := [];
  Options := Options + [evt_RENAMEITEM];
  Options := Options + [evt_CREATE];
  Options := Options + [evt_DELETE];
  Options := Options + [evt_MKDIR];
  Options := Options + [evt_RMDIR];
  for p := 0 to 15 do begin
    inCopy[p] := false;
    FolderWatch[p] := tplFolderWatcher.Create(Application);
    FolderWatch[p].Tag := p;
    FolderWatch[p].OnChange := plFolderWatcher1Change;
    FolderWatch[p].StopWatch;
    FolderWatch[p].Options := Options;
    uList[p] := Tstringlist.Create;
  end;

 これで15個のplFolderWatcherがCreateされるはずです。そしてイベントが
発生すると、どのplFolderWatcherでイベントが発生してもplFolder1Changeが
呼ばれます。そこで

procedure TFrmSet.plFolderWatcher1Change(Sender: TObject; AEvent: Integer;
  BeforeFullPath, BeforeFileName, AfterFullPath, AfterFileName: String);
var
  ACaption : String;
  p : integer;
begin
    :
end;

として、個々のplFolderWatcherのTag値で何番目のplFolderWatcherから呼ば
れたか切り分けようとしています。ところが、実際はどのplFolderWatcher.Di
rectoryでイベントを起こしても、TComponent(Sender).Tagの値は有効になっ
ているplFolderWatcher配列の最後の番号しか返ってきません。
 たとえば、FolderWatch[0].DirectoryがD:\AAA、FolderWatch[0].Directory
がD:\BBBだとして、この二つがWatchStartしている場合、D:\AAAでもD:\BBBで
も帰ってくる値(Tagに設定したintreger)は'1'しか戻ってきません。
 もしかしてplFolderWatcherは複数使えないのでしょうか?

[4138] Re:plFolderWatcherについて返信 削除
2011/1/5 (水) 21:56:17 Mr.XRAY
▼ たてぐやさん

>  もしかしてplFolderWatcherは複数使えないのでしょうか?

あれっ?
う〜ん.テストしてみます.


[4139] Re2:plFolderWatcherについて返信 削除
2011/1/5 (水) 22:01:10 たてぐや
▼ Mr.XRAYさん

 一つ書き忘れていました。

var
  ACaption : String;
  p : integer;
begin
  p := TComponent(Sender).Tag  //ここでpに0〜15が入るはず
  Showmessage(IntToStr(p));
end;

 それとWatchStartは別の場所で行っています。

> あれっ?
> う〜ん.テストしてみます.


 いつもいつも済みません。

[4141] Re3:plFolderWatcherについて返信 削除
2011/1/6 (木) 21:49:57 Sara
▼ たてぐやさん Mr.XRAYさん こんばんは

以下のようにすると、希望どおり動くようです(テスト不足ですが・・・)

  TplFolderWatcher = class(TComponent)
  private
    { Private 宣言 }

    OwnerWindowProc   : TWndMethod;
    procedure WndProc(var msg: TMessage);

      ・
      ・


function TplFolderWatcher.StartWatch(Handle: HWND): Boolean;
      ・
      ・
begin
      ・
      ・
      ・
      ・
  //メッセージはオーナーが受取るので,オーナーのウィンドウプロシージャーを書換え
//  OwnerHandle := Handle;
//  if OwnerHandle <> 0 then begin
{
    OriginOwnerWndProc := Pointer(SetWindowLong(OwnerHandle,
                                  GWL_WNDPROC,
                                  LongInt(Addr(OwnerWndProc))));
}

   OwnerWindowProc := (Owner as TWinControl).WindowProc;
   (Owner as TWinControl).WindowProc := WndProc;

    //監視開始
    uIID := SHChangeNotifyRegister1(Handle,
                                   FSources,
                                   fEvents,
                                   WM_PLCHANGENOTIFY,
                                   1,
                                   Entry);
    Result := uIID <> 0;
//  end;

  CoTaskMemFree(PItemID);
end;


procedure TplFolderWatcher.StopWatch;
begin
  //オーナのウィンドウプロシージャーを元に戻しておく
  if OriginOwnerWndProc <> nil then begin
     (Owner as TWinControl).WindowProc := OwnerWindowProc;
    OriginOwnerWndProc := nil;
  end;
  WM_PLCHANGENOTIFY := 0;

  if uIID <> 0 then SHChangeNotifyDeregister1(uIID);
  Malloc := nil;
end;


procedure TplFolderWatcher.WndProc(var msg: TMessage);
type
  TPItemIDListArray = array of PItemIDList;
  PPItemIDListArray  = TPItemIDListArray;

var
  PItemIDBefore : PItemIDList;
  PItemIDAfter  : PItemIDList;
  PathBefore    : String;
  PathAfter     : String;
  Event         : Integer;
begin
  if msg.Msg = WM_PLCHANGENOTIFY then begin

    //メッセージの種類
    Event := msg.lParam;

    //変更前のファイルフォルダの項目識子(デスクトップ基準)
    //PItemIDs[0]には処理したファイルの名前が,[1]は操作の種類によって異なる
    PItemIDBefore := ILClone(TPItemIDListArray(msg.WParam)[0]);

    //変更後のファイルフォルダの項目識別子(デスクトップ基準)
    PItemIDAfter := ILClone(TPItemIDListArray(msg.WParam)[1]);

    //それらの項目識別子をフルパスに変換
    PathBefore := GetDispNameFromPItemID(sfDesktop, PItemIDBefore, SHGDN_FORPARSING);
    PathAfter  := GetDispNameFromPItemID(sfDesktop, PItemIDAfter,  SHGDN_FORPARSING);


    //何故か、関係ないはずのFolderWatchも通るのでとりあえず、判定(^^;
    //Directoryの指定内容によっては、これでは問題があるので変更してください。
    if pos(Self.Directory,PathBefore) > 0 then begin

      if Assigned(FOnChange) then begin
        FOnChange(Self,
                                Event,
                                PathBefore,
                                ExtractFileName(PathBefore),
                                PathAfter,
                                ExtractFileName(PathAfter));
      end;
    end;

    CoTaskMemFree (PItemIDBefore);
    CoTaskMemFree (PItemIDAfter);
  end;
  OwnerWindowProc(Msg);

end;


[4142] Re4:plFolderWatcherについて返信 削除
2011/1/6 (木) 22:00:54 たてぐや
▼ Saraさん

 こんなにコードを書いてテストしていただき、感謝に堪えません。今日はちょっと
時間が取れませんので週末に試してみます。ありがとうございました。

[4143] Re5:plFolderWatcherについて返信 削除
2011/1/7 (金) 00:05:22 Mr.XRAY
▼ たてぐやさん
▼ Saraさん

おおっ,Saraさん,サンクスです.
持つべきは....
先ほど,カラオケ大会から戻ってきました.

>    //何故か、関係ないはずのFolderWatchも通るのでとりあえず、判定(^^;
>    //Directoryの指定内容によっては、これでは問題があるので変更してください。


そうなんですよね.フォルダ内のイベントを検出するAPIなんですが,
結構使い方は難しいですね.
といって,ネット上でよく見かけるFILE...なんとかだと検出できない
操作もありますし.

>   OwnerWindowProc := (Owner as TWinControl).WindowProc;
>   (Owner as TWinControl).WindowProc := WndProc;


そうか.WndProcを... なるほど.


[4145] Re6:plFolderWatcherについて返信 削除
2011/1/7 (金) 16:22:49 Sara
▼ Mr.XRAYさん ▼ たてぐやさん

あれ、OriginOwnerWndProc と OwnerWindowProcが間違ってますね・・・(^^;

procedure TplFolderWatcher.StopWatch;
begin
  //オーナのウィンドウプロシージャーを元に戻しておく
//  if OriginOwnerWndProc <> nil then begin
  if OwnerWindowProc <> nil then begin
     (Owner as TWinControl).WindowProc := OwnerWindowProc;
      OwnerWindowProc := nil;
//    OriginOwnerWndProc := nil;
  end;
  WM_PLCHANGENOTIFY := 0;

  if uIID <> 0 then SHChangeNotifyDeregister1(uIID);
  Malloc := nil;
end;

と、しておいてください。(^^;

[4148] Re7:plFolderWatcherについて返信 削除
2011/1/7 (金) 22:34:57 たてぐや
▼ Saraさん

> と、しておいてください。(^^;

 修正してコンパイルしたのですが、
    //監視開始
    uIID := SHChangeNotifyRegister1(Handle,
                                   FSources,
                                   fEvents,
                                   WM_PLCHANGENOTIFY,
                                   1,
                                   Entry);

 「SHChangeNotifyRegister1」が未定義となってしまいました。

[4149] Re8:plFolderWatcherについて返信 削除
2011/1/7 (金) 23:34:35 Mr.XRAY
▼ たてぐやさん

>  「SHChangeNotifyRegister1」が未定義となってしまいました。

あれっ? ちょっと待ってください.


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82