喫茶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

[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行は実行する必要は特にありません.

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


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