喫茶XRAYトップページ

[▲前のスレッド]

[4082] plExplorerFolderTreeにて返信 削除
2010/12/26 (日) 23:53:42 Sara
Mr.XRAYさん こんばんは。

また、やってきました(^^;

plExplorerFolderTreeでグローバルフックを使わずにOnMouseEnterを
起こすことに成功しました。(って言うほどのものでもないですが)

どのようにしたかといいますと・・・

以下のように、MessageLoop内で強引にイベントを発生させたのです。

procedure TplExplorerFolderTreeThread.MessageLoop;
var
  Amsg : Msg;
  APos : TPoint;
  cmpFind : TWinControl;
begin
  while True do begin
    if GetMessage(AMsg, 0, 0, 0) = False then begin
      PostQuitMessage(0);
      break;
    end;
    case AMsg.message of
      WM_MOUSEMOVE:begin
        GetCursorPos(APos);
        cmpFind := FindVCLWindow(APos);
        if (cmpFind = FWinControl) then begin
          if not FWinControl.FMouseEnterFlg then begin
             FWinControl.FMouseEnterFlg := True;
             FWinControl.DoMouseEnter;
          end
        end
        else begin
          if FWinControl.FMouseEnterFlg then begin
             FWinControl.FMouseEnterFlg := False;
             FWinControl.DoMouseLeave;
          end;
        end;
      end;
    end;
    TranslateMessage(Amsg);
    DispatchMessage(Amsg);
  end;
end;

そこで、実際のMouseEnterイベント内で、plExplorerFolderTreeにSetFocusを
実行すると、何も起きない・・・で調べると、実際のFolderTreeはFEXPLとなって
いるので、こちらにもSetFocusを追加したのは良いのですが、
  IUnknown_GetWindow(m_pNameSpaceTreeControl, FHandle);
  Windows.SetFocus(FHandle);
とするしかなく、実際にフォーカスはわたるのですが、MouseLeave時に
他のコンポーネントで例えば ListView1.SetFocus としても、フォーカスが
わたらないんです・・・(^^;

かといって、全コンポーネントでWindows.SetFocusを利用すると、Zオーダーが
狂うのですよね・・・(^^;

なにかよい方法ありませんでしょうか?m(_ _)m

[4083] Re:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 10:01:21 Mr.XRAY
▼ Saraさん.こんにちは.

> plExplorerFolderTreeでグローバルフックを使わずにOnMouseEnterを
> 起こすことに成功しました。(って言うほどのものでもないですが)


おおっ! やってしまいましたね.すごい.

> 他のコンポーネントで例えば ListView1.SetFocus としても、フォーカスが
> わたらないんです・・・(^^;


ムムム...

> なにかよい方法ありませんでしょうか?m(_ _)m

ありません.
何かないですかね.う〜ん.
エクスプローラのオブジェクトが,Delphiのようなコントロールだったら
簡単なんですけどね.


[4084] Re:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 13:06:41 Mr.XRAY
▼ Saraさんち,どうも

> 実際のFolderTreeはFEXPLとなっているので、

FEXPLを使用しないコードにしてみました.
前にも書いたのですが,Delphiではインタフェースの大部分を面倒みて
くれます.参考にしたサイトのC++のコードを,ほとんどそのままので移植
したわけですが,これは,ちょうどHalbow資料館の

http://mrxray.on.coocan.jp/Halbow/Chap01.html

のようになっているわけです.そこで,

 TplExplorerFolderTree = class(TCustomPanel,
                               INameSpaceTreeControlCustomDraw)

ように変更しました.つまり,インターフェイス部分を
 TplExplorerFolderTreeの直接のメンバーにしたわけです.
これで,少しはメッセージ処理がしやすくなるのではないかと思います.

今,別の解決方法も考えています.
しばらくお待ちくださいませ.
published部と,Create部の重要な変更はないので,再構築,ビルドは
必要ありません.単に置き換えてください.

■添付ファイル plexplorerfolder.zip

[4085] Re2:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 15:14:45 Mr.XRAY
▼ Saraさん,どうも

> 今,別の解決方法も考えています.

エクスプローラのツリーのハンドルで操作することを考えました.
このハンドル不思議です.このハンドルでウィンドウプロシージャーでの
操作を考えたのですが,確かに設定はできました.
しかし,メッセージを補足することができません.

ところが,このハンドルで,位置とサイズは取得,更新できます.
(実際にコンポ内で,位置とサイズはWndProcで再設定しています)

前にエクスプローラのサンプル([945])での記憶があったので,
メッセージ処理は,フックしかないと思っていたのですが,
考えてみれば,このエクスプローラのオブジェクト,同じプロセス内で
動作しているんですよね.

そこで,このハンドルをプロパティにして,以下の手順で検出すると
いうのはどうでしょう.

(1)このコンポを配置しているフォームに TApplicationEventsを配置
    TApplicationEventsは[Addtioanl]タブにある

(2) TApplicationEventsのOnMessageイベントを作成

(3) このイベントを以下のようなコードにする

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
var
  APos  : TPoint;
  ARect : TRect;
begin
  if Msg.message = WM_MOUSEMOVE then begin
    GetCursorPos(APos);
    GetWindowRect(plExplorerFolderTree1.hwndTree, ARect);
    if PtInRect(ARect, APos) then begin
      //ここに処理を書く
    end;
  end;
end;

動作確認は,Windows 7 U64 + Delphi 2010(UP5) + IE8

hwndTreeをpublicなプロパティにしたコード
■添付ファイル 4085_plexplorerfolder.zip

[4086] Re3:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 17:33:24 Mr.XRAY
スレッドでの処理ですが,修正したplExplorerFolderTree.pasであれば,

procedure TplExplorerFolderTreeThread.MessageLoop;
var
  Amsg : Msg;
begin
  while True do begin
    if GetMessage(AMsg, 0, 0, 0) = False then begin
      PostQuitMessage(0);
      break;
    end;
    if Amsg.message = WM_MOUSEMOVE then begin
      //処理
    end else begin
      TranslateMessage(Amsg);
      DispatchMessage(Amsg);
    end;
  end;
end;

こんな感じですね.

      TranslateMessage(Amsg);
      DispatchMessage(Amsg);

はキー操作関係の場合は,実行しないと,表示も正常に行われないし,
Itemの名前変更もできなくなります.
マウスメッセージの場合は,この2行は実行する必要は特にありません.


[4087] Re4:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 17:49:53 Mr.XRAY
ごめんなさい.

> マウスメッセージの場合は,この2行は実行する必要は特にありません.

うそです.
クリック等はは処理しないとダメです.ハイ!!
当然?!


[4088] Re3:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 18:43:37 Mr.XRAY
> 操作を考えたのですが,確かに設定はできました.
> しかし,メッセージを補足することができません.


考えてみれば当たり前ですわ.
これ,エクスプローラのオブジェクトですから,クラス名は,
SysTreeView32ですね.ハハハッ
コンポ内で取得しているウィンドウハンドルというのは,このSysTreeView32を
表示するための,操作するためのインターフェイスなんですね.

なんか疲れているなー.うん.


[4092] Re3:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 20:16:37 Sara
▼ Mr.XRAYさん

> hwndTreeをpublicなプロパティにしたコード

これから、検証してみます。(^^) 御苦労様です。

[4093] Re4:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 20:23:19 Mr.XRAY
▼ Saraさん,どうも

> これから、検証してみます。(^^) 御苦労様です。

個人的には,同じプロセス内でのメッセージ処理なので,例の
スレッドのコードではなく,OnMessage等を使用する方がいいと思っています.
コンポ内で処理する場合もです.

http://mrxray.on.coocan.jp/Halbow/VCL07.html
こなんところも参考になるかと思います.


[4094] Re5:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 22:26:08 Sara
▼ Mr.XRAYさん こんばんは

> 個人的には,同じプロセス内でのメッセージ処理なので,例の
> スレッドのコードではなく,OnMessage等を使用する方がいいと思っています.
> コンポ内で処理する場合もです.


procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;

すみません。これにメッセージが返ってきませんが・・・

どこか、記述漏れがありますかね・・・(^^;
こちらで修正したものにソースを見ながら追記したので・・・

それ以外は、正常動作をしています。


[4095] Re6:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 22:41:48 Mr.XRAY
▼ Saraさん

> procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
>
> すみません。これにメッセージが返ってきませんが・・・


えっ?
何にもですか? それは,ちょっと変ですね.
アプリケーションのメッセージですから.すごい量のメッセージが飛んで
くるハズなんですが.


[4096] Re6:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 22:48:34 Sara
▼ Mr.XRAYさん こんばんは

> procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
>
> すみません。これにメッセージが返ってきませんが・・・


ちなみに、
procedure TplExplorerFolderTreeThread.MessageLoop;

    DispatchMessage(Amsg);
    Application.ProcessMessages;
とすると、メッセージが返ってきます・・・終了できなくなりますが・・・(^^;

あと、面白いことに、WM_MOUSEMOVEだけ検出してみると、plExplorerFolderTree
のアイテム上でしか、WM_MOUSEMOVEが検出されないようです。
(背景の白い部分や、他のコンポーネント上は未検出)



[4097] Re7:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 22:54:05 Mr.XRAY
▼ Saraさん

> > procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
> >
> > すみません。これにメッセージが返ってきませんが・・・


今ちょっとやってみました.
はは〜ん,おそらく,こういうことではないかと思います.
このApplicationのOnMessageはコードでも作成できますが,
TApplicationコンポーネントというのがあります.これを使用してください.
この方が簡単です.[4085]参照

とりあえず,ここの部分だけ


[4098] Re8:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 23:01:02 Mr.XRAY
ちょっと待ってください.
今,やったら,フォルダツリーからのメッセージが来ません.
表示前なら来るのですが.


[4099] Re9:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 23:12:17 Sara
▼ Mr.XRAYさん
> ちょっと待ってください.
> 今,やったら,フォルダツリーからのメッセージが来ません.
> 表示前なら来るのですが.


そうなんですよね・・・

で、ちょっと試しに

//  if FThread = nil then begin
//    FThread := TplExplorerFolderTreeThread.Create;
//  end;

としてみたんです・・・すると・・・メッセージきますね・・・
処理も正常に動いているっぽいんですが・・・
(フォルダ追加、削除にちゃんと追従しますし)
このスレッドっていったい・・・(^^;

[4100] Re10:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 23:16:35 Mr.XRAY
▼ Saraさん

> (フォルダ追加、削除にちゃんと追従しますし)
> このスレッドっていったい・・・(^^;


ファイルかフォルダの名前を変更してみてください.
[F2]でも,マウスを静かにクリックでも.


[4101] Re11:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 23:24:34 Mr.XRAY
▼ Saraさん

やっぱりローカルフックでないと無理ですね.

7−2 ローカルフック : WH_GETMESSAGE
http://mrxray.on.coocan.jp/Halbow/VCL07.html

のList 3

でやってみました.OKです.
これが一番簡単でしょう.




[4102] Re12:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 23:27:16 Mr.XRAY
一応コードです.

var
  Hook: HHOOK;

function GetMsgProc(code:integer;wparam:WPARAM;lparam:LPARAM):LRESULT;stdcall;
var
  Msg: PMsg;
begin
  if (code < 0) then begin
    result := CallNextHookEx(Hook,code,wparam,lparam);
    exit;
  end;

  if (code = HC_ACTION) then begin
    Msg := PMsg(lparam);
    case Msg^.message of
      WM_MOUSEMOVE:begin
       if wparam = PM_REMOVE then
          //処理
      end;
    end;
  end;

  result := CallNextHookEx(Hook,code,wparam,lparam);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  Hook := SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,0,GetCurrentThreadID);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnHookWindowsHookEx(Hook);
end;



[4103] Re11:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 23:33:11 Sara
▼ Mr.XRAYさん
> ▼ Saraさん
>
> > (フォルダ追加、削除にちゃんと追従しますし)
> > このスレッドっていったい・・・(^^;
>
> ファイルかフォルダの名前を変更してみてください.
> [F2]でも,マウスを静かにクリックでも.


なるほど・・・F2だと、フォーカスに関係なく別な処理が割り当てられていると
そちらにいってしまいますね・・・クリックならなんとか変更可能ですが、
矢印キーが使えないですね・・・マウスと併用なら何とか変更可ですが・・・
使いづらい・・・(^^;

しかし、このスレッドがあると、F2がフォーカスに関係なくplExplorerFolderTreeに
持って行かれますね・・・
っていうか キーボードー系のイベントが全て持って行かれる?・・・(^^;

これは、困った・・・

[4104] Re12:plExplorerFolderTreeにて返信 削除
2010/12/27 (月) 23:43:12 Mr.XRAY
▼ Saraさん

> しかし、このスレッドがあると、F2がフォーカスに関係なくplExplorerFolderTreeに
> 持って行かれますね・・・
> っていうか キーボードー系のイベントが全て持って行かれる?・・・(^^;
>
> これは、困った・・・


「弊社としてましては,この現象を認識しています.
これは,エクスプローラーのオブジェクトを正常に動作させるための仕様
と認識しています.
お客様は,仕様の範囲内でのご利用をお勧めいたします」

という感じの文章を,とあるサイトでよく見かけます.
フォルダビュー(ファイルリスト)だと,TranslateAcceleratorという関数が
あり,この現象をある程度回避できるんですけどね.


[4105] Re13:plExplorerFolderTreeにて返信 削除
2010/12/28 (火) 00:34:37 Sara
▼ Mr.XRAYさん

> という感じの文章を,とあるサイトでよく見かけます.
> フォルダビュー(ファイルリスト)だと,TranslateAcceleratorという関数が
> あり,この現象をある程度回避できるんですけどね.


なるほど、参考になります・・・

なにかできないか、調べてみますm(_ _)m

[4106] マウスだけの操作たったらマウスフック返信 削除
2010/12/28 (火) 13:15:49 Mr.XRAY
▼ Saraさん

マウスの動作だけの操作が対象であれば,
マウスの,ローカルフックでいいのではないかと思います.


[4109] Re14:plExplorerFolderTreeにて返信 削除
2010/12/28 (火) 20:24:50 Sara
▼ Mr.XRAYさん
 
> > フォルダビュー(ファイルリスト)だと,TranslateAcceleratorという関数が
> > あり,この現象をある程度回避できるんですけどね.

 
> なにかできないか、調べてみますm(_ _)m

というわけで、強引な方法で解決策を作ってみました・・・(^^;
この方法で問題ないかどうかは、まだ何とも言えませんが、
今のところ、問題なく動いているようです。(^^;

で、具体的に何をしたかですが・・・(あまり言いたくないかも・・・)

plExplorerFolderTreeにマウスカーソルが入った時に、FThreadをCreateして
マウスが出た時に、FThreadをTerminateしましたとさ・・・

問題がでなければ、この方法で進んでみます。(^^;;

[4110] Re15:plExplorerFolderTreeにて返信 削除
2010/12/28 (火) 23:59:30 Mr.XRAY
▼ Saraさん

> plExplorerFolderTreeにマウスカーソルが入った時に、FThreadをCreateして
> マウスが出た時に、FThreadをTerminateしましたとさ・・・


なるほど....
 
> 問題がでなければ、この方法で進んでみます。(^^;;

了解しました.
では,がんばってくたさい (^^)


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