C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]: 他アプリに対して、ファイルパスをドロップ


(過去ログ 32 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■15727 / inTopicNo.1)  他アプリに対して、ファイルパスをドロップ
  
□投稿者/ 熊谷隆史 (12回)-(2008/03/19(Wed) 14:32:11)

分類:[C/C++] 

こんにちは。
IDropTargetを実装した他アプリに対して、
ファイルパスをドロップさせようとしています。

DLL側のIDropTarget::Dropの呼び出しで
IEが落ちるので
この部分に問題ありと見ているのですが、
何が原因なのかが分かりません。


直前のIShellFolder::GetUIObjectOfは
大丈夫だとは思うのですが。

どなたかお分かりになられる方、
宜しくお願いします。

環境

Vista  
Visual C++ 2008 Express Editions 
Excel2007(VBA) 

テストなのでIEを対象にしています。


--- drop.cpp ---
	#include <windows.h> 
	#include <oleidl.h> 
	#include <objidl.h> 
	#include <shobjidl.h>
	#include <shlobj.h>
	#include <string.h>
	
	#pragma data_seg("shared")
	HHOOK g_hHook = NULL;
	#pragma data_seg()

	#pragma comment( lib, "shell32.lib" )
	#pragma comment(linker, "/section:shared,rws")

	HINSTANCE g_hDLL;

	BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
	{
	    switch (ul_reason_for_call){
		case DLL_PROCESS_ATTACH:
		    g_hDLL = hModule;
		    break;
		case DLL_THREAD_ATTACH:
		    break;
		case DLL_THREAD_DETACH:
		    break;
		case DLL_PROCESS_DETACH:
		    break;
	    }
	    return TRUE;
	}


	LRESULT CALLBACK DropProc(int nCode, WPARAM wParam, LPARAM lParam)
	{

		MSG *pmsg = (MSG*)lParam; 

	if(nCode == HC_ACTION && pmsg->message == WM_NULL)
	 {
	         
		::UnhookWindowsHookEx(g_hHook);
		::CoInitialize( NULL ); 
		
		IDropTarget *pDrop = (IDropTarget *) ::GetProp(pmsg->hwnd, L"OleDropTargetInterface");

		pDrop->AddRef();

		IShellFolder* pDesktop_Shell;
		IShellFolder* pFolder_Shell;
		IDataObject* pData;
		
	    ITEMIDLIST *Folder_pid1;
	    ITEMIDLIST *File_pid1;
	                        
		::SHGetDesktopFolder(&pDesktop_Shell);
		
		pDesktop_Shell->ParseDisplayName(NULL,NULL, L"C:\\Temp", NULL, &Folder_pid1, NULL); 
					
		pDesktop_Shell->BindToObject(Folder_pid1, NULL, IID_IShellFolder, reinterpret_cast<void **>(&pFolder_Shell)); 

		pDesktop_Shell->Release();

		pFolder_Shell->ParseDisplayName( NULL, NULL, L"Google.html", NULL,  &File_pid1,  NULL); 

		HRESULT hr = pFolder_Shell->GetUIObjectOf( NULL, 1, const_cast<LPCITEMIDLIST *>(&File_pid1), IID_IDataObject, NULL, reinterpret_cast<void **>(&pData)); 

		// 戻り値確認。
		::SetProp (pmsg->hwnd,L"pDrop",(HANDLE)hr);

		::ILFree ( Folder_pid1 );
		::ILFree ( File_pid1 );
		pFolder_Shell->Release();

		POINTL pt;		
		pt.x = 10;
		pt.y = 10;

		pDrop->Drop (pData, MK_LBUTTON, pt, (DWORD *)DROPEFFECT_LINK  );
				
		pDrop->Release();
		
		::CoUninitialize(); 
	 
	 }
	 return ::CallNextHookEx(g_hHook, nCode, wParam, lParam);
	} 
	 

	BOOL WINAPI hookINST(HWND hWnd)
	{
		BOOL foo = true;

		g_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)DropProc, g_hDLL, ::GetWindowThreadProcessId( hWnd, NULL));
	                                         
	    if(g_hHook == NULL)
		{
			foo = false;
		}else{
			::PostMessage(hWnd, WM_NULL, 0, 0);
		}
		return foo;
	}

--- drop.def ---
LIBRARY drop
EXPORTS 
 hookINST @1


--- VBA ---
Option Explicit

Private Declare Function RemoveProp Lib "user32" Alias "RemovePropA" _
        (ByVal hWnd As Long, ByVal lpString As String) As Long
Private Declare Function hookINST Lib "drop" (ByVal hWnd As Long) As Long

Sub hoge()
    Dim objIE As Object
    Dim lngResult As Long
    Dim hWndIE As Long

    ChDrive ThisWorkbook.Path
    ChDir ThisWorkbook.Path

    Set objIE = CreateObject("InternetExplorer.application")
    objIE.Visible = True
    hWndIE = objIE.hWnd

    If hookINST(hWndIE) Then
        lngResult = RemoveProp(hWndIE, "pDrop")
        If lngResult = 0 Then Exit Sub
    End If

End Sub

引用返信 編集キー/
■15728 / inTopicNo.2)  Re[1]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ シャノン (331回)-(2008/03/19(Wed) 14:54:07)
No15727 (熊谷隆史 さん) に返信
> DLL側のIDropTarget::Dropの呼び出しで
> IEが落ちるので
> この部分に問題ありと見ているのですが、
> 何が原因なのかが分かりません。

DROPEFFECT_LINK は単なる整数値ですから、DWORD * にキャストしちゃダメでしょう。
IE はアドレス 0x00000004 に対して書き込もうとしますよ。

で、前スレ
http://bbs.wankuma.com/index.cgi?mode=al2&namber=15616
は結局、何も解決されないまま閉じられてしまったわけですが、もう一度言いますよ/聞きますよ。

GetProp で OleDropTargetInterface を取得するのはやめたほうがいいでしょう。
仮にそれでうまいこと IDropTarget が取得できたとしても、別のバージョンの Windows でも可能である保証はありません。

あと、IDropTarget::Drop を直接呼び出してうまく動く保証もゼロです。

そもそも、何がしたいんですか?
「IEにHTMLファイルを開かせたい」なら、他に方法があるでしょう。
「特定のアプリにファイルを開かせたい」でも、そのアプリが特定できれば、別の方法があるかもしれません。
「IDropTargetを実装したアプリ一般にファイルを開かせたい」は無理です。IDropTargetを実装するアプリがファイルを受け入れるとは限りません。
「とにかくドロップしたい。結果は問わない」なら別かもしれませんが、そんなことに意味があるとは思えません。
引用返信 編集キー/
■15730 / inTopicNo.3)  Re[2]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ 熊谷隆史 (13回)-(2008/03/19(Wed) 17:20:11)
No15728 (シャノン さん) に返信
> DROPEFFECT_LINK は単なる整数値ですから、DWORD * にキャストしちゃダメでしょう。
> IE はアドレス 0x00000004 に対して書き込もうとしますよ。

コンパイル時に

'IDropTarget::Drop' :
4 番目の引数を 'int' から
'DWORD *' に変換できません。

と出るので

pDrop->Drop (pData, MK_LBUTTON, pt, (DWORD *)DROPEFFECT_LINK );

としています。


> 仮にそれでうまいこと IDropTarget が取得できたとしても、別のバージョンの Windows でも可能である保証はありません。

他のバージョンのWindowsで動作しなくとも
構いません。



> 「IEにHTMLファイルを開かせたい」なら、他に方法があるでしょう。
> 「特定のアプリにファイルを開かせたい」でも、そのアプリが特定できれば、別の方法があるかもしれません。

上でも書きましたが後者です。

> 「IDropTargetを実装したアプリ一般にファイルを開かせたい」は無理です。IDropTargetを実装するアプリがファイルを受け入れるとは限りません。

手動で可能ならコードでも可能では
と思っています。


シャノンさん、お手数掛けました。
閉じます。
解決済み
引用返信 編集キー/
■15731 / inTopicNo.4)  Re[3]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ シャノン (332回)-(2008/03/19(Wed) 17:42:58)
No15730 (熊谷隆史 さん) に返信

解決したようですので(とてもそうは見えないが)以降関わらないことにします。
# 疲れた。
解決済み
引用返信 編集キー/
■15732 / inTopicNo.5)  Re[4]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ ぽぴ王子 (332回)-(2008/03/19(Wed) 17:51:14)
ぽぴ王子 さんの Web サイト
質問が閉じちゃってる上に、C++ にはぜんぜん明るくない私ですが。
もちろん COM もさっぱりさっぱりです。

■No15730 (熊谷隆史 さん) に返信

> ■No15728 (シャノン さん) に返信
>>DROPEFFECT_LINK は単なる整数値ですから、DWORD * にキャストしちゃダメでしょう。
>>IE はアドレス 0x00000004 に対して書き込もうとしますよ。
> 
> コンパイル時に
> 
> 'IDropTarget::Drop' : 
> 4 番目の引数を 'int' から 
> 'DWORD *' に変換できません。
> 
> と出るので
> 
> 		pDrop->Drop (pData, MK_LBUTTON, pt, (DWORD *)DROPEFFECT_LINK  );
> 
> としています。

これは…
ちょっと調べてみたけど、IDropTarget::Drop はドロップされたときに呼ばれる
関数みたいですね。
ってことは、ドロップを擬似的に再現したいってこと?(流れを読むとそんな感じ
みたいなのでてきとーに言ってます)。

これまたちょっと調べたところによれば、Drop はドロップされた側が *pdwEffect
に DROPEFFECT_ほにゃらら を入れるものみたいですね。
じゃあこっちから指定すべきは DROPEFFECT_* じゃなくて、それを入れてもらうための
エリアなのじゃないかしらん?と思ったり。
(この辺明るくないのでてきとーに言ってます。間違ってたらごめんなさい)

> 'IDropTarget::Drop' : 
> 4 番目の引数を 'int' から 
> 'DWORD *' に変換できません。

と警告されたから

> 		pDrop->Drop (pData, MK_LBUTTON, pt, (DWORD *)DROPEFFECT_LINK  );

と書いちゃう、ってところは僕もちょっと心配というか大丈夫かな?って思います。
ちゃんと理解して書かれているのかな?と。

だからこそシャノンさんがいろいろ警鐘を鳴らしてくれているのじゃないかと
思ったりしています。
COM だから、C++ だから、の前にもうちょっと高めのハードルがありそうですね。

自分が言うのもアレですが、もうちょい知識を深めてみてからチャレンジしてみては
どうでしょうか。

解決済み
引用返信 編集キー/
■15736 / inTopicNo.6)  Re[5]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ 熊谷隆史 (14回)-(2008/03/19(Wed) 18:21:23)
No15732 (ぽぴ王子 さん) に返信
ぽぴ王子さん、ありがとうございます。
この様に言ってくださる方がいらして、
救われました。

> ちょっと調べてみたけど、IDropTarget::Drop はドロップされたときに呼ばれる
> 関数みたいですね。
> ってことは、ドロップを擬似的に再現したいってこと?(流れを読むとそんな感じ
> みたいなのでてきとーに言ってます)。

そうです。


> 自分が言うのもアレですが、もうちょい知識を深めてみてからチャレンジしてみては
> どうでしょうか。

基本から勉強し直したいと思います(道が開けそうです)。
ありがとうございました。

解決済み
引用返信 編集キー/
■15737 / inTopicNo.7)  Re[5]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ やじゅ (258回)-(2008/03/19(Wed) 18:31:21)
> ■No15730 (熊谷隆史 さん) に返信

目的というか、やりたいことは↓のようなことですか?

 手動でドロップできるアプリケーションに対して
 なんらかの方法でファイルを選択するなどすると
 ドロップされたかのように選択したファイルが
 アプリケーション側で開く。

引用返信 編集キー/
■15751 / inTopicNo.8)  Re[6]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ 熊谷隆史 (15回)-(2008/03/20(Thu) 10:37:03)
> 		pDrop->Drop (pData, MK_LBUTTON, pt, (DWORD *)DROPEFFECT_LINK  );

		↓
		DWORD *pdwEffect = NULL;

		pDrop->Drop (pData, MK_LBUTTON, pt, pdwEffect );

の様に変更して、対象のアプリが落ちることは
ありませんでしたが、無反応です
 (まだ、何か考え違いをしてるのでしょうか)。


> DROPEFFECT_LINK は単なる整数値ですから、DWORD * にキャストしちゃダメでしょう。
> IE はアドレス 0x00000004 に対して書き込もうとしますよ。

こちらのレスの意味が分かってませんでした。

シャノンさんのご気分を不快にさせてしまって
慎んでお詫び申し上げます。申し訳ありませんでした。
シャノンさんのこれからのご活躍を期待しております。


>  手動でドロップできるアプリケーションに対して
>  なんらかの方法でファイルを選択するなどすると
>  ドロップされたかのように選択したファイルが
>  アプリケーション側で開く。	

やじゅさん、おしゃっる通りです。

もう暫く、試行錯誤してみます。
ありがとうございました。

解決済み
引用返信 編集キー/
■15752 / inTopicNo.9)  Re[7]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ ぽぴ王子 (333回)-(2008/03/20(Thu) 11:16:10)
ぽぴ王子 さんの Web サイト
No15751 (熊谷隆史 さん) に返信
> > 		pDrop->Drop (pData, MK_LBUTTON, pt, (DWORD *)DROPEFFECT_LINK  );
> 
> 		↓
> 		DWORD *pdwEffect = NULL;
> 
> 		pDrop->Drop (pData, MK_LBUTTON, pt, pdwEffect );
> 
> の様に変更して、対象のアプリが落ちることは
> ありませんでしたが、無反応です
>  (まだ、何か考え違いをしてるのでしょうか)。

これだと、pdwEffect という ポインタ を定義しているに過ぎないです。

		DWORD dwEffect;

		pDrop->Drop (pData, MK_LBUTTON, pt, &dwEffect );

こうじゃないかなあと。

解決済み
引用返信 編集キー/
■15764 / inTopicNo.10)  Re[8]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ 熊谷隆史 (16回)-(2008/03/20(Thu) 13:26:47)
No15752 (ぽぴ王子 さん) に返信
---
 'IDropTarget::Drop' : 4 番目の引数を 
 'DWORD **' から 'DWORD *' に変換できません。
--- 

となります。

ひょっとして、
IDropTargetの全てのメンバを呼んで
やらないといけないのかも知れません。
引き続き、頑張ります。

ぽぴ王子さん、
ありがとうございました。	

引用返信 編集キー/
■15766 / inTopicNo.11)  Re[9]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ やじゅ (261回)-(2008/03/20(Thu) 14:27:20)
やじゅ さんの Web サイト
No15764 (熊谷隆史 さん) に返信

少し調べてみました。

@「擬似ドロップ」で検索してみると、
「あふ」ってファイラーが擬似ドロップしてますね、少しだけ操作してみたところでは
対象ファイルを「-」キーを押すと、現在起動されているドロップ対象のアプリケーション
一覧が出てきて、それを選択してEnterキーを押すと、指定したファイルを開いてくれました。
http://www.h5.dion.ne.jp/~akt/akt_afx.htm

A「ドロップ エミュレート」で検索してみると、
「相手先のウィンドゥに直接WM_DROPFILESを送ってやることで可能です。
DROPFILES構造体用のメモリを確保し、そこに必要情報を書き入れ、相手先の
ウィンドウに送りつけます。
メモリ確保は、シェルAPIのSHGetMalloc(&pMalloc)でメモリインターフェイスを
取得し、pMalloc->Alloc()でメモリを確保します。
pMalloc->Alloc()で確保したメモリは異プロセス間で参照可能です。
pMallocを使用し終わった後はpMalloc->Release()を忘れないようにしてください。
なお、DROPFILESに入れるファイル名ですが、Windows NT系列ではUNICODE、
それ以外ではANSIで入れないといけないようです。
(DROPFILES::fWideも適切にセットする。) 」

という情報が2chの掲示板にありました、動作未確認です。
引用返信 編集キー/
■15769 / inTopicNo.12)  Re[10]: 他アプリに対して、ファイルパスをドロップ
□投稿者/ 熊谷隆史 (17回)-(2008/03/20(Thu) 16:19:38)
ついに
キタ━━━(゚∀゚)━━━!!!!!

成功です(めっちゃ嬉しいです)。


		DWORD dwEffect = 0;

		pDrop->Drop (pData, MK_LBUTTON, pt, &dwEffect );

			// 戻り値確認。
		::SetProp (pmsg->hwnd,L"pDrop",(HANDLE)dwEffect);


DWORD型を、NULLポインタで初期化すると言う妙な事を
やってたのがいけなかったのと、
ぽぴ王子さんからご指摘頂きました、
アドレスを渡すようにしたところ、
見事に成功です。

しかし、ウィンドウプロパティに
dwEffectの値がセットされないのは謎ですが。





やじゅさん、
情報ありがとうございます。

すでにこの手の処理を行っているアプリが
あるのですね。

Cに於いてのWM_DROPFILESの方法も
勉強になりました。


ただ、メモ帳はウィンドウプロシージャで
WM_DROPFILESを処理していますが、

IEやエクスプローラなど、一般的には
OLEドロップ(←この呼称も適切かは分かりませんが)のみを
処理してることが多いようです。
 (メモ帳はOLEドロップには未対応)


なので、
今回の様な方法を選択しています。

複数ファイルのドロップには
複数回の呼び出しと冗長な処理に
なってしまうのとフォルダのパスのドロップは

IDataObjectを実装したクラスを作成しなくては
いけないのが今後の課題です。


回答を頂いた皆さん、
ありがとうございました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -