マウス位置に存在するエクスプローラ内のアイテムを取得しようと思っております。
エクスプローラの左側のフォルダ一覧(クラス名:SysTreeView32)と右側のファイルとフォルダ名の一覧(クラス名:SysTreeView32)において、そのSysListView32内のマウス位置に存在するアイテムを取得したいのです。
なぜかというと、オリジナルアプリ内のリストビューにFTPサーバのファイル一覧を出力し、リストビューからエクスプローラへの直接ドラッグにより、サーバからローカル\TempにDLして、ドラッグ先にDLしたファイルを移動したいのです。
現状としてはLVM_HITTESTをエクスプローラ内のSysListView32に送っているのですが、こちらが送ったLVHITTESTINFO構造体のXYと、SpyでみたXYの値が違っているのです。結果としてアイテムインデックスを得ることができませんでした。
参考までに、LVM_GETITEMCOUNTはエクスプローラからも取得できました・・・
どのようにしたら、マウス位置のアイテムを取得することができるのでしょうか?
簡単に処理内容を記します。
ドラッグ時に
GetCursorPos:マウス位置を取得
WindowFromPoint:マウス位置のハンドル取得
GetClassName:マウス位置のハンドルよりそのオブジェクトのクラス名を取得
以下は[クラス名=SysListView32]のときのみの処理
ScreenToClient:SysListView32をベースとした座標に変換
SendMessage: TVM_HITTESTと、LVHITTESTINFO構造体を送る
以上です。
本当は・・・
アプリはVBにて製作中なのですが、この手の質問はこちらのCの掲示板の方が回答を望めるかもと思って、こちらに質問させていただきました。Cで答えていただいて結構です。こちらでコンバートしますので。。。
どうぞよろしくお願いいたします。m(__)m
No.3ベストアンサー
- 回答日時:
実際に試した訳じゃないのでうまくいくか分かりませんが、
思い付いた事を....
たしか今回のように別のプロセスにあるウィンドウを調べようとした場合、
LVM_GETITEMCOUNTのようにSendMessageの戻り値で取得するのは
問題ないけど、LVM_HITTESTのように構造体のアドレスを渡す場合には
CreateFileMappingとMapViewOfFileを使って、共有メモリから
割り当てなければならなかったと思います。
// 共有メモリをオープン
HANDLE hFileMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,PAGE_READWRITE, 0, sizeof(LVHITTESTINFO), NULL);
LVHITTESTINFO* pHitTestInfo = (LVHITTESTINFO*)MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
//LVHITTESTINFO構造体への値設定
・・・
//HitTest
SendMessage(hSysWnd, LVM_HITTEST, 0, (LPARAM)pHitTestInfo);
// 共有メモリをクローズ
UnmapViewOfFile(pHitTestInfo);
CloseHandle(hFileMapping);
この回答への補足
現在VBのコードで、HitTestマクロを改良中です。
教えていただいたコードを参考に、このような状況になりました。
わかりずらいかもしれませんが、VBではAPIを呼ぶときに呼びたいAPI関数の宣言を先頭に行います。ですのでポインタで渡さなければならない部分は、きちんとポインタ渡しになっております。
Private Function ListView_HitTest(hwndLV As Long, pInfo As LVHITTESTINFO) As Long
Dim hFileMapping As Long
Dim pHitTestInfo As Long
'共有メモリをオープン
hFileMapping = CreateFileMapping(&HFFFFFFFF, ByVal 0&, PAGE_READWRITE, 0, LenB(pInfo), ByVal 0&)
pHitTestInfo = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0&, 0&, 0&)
'パラメータによって受けた値を、共有メモリ領域にコピー
Call CopyMemory(ByVal pHitTestInfo, pInfo, Len(pInfo))
'ヒットテスト
ListView_HitTest = SendMessage(hwndLV, LVM_HITTEST, 0, ByVal pHitTestInfo)
Call CopyMemory(pInfo, ByVal pHitTestInfo, Len(pInfo))
'それぞれ開放
Call UnmapViewOfFile(pHitTestInfo)
Call CloseHandle(hFileMapping)
End Function
で現状としては、自アプリ中のリストビューからリストビューへのHITTESTは求めている結果を得ることができます。エクスプローラ内のリスビューに送ると、エクスプローラが落ちます。共有メモリの取得失敗?
最初に述べているようにVBで作成中です。使用しているリストビューは、VBのコントロールのリストビューです。スパイで監視したところ、ヒットテストのメッセージがそのVBリストビューコントロールで受けてないように見えます。[LVM_HITTEST]が発生していないのです。もしかして、VB仕様?もしそうなら、みなさんに迷惑をかけてしまってすいません。
もういちど、vbコントロールを使用しないで、API関数のみでリストビューを自作して調査してみます。
それでもだめなら、本当はCでDLLを作成するべきなのでしょうが、「VBでのFTPソフト」を目指しているので、できたらVBオンリーにしたいのです。。。
何はともあれもう一度チャレンジ!
VB仕様かな?と思って、同様の処理をCでも作成して検証しました。
LVM_HITTESTを行うと、やはりメモリの違反が発生します。
海外サイトでも、別プロセスへのHITTESTのサンプルが存在しないのは、根本的に無理だから?
とりあえず、別方法を考えます。
No.5
- 回答日時:
この回答への補足
ありがとうございます。ファイルのコピーはそれで確かにできますね。
しかし、ファイルはローカルには存在していない状態から行う処理をするのです。
FTPソフトなので、ドラッグが始まるたびにDLして、セットしていては無駄な処理が多くなります。ですので、ドラッグが終わったときにドラッグ先のパスを取得し、同名ファイルの有無を取得した後DLするかどうかの問い合わせを行って、その後にローカル¥TempにDLを行います。DLが終了したら、指定のパスにファイルを移動します。
VBのOLEStartDragはドラッグスタート時に発生するイベントです。
VBの内部で行われている処理は、StreamにCF_HDROP(VBのvbCFFiles)型のデータをセットしてしまい、受け側がその型をサポートしている場合は受け側でそれを読み取るという処理を行っていると勝手に思ってますが・・・
現在行いたいのは、ファイルのコピーや移動ではなく、そのドラッグ先のパス取得です。
※現段階の調査結果の報告
1.エクスプローラ内のリスビューに、リストビューメッセージを渡すだけの処理は可能。
2.共有メモリを使用しても、エクスプローラ内のリスビューに、パラメータに値を返すリストビューメッセージを渡すとメモリエラー発生。
2について・・・
エクスプローラはメモリの共有参照不可にしているようです。これはVBでもCでも検証しました。(技術不足?)#3の発言を元に作成したもの以外に、GlobalAllocでメモリ確保して、コールバック関数でDrag処理をさせてもリストビューのアイテムを取得しようとすると、同じ状況になります。
※今後の検証予定
Shellエクステンション系の操作を試みようと思います。
今は、どのエクスプローラが、どのフォルダを開いているかが取得可能になりました。しかしエクスプローラ内リストビューの中にサブフォルダが存在していて、そのサブフォルダの上にドラッグされたときの判断ができないので、その部分の処理を調査したいと思っています。
No.4
- 回答日時:
エキスプローラーへのドロップという事でしたら
OleDrag&Dropを使ったほうが簡単かもしれません。
SAMPLEがあるURLのせておきますので参考にしてください。
参考URL:http://support.microsoft.com/default.aspx?scid=k …
ちょっとプロジェクトが大きめで、デバッグに時間がかかってしまいました。
現在作成中のアプリは、完成したら書物にしようと思っております。
VBでも一応プロセス監視などができるのですが、できるだけ使用したくない気持ちもあるのです。
参考コードをVBにコンバートしきれるかどうかがちょっと不安ですが。。。
もう少しやってみます。
No.2
- 回答日時:
>うーむ、行き詰まってます・・・
別の方法があるかもしれません。
反則ぎみなアドバイスをひとつ。
LHUT32というフリーソフトがエクスプローラへファイルをドロップできます。
これをSpyしてみては?
この回答への補足
LHUTではないですが、類似ソフトでの調査済みなので報告します。
受け側のエクスプローラ内のSysListView32内ではLVM_HITTESTは発生しているのですが、これはエクスプローラ本体が送っているメッセージ、あるいはWINDOWSそのものが送っているメッセージであって、アプリ側からLVM_HITTESTを送っているようには見えませんでした。
知り合いに相談した結果、「おそらくファイル名ではなく、"FileContents"でStreamを渡し・・・云々」というのですが、さっぱりです。
何か手は無いものでしょうか?
No.1
- 回答日時:
この回答への補足
英語が苦手なのでよく理解していませんが・・・
これはListViewのHITTESTですよね。
現在の方法で、ListViewのHITTESTは可能なのですが・・・
どうやらSysListView32へのHITTESTはちょっと違うようです。
フラグをセットする以前に、メッセージで送った構造体の各値と、受けている状態をスパイでデバッグした各値が違うのです。
最初に述べたように英語が苦手なので、意味不明な返答でしたらごめんなさい。
もし、参考URLが解決策を書いているのであれば、どのような内容か教えてください。
お願いいたします。
お礼ではなくさらに補足です。
デスクトップのクリック検出って、グローバルフックを使用しますよね?
だから、もしかしてフックしなくてはいけないのかな?
うーむ、行き詰まってます・・・
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBA 画面上のカーソルに文字数字を入力するコードを教えて下さい 1 2022/10/30 10:31
- AJAX 自作の地図をグーグルマップのようにしたい 3 2022/11/15 11:53
- C言語・C++・C# ディスプレイの解像度とマウスの位置について 2 2023/05/21 19:01
- その他(IT・Webサービス) WEBサイト内のファイルを探す方法は? 1 2022/11/11 16:38
- Windows 10 タスクバー上に表示されたアドレス・ボックス? 1 2023/04/30 17:37
- その他(プログラミング・Web制作) Windowsのマクロプログラムで、こんなことできますか? 3 2022/06/28 14:30
- Visual Basic(VBA) outlook マクロが終了しません。 1 2022/09/02 11:14
- Visual Basic(VBA) 動かなくなってしまった古いVBAを動くようにしたい 8 2022/09/20 13:57
- Excel(エクセル) フォルダ内のワードファイルをPDFに一括変換するVBA 3 2023/06/09 16:51
- 運転免許・教習所 教習所の方向変換について質問です。 左バックで駐車位置にいれる際、最初に教官に言われた通り、いれたい 3 2022/04/03 00:29
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAでActiveDirectoryのユーザ...
-
ListView 項目の選択/選択解除...
-
count(*)で取得した値をJAVAの...
-
VB.NETで DataRow()を利用して...
-
JavaScriptでWindowsログオンID...
-
VBA:小数点以下の数字を取得で...
-
getParameter と getAttribut...
-
データ数をカウントしたいのですが
-
NTPサーバから時刻を取得する
-
jQueryによるajaxで、CGIからの...
-
利用者側のMACアドレスを取得し...
-
コンボボックス表示文字列を取...
-
like演算子内に変数って使えな...
-
整数の桁数が取得できません
-
PCインストール済みのアプリケ...
-
LAN内接続マシン数及びIP、マシ...
-
URIでのページの移動について
-
ディスプレイの表示可能な解像...
-
VBA リストボックス内の値を複...
-
JavaScriptでリンク先やリモー...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAでActiveDirectoryのユーザ...
-
VB.NETで DataRow()を利用して...
-
ListView 項目の選択/選択解除...
-
VBA:小数点以下の数字を取得で...
-
count(*)で取得した値をJAVAの...
-
データ数をカウントしたいのですが
-
like演算子内に変数って使えな...
-
ListViewで複数選択された項目...
-
Flexgridで選択行の列の値を取...
-
エクセルVBAで複数選択できるよ...
-
JavaScriptでWindowsログオンID...
-
利用者側のMACアドレスを取得し...
-
郵便番号検索APIにてget Elemen...
-
COMポート 名前を取得する方法
-
コンボボックス表示文字列を取...
-
VBA Shapesの座標からセル位置...
-
Spreadの選択行の取得について
-
VBScriptで数値にコンマを付け...
-
C言語におけるコンピュータ名・...
-
Excel VBA でログインしてい...
おすすめ情報