画像のURL(MelanderBlogのコンポーネント)に関して


deldel  2012-01-24 09:56:23  No: 41497  IP: 192.*.*.*

Mr.XRAYさんのサイト「Delphiサンプルプログラム集」
http://mrxray.on.coocan.jp/Delphi/plSamples/821_Application_DragDrop.htm
の真ん中よりちょっと下に
  リスト4 
  ブラウザからドロップした画像のURLは,URLプロパティで取得可能
  ShowMessage(DropComboTarget1.URL);
というのがあります。

例えばJpeg画像をドロップした場合、DropComboTarget1.URLの内容が
「〜.jpg」という場合と、画像をリンクとして使用している場合は
そのリンク先のURLの場合があります。

後者の場合でも、ブラウザ上で右クリックすると「名前を付けて画像を保存」
というメニューが出てJpegファイルとして保存できますので、なんとかして
画像のURLを取得できそうな気がするのですが、何か方法があるのでしょうか?

(ここに質問するのはどうかなと思いましたが、結構いいコンポ集なので、
  紹介も兼ねて^^;)

編集 削除
Mr.XRAY  2012-01-24 15:50:16  No: 41498  IP: 192.*.*.*

こんにちは.Mr.XRAYです.
私の名前が見えたので....

>画像のURLを取得できそうな気がするのですが、何か方法があるのでしょうか?

これは,ドラッグ,ドロップした時にということでしょうか?
もし,そうであれば,

DropComboTarget1.Text

で取得できるようですが...  ハズしたかな?
もっともリダイレクトはしませんが.

編集 削除
deldel  2012-01-24 16:28:05  No: 41499  IP: 192.*.*.*

ご回答ありがとうございます。
やってみましたが、うまくいきませんでした。

同じページの上部に、「山 Mr.XRAY」という画像がありますが、これをD&Dすると、
DropComboTarget1.Text も、DropComboTarget1.URL も、
  http://mrxray.on.coocan.jp/Delphi/Images/Little_MrXRAY.gif
となって、これはファイル名が取得できます。

が、その左の「HOME」という画像では、共に
  http://mrxray.on.coocan.jp/index.htm
となります・・・。これも同様に、
  http://mrxray.on.coocan.jp/Delphi/Images/Hoome.gif
のような感じの文字列が取得できればいいんですが・・・。

編集 削除
Mr.XRAY  2012-01-24 17:16:36  No: 41500  IP: 192.*.*.*

なるほど.
どちらも同じ値で,リンク先がある時は,そのURL.ない時は,画像のパス名なんですね.
う〜む.調べないと分かりせん.

編集 削除
Mr.XRAY  2012-01-25 08:35:51  No: 41501  IP: 192.*.*.*

IDropTargetインターフェイスでは取得できないようですね.
仕様ということです.多分.残念ですが.
で,方法は他の方にバトンタッチします.

編集 削除
deldel  2012-01-25 16:47:22  No: 41502  IP: 192.*.*.*

調べていただきありがとうございます。
そうですか・・・残念です><

編集 削除
Mr.XRAY  2012-01-25 18:35:04  No: 41503  IP: 192.*.*.*

あまりにも簡単なレスなので,ちょっと説明を.

IDropTargetインターフェイスは受け取る側ですが,
受け取ることができるデータは,
ドラッグされる側,今回はブラウザ(IEやFireFox)ですが,こちらが実装している
IDropSourceによります.つまり,ブラウザ側がどんなデータを渡しているかによります.

つまり,URLやTextプロパティの値は,ブラウザとそのバージョンによって異なる可能性があります.

編集 削除
中身をチェック  2012-01-25 20:12:36  No: 41504  IP: 192.*.*.*

ブラウザから画像をDragした時に、どんなデータが渡されるのかを調べてListViewに列挙してやれば、求める画像データが含まれるか確認できます。
リンク付きの画像をそのままDragした場合は画像データが含まれないことが分かります。
なので、画像データが含まれるようにDragするためには、その画像を選択状態(画像に網がかかった状態)にしてからDragする必要があります。
そうすれば、画像の情報(HTMLテキスト)が含まれるので、画像のURLを取得できます。


unit U_TestDropComboTarget;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, ExtCtrls, DragDrop, DropTarget, DragDropGraphics, //JPEG,
  DropComboTarget, StdCtrls, ActiveX, ComCtrls, OleCtrls, SHDocVw_TLB,
  UIWebBrowser, OleErrors;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Image1: TImage;
    DropComboTarget1: TDropComboTarget;
    Button1: TButton;
    Memo1: TMemo;
    MemoHTML: TMemo;
    ListView1: TListView;
    UIWebBrowser1: TUIWebBrowser;
    Edit1: TEdit;
    procedure FormShow(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure DropComboTarget1Drop(Sender: TObject;
      ShiftState: TShiftState; APoint: TPoint; var Effect: Integer);
  private
    { Private 宣言 }
    FSize: Integer;
    function FormatTypeToString(cf: Word): string;
    procedure HandleHTML(dataObj: IDataObject;  fetc: TFormatEtc);
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  本フォームの上にTPanelを配置,そのTPanelにTImaeを配置してある
//
//  TargetをTPanelにする
//  対象のフォーマット指定.テキスト等もテスト可能なように設定
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
  DropComboTarget1.Target := Panel1;  //ScrollBox1;

  DropComboTarget1.Formats := [];
  DropComboTarget1.Formats := DropComboTarget1.Formats + [mfText];
  DropComboTarget1.Formats := DropComboTarget1.Formats + [mfFile];
  DropComboTarget1.Formats := DropComboTarget1.Formats + [mfURL];
  DropComboTarget1.Formats := DropComboTarget1.Formats + [mfBitmap];
  DropComboTarget1.Formats := DropComboTarget1.Formats + [mfMetaFile];
  DropComboTarget1.Formats := DropComboTarget1.Formats + [mfData];

  Image1.Transparent := True;
end;

//=============================================================================
//  TDropComboTargetのOnDropイベント
//=============================================================================

procedure TForm1.DropComboTarget1Drop(Sender: TObject;
  ShiftState: TShiftState; APoint: TPoint; var Effect: Integer);
var
  DataObj: IDataObject;
  stgm: TSTGMEDIUM;
  fetc: TFormatEtc;
  ef: IEnumFORMATETC;
  s, sD: string;
  p: Pointer;
  O: TClass;
  sz: array[0..255] of char;
begin
  MemoHTML.Clear;
  Memo1.Clear;
  ListView1.Items.Clear;
  Edit1.Text := '';
  Image1.Picture.Assign(nil);
  UIWebBrowser1.Navigate('about:blank');
  O := ExceptionClass;
  ExceptionClass := EAbort;
  DataObj := DropComboTarget1.DataObject;
  // IEnumFORMATETC interfaceを取得
  DataObj.EnumFormatEtc(DATADIR_GET, ef);
  // FormatEtc列挙
  while(ef.Next(1, fetc, nil) <> S_FALSE) do begin
    FSize := 0;
    // FormatEtc記述名を取得
    GetClipboardFormatName(fetc.cfFormat, @sz, Sizeof(sz)-1);
    if(sz = 'HTML Format') then begin
      HandleHTML(DataObj, fetc);
    end;
    with ListView1.Items.Add do begin
      Caption := FormatTypeToString(fetc.cfFormat);
      SubItems.Add(IntToStr(FSize));
    end;
  end;
  if DropComboTarget1.Bitmap.Handle <> 0 then begin
    Image1.Picture.Assign(DropComboTarget1.Bitmap);
  end else
  if DropComboTarget1.MetaFile.Handle <> 0 then begin
    Image1.Picture.Assign(DropComboTarget1.MetaFile);
  end;
  ExceptionClass := O;
  Memo1.Text := DropComboTarget1.Text;
  Caption := DropComboTarget1.URL;
end;

//=============================================================================
//  ついでにクリップボードからの[貼り付け]テスト
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  DropComboTarget1.PasteFromClipboard;
end;

//=============================================================================
//リンク付き画像の場合、それを選択して網がかかった状態にしてからDragする必要あり
//=============================================================================
function TForm1.FormatTypeToString(cf: Word): string;
var
   sz: array[0..255] of char;
begin
  case (cf) of
    CF_TEXT         : result := 'CF_TEXT';
    CF_BITMAP       : result := 'CF_BITMAP';
    CF_METAFILEPICT : result := 'CF_METAFILEPICT';
    CF_SYLK         : result := 'CF_SYLK';
    CF_DIF          : result := 'CF_DIF';
    CF_TIFF         : result := 'CF_TIFF';
    CF_OEMTEXT      : result := 'CF_OEMTEXT';
    CF_DIB          : result := 'CF_DIB';
    CF_PALETTE      : result := 'CF_PALETTE';
    CF_PENDATA      : result := 'CF_PENDATA';
    CF_RIFF         : result := 'CF_RIFF';
    CF_WAVE         : result := 'CF_WAVE';
    CF_UNICODETEXT  : result := 'CF_UNICODETEXT';
    CF_ENHMETAFILE  : result := 'CF_ENHMETAFILE';
    CF_HDROP        : result := 'CF_HDROP';
    CF_LOCALE       : result := 'CF_LOCALE';
    CF_MAX          : result := 'CF_MAX';
  else
    begin
      GetClipboardFormatName(cf, @sz, Sizeof(sz)-1);
      result := '[' + IntToStr(cf) + '] ' + sz;
    end;
  end;
end;

procedure TForm1.HandleHTML(dataObj: IDataObject; fetc: TFormatEtc);
const
  OFS_HTM = 'StartHTML:';
  TGT_URL = 'SourceURL:';
var
  BaseTAG, BaseURL: string;
  //---------------------------------------------
  function InsertBaseTAG(HTMLCode: PChar; out InsPtr: PChar): Integer;
  var
    p, pH: PChar;
  begin
    result := 0;
    InsPtr := nil;
    //HTML先頭までのオフセット
    p := StrPos(HTMLCode, OFS_HTM);
    if p <> nil then begin
      inc(p, Length(OFS_HTM));
      pH := p;
      while not(p^ in [#0,#13]) do inc(p);
      if p^ = #0 then exit;
      p^ := #0;
      result := StrToIntDef(pH, 0);
      p^ := #13;
      // BaseURLを抽出
      pH := StrPos(p+1, TGT_URL);
      if pH <> nil then begin
        inc(pH, Length(TGT_URL));
        p := HTMLCode + result;
        if p^ <> '<' then exit;
        while (p-1)^ <> '/' do dec(p);
        p^ := #0;
        BaseURL := Trim(pH);
        BaseTAG := '<BASE HREF="'+ Trim(pH) +'">'#13#10;
        p^ := '<';
      end;
    end;
    // BaseTAGの挿入位置を探す
    InsPtr := StrPos(p+1, '<HEAD>');      // <HEAD>の直後
    if InsPtr <> nil then begin
      inc(InsPtr, Length('<HEAD>'));
      if (InsPtr)^ <> #13 then BaseTAG := #13#10 + BaseTAG;
    end;
  end;
  // HTMLテキストをブラウザに読み込んで表示
  procedure WB_LoadHTML(WebBrowser: TUIWebBrowser; HTMLCode: PChar);
  var
    ms: TMemoryStream;
  begin
    WebBrowser.Navigate('about:blank');
    while WebBrowser.ReadyState < READYSTATE_INTERACTIVE do begin
      Application.ProcessMessages;  Sleep(1);
    end;
    if Assigned(WebBrowser.Document) then begin
      with TStringList.Create do
      try
        ms := TMemoryStream.Create;
        try
          Text := HTMLCode;
          SaveToStream(ms);
          ms.Seek(0, 0);
          (WebBrowser.Document as IPersistStreamInit).Load(TStreamAdapter.Create(ms));
        finally
          ms.Free;
        end;
      finally
        Free;
      end;
    end;
  end;
  //-------------------------------------------------------
var
  p: Pointer;
  stgm: TSTGMEDIUM;
  s, sD: string;
  pN, pS: PChar;
  ofs: Integer;
begin
  if(dataObj.QueryGetData(fetc) = NOERROR) then begin
    OleCheck(dataObj.GetData(fetc, stgm));
    p := GlobalLock(stgm.hGlobal);
    try
      FSize := GlobalSize(stgm.hGlobal);
      s  := Utf8ToAnsi(PChar(p));
      ofs := InsertBaseTAG(PChar(s), PChar(pN));
      if pN <> nil then begin
        pN^ := #0;
        sD := PChar(s) + BaseTAG;
        pN^ := '<';
        sD := sD + pN;
        MemoHTML.Text := sD;
      end else begin
        sD := s;
        MemoHTML.Text := s;
      end;
      WB_LoadHTML(UIWebBrowser1, PChar(sD) + ofs);
      pN := StrPos(pN, '<!--StartFragment-->');
      if pN = nil then exit;
      pN := StrPos(pN, 'src="');
      if pN <> nil then begin
      pS := pN + StrLen('src="');
      pN := pS;
       while pN^ <> '"' do inc(pN);
      pN^ := #0;
      if StrLComp(pS, 'http', 4) = 0 then
        Edit1.Text := pS
      else
        Edit1.Text := BaseURL + pS;
    end;
    finally
      GlobalFree(stgm.hGlobal);
      ReleaseStgMedium(stgm);
    end;
  end;
end;

end.

編集 削除