InternetExplorer及びIEコンポーネントを使用しているタブブラウザ等から
自前のWindowにリンクのドロップを受けとる方法が判りません。
IE以外のエンジンのブラウザ(FireFox等)からの場合はテキストの場合と同様
IDropTargetインターフェイスの実装で普通に受け取る事が出来るのですが、
IEのリンクの場合、IDropTargetにはDropイベントがきません。
(DragEnterは来るのでDragEnterの時点でGetDataしておけば一応リンク自体
得る事は可能なのですが、マウスカーソルは駐禁マークのままだし終了を
検知出来ないのでマウスカーソルがWindow内に入った瞬間にドロップされた
ことにしてしまうしかない)
Sleipnir等、コンポーネントブラウザでは普通にリンクをブラウザウィンドウ
以外の部分で受け取る事も出来ているので、恐らく何か方法があるとは
思うのですが、調べたところではIWebBrowser2でドロップの受け取り可否が
出来るらしいという程度で、しかもIWebBrowser2に設定したところで
受け取れるのはIWebBrowser2上エリアだけなので意味が無い。
もしかしたらIWebBrowser2は全くレンダリングせず、表示はあくまで自前の
Windowで、でも自前のWindowの表面にIWebBrowser2が張り付いている、という
ような作成方法があったりするのかもしれないですが実現方法が判りません。
何方か、IEからのリンクの受け取り方をご存知の方は教えていただけませんでしょうか?
よろしくお願いします。
>DragEnterは来るのでDragEnterの時点でGetDataしておけば一応リンク自
>体得る事は可能なのですが、マウスカーソルは駐禁マークのまま
それはひょっとして、DragEnter への応答を間違えていたりしませんか?
具体的にはどんなコードを書いていますか?
>もしかしたらIWebBrowser2は全くレンダリングせず、表示はあくまで自前
>のWindowで、でも自前のWindowの表面にIWebBrowser2が張り付いている、
>というような作成方法があったりするのかもしれない
それはまずあり得ないと思います。
具体的コード例について記させて頂きます。
IDropTargetの実装についてですが、
http://hp.vector.co.jp/authors/VA016117/oledragdrop1.html
このサイトのサンプルを元にして作成させていただきました。
#include <windows.h>
#include <objbase.h>
#include "dropTarget.h"
HRESULT __stdcall dropTarget::QueryInterface(const IID& iid, void** ppv)
{
HRESULT hr;
if(iid == IID_IDropTarget || iid == IID_IUnknown){
hr = S_OK;
*ppv = (IDropTarget*)this;
AddRef();
}else{
MessageBox(NULL, "知らないインターフェイスを要求されたよ?", "あうぅ", MB_OK) ;
hr = E_NOINTERFACE;
*ppv = 0;
}
return hr;
}
ULONG __stdcall dropTarget::AddRef()
{
InterlockedIncrement(&_RefCount);
return (ULONG)_RefCount;
}
ULONG __stdcall dropTarget::Release()
{
ULONG ret = (ULONG)InterlockedDecrement(&_RefCount);
if(ret == 0){
// このクラスを作成する時はnewを使うこと
delete this;
}
return (ULONG)_RefCount;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT __stdcall dropTarget::DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL ptl, DWORD* pdwEffect)
{
_DataObject = pDataObject; //IDataObjectを記憶してDragOverでも使えるようにする
SetForegroundWindow(hWnd) ;
SetCapture(hWnd) ;
HCURSOR cur ;
cur = LoadCursor(NULL, IDC_ARROW) ;
SetCursor(cur) ;
SetClassLong(hWnd, GCL_HCURSOR, (LONG)cur) ;
// MessageBox(hWnd, "きてるよ", "DragEnter", MB_OK) ;
return DragOver(grfKeyState, ptl, pdwEffect); //あとはDragOverと同じ
}
HRESULT __stdcall dropTarget::DragOver(DWORD grfKeyState, POINTL ptl, DWORD* pdwEffect)
{
//フォーマットに対応した処理をする
FORMATETC ft ;
ft.cfFormat = CF_TEXT ;
ft.ptd = NULL ;
ft.dwAspect = DVASPECT_CONTENT ;
ft.lindex = -1 ;
ft.tymed = TYMED_HGLOBAL ;
*pdwEffect = DROPEFFECT_COPY ;
if(_DataObject->QueryGetData(&ft) == S_OK) {
HCURSOR cursor ;
cursor = LoadCursor(NULL, IDC_ARROW) ;
SetCursor(cursor) ;
STGMEDIUM sg ;
if(_DataObject->GetData(&ft, &sg) == S_OK) {
LPVOID lpdat ;
lpdat = GlobalLock(sg.hGlobal) ;
int len ;
len = lstrlen((LPSTR)lpdat) ;
lstrcpy(url, (LPSTR)lpdat) ;
GlobalUnlock(sg.hGlobal) ;
ReleaseStgMedium(&sg) ;
if((grfKeyState & MK_LBUTTON) == 0) {
MessageBox(NULL, url, "URL from IE?", MB_OK) ;
}
}
}
return S_OK;
}
HRESULT __stdcall dropTarget::DragLeave()
{
ReleaseCapture() ;
_DataObject = NULL ;
HCURSOR cursor ;
cursor = LoadCursor(NULL, IDC_NO) ;
SetCursor(cursor) ;
return S_OK;
}
HRESULT __stdcall dropTarget::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL ptl, DWORD* pdwEffect)
{
*pdwEffect = DROPEFFECT_COPY;
FORMATETC ft ;
ft.cfFormat = CF_TEXT ;
ft.ptd = NULL ;
ft.dwAspect = DVASPECT_CONTENT ;
ft.lindex = -1 ;
ft.tymed = TYMED_HGLOBAL ;
STGMEDIUM sg ;
if(_DataObject->GetData(&ft, &sg) == S_OK) {
LPVOID lpdat ;
lpdat = GlobalLock(sg.hGlobal) ;
int len ;
len = lstrlen((LPSTR)lpdat) ;
char *string ;
string = new char[len+1] ;
lstrcpy(string, (LPSTR)lpdat) ;
GlobalUnlock(sg.hGlobal) ;
ReleaseStgMedium(&sg) ;
MessageBox(NULL, string, "URL?", MB_OK) ;
delete [] string ;
}
MessageBox(NULL, "キターーーーー", "キター", MB_OK) ;
return S_OK;
}
タブが省略されて見難くなってしまいました、すみません。
とりあえず貼り付けたサンプルは実験用コードですが、とりあえず
このコードで通常のTEXT形式のドロップを受け取ることは出来ています。
また、アドレスバーのアイコンからのドロップについても受け取る事が
出来ます。
問題は、コンテンツ中に記されているリンクのドロップを正常に
受け取れないという点にありまして、それで困っています。
どなたかお分かりになる方が居られましたらご教授願います。
すみません、あと補足説明なんですが、DragEnter/Overの戻り値が絶対S_OKだったり
その他チェックが甘いという点はあると思いますが、IEからのリンクドロップが
来るか来ないかでとことんチェックを甘めにして、どうしたらDropが来るか
と色々実験した結果です。その点についての突っ込みはご勘弁下さい。
宜しくお願いします。
1つ思ったのですが、ひょっとしてRegisterDragDropだけでは
IEからのリンクのドロップは受け取れないのでしょうか?
WebBrowser経由かなにかで何かのインターフェイスを取得して、
そこにIDropTargetを登録するメソッドがあったりするのでしょうか?
> 問題は、コンテンツ中に記されているリンクのドロップを正常に
> 受け取れないという点にありまして、それで困っています。
正常に受け取れないということは、異常には受け取れるのですか?
それとも、全く受け取れないのですか?
試してないけど、CF_TEXT に加えて、CFSTR_INETURL も受け入れればできませんかね?
http://msdn2.microsoft.com/en-us/library/aa969394.aspx#CFSTR_INETURL
>正常に受け取れないということは、異常には受け取れるのですか?
>それとも、全く受け取れないのですか?
すみません、そもそもの問題はDropイベントが来ないという点にありまして、
DragEnterは来ているのにDropが来ないのがなんでかなぁ?という感じなのです。
またDragEnterにてCF_TEXTで受け取る事は出来るので、フォーマットの問題でも
ありません。一応CFSTR_INETURLもRegisterClipboardFormat経由にて試してみましたが
変わりませんでした。
(というか*pdwEffectは無条件でDROPEFFECT_COPYにしていますのでそういう
問題じゃないと思います)
で、その他色々と見直してしていまして、実は解決出来ました。
問題点は、*pdwEffectに設定していたのがDROPEFFECT_COPYだったという点でして
DROPEFFECT_LINKにするとあっさり受け取る事が出来ました。
まだまだ実験が足りなかったようですね。
お騒がせしました〜
すみません、解決にするの忘れてました。
ツイート | ![]() |