Solved

TWebBrowser OLE Drag Drop

Posted on 2004-09-09
1
857 Views
Last Modified: 2010-04-05
How do I override the default OLE drag drop behaviour for a TWebBrowser?

I am using the TWebrowser component as a HTML editor by putting it in edit mode.  I like the fact that I can drag HTML from IE into it. But, When I drag a link, or a html file, it opens the document, replacing the contents with the new file.  I would like to speficy my own behaviour when files are dropped, but use the existing behaviour when html is dropped.

It looks like I need to create a new Interface that inherits from the IDropTarget Interface that TWebBrowser uses, but I have no Idea how to do this.

I have figured out how to replace the IDropTarget interface, by doing the following:


//-------
...
CustDoc: ICustomDoc;
hr : HResult;
begin
  hr := WebBrowser1.Document.QueryInterface(ICustomDoc, CustDoc);
  if hr = $00000000 {S_OK} then
    CustDoc.SetUIHandler(DocHostUIHandler);
...

DocHostUIHandler is an instance of this class, which allows overriding the regular UI operations:

TDocHostUIHandler = class(TComObject, IDocHostUIHandler)

One of the methods of this class is GetDropTarget, which allows you to specify an alternate IDropTarget interface.  I have been able
disable and enable drag drop by editing the contents.  So, I think that all I need to do is replace ppDropTarget with my own interface? How do I create this interface, so that I can inherit some of the existing behaviour?

function TDocHostUIHandler.IDocHostUIHandler_GetDropTarget(const pDropTarget: IDropTarget;
  out ppDropTarget: IDropTarget): HRESULT;
begin
 //Enables Drag drop;
  Result := S_OK;
  //Disables drop
  //Result := S_FALSE;
end;

0
Comment
Question by:wolsen
1 Comment
 
LVL 33

Accepted Solution

by:
Slick812 earned 125 total points
Comment Utility
hello  wolsen, , I have done a little with the IDropTarget Interface, I am mostly posting here because no one else has. I can not explain the IDropTarget Interface since, there are many factors and methods, it controls the cursors shown for a drag over, and queries for drop data types that are accepted or not, I do not handle any of that in my code. . .
Here is a BASIC and about as simple as you can get IDropTarget class. . . There are MANY types of Drop Data, they are usually typed by a Clip board format, like CF_HDROP  , CF_TEXT  and  CF_IDLIST , I do not know the CF_  type for HTML or Links . . .
The following code only does the CF_HDROP  format, sorry I do not have time now to clean it up , (take out un-used code) - -


type

  TDropTarget = class(TInterfacedObject, IDropTarget)
   function DragEnter(const DataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; stdcall;
   function DragOver(grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; stdcall;
   function DragLeave: HResult; stdcall;
   function Drop(const DataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; stdcall;
   end;

implementation


// TDropTarget = = = = = = = = = = = = = = = = = = = = = = = =
// the first three functions do not do anything, just return a default NOERROR and the system does the default handling

function TDropTarget.DragEnter(const DataObj: IDataObject; grfKeyState: Longint;
                               pt: TPoint; var dwEffect: Longint): HResult;
begin
//DataObj.EnumFormatEtc(dwDuirection, IEnumFormatetc);
 dwEffect := DROPEFFECT_NONE{DROPEFFECT_LINK};
 Result := NOERROR;
end;

function TDropTarget.DragOver(grfKeyState: Longint; pt: TPoint;
                              var dwEffect: Longint): HResult;
begin
 dwEffect := DROPEFFECT_NONE{DROPEFFECT_LINK};
 Result := NOERROR;
end;

function TDropTarget.DragLeave: HResult;
begin
 Result := NOERROR;
end;

function TDropTarget.Drop(const DataObj: IDataObject; grfKeyState: Longint;
                          pt: TPoint; var dwEffect: Longint): HResult;
var
 Enum : IEnumFormatEtc;
 Link : PChar;
 Dummy : Integer;
 Format : TFormatEtc;
 Medium : TStgMedium;
 {FileStr,} FileStr1: String;
 DropFiles: PDropFiles;
 //ShiftState: Byte;

  {function GetFilesFromHGlobal(const HGlob: HGlobal; Files: String): boolean;
  var
  DropFiles: PDropFiles;
  Filename: PChar;
  begin
  DropFiles := PDropFiles(GlobalLock(HGlob));
  try
  Files := 'Low';
  //FileStr1 := 'Low';
    Filename := PChar(DropFiles) + DropFiles^.pFiles;
    while (Filename^ <> #0) do
    begin
      if (DropFiles^.fWide) then // -> NT4 & Asian compatibility
      begin
        //Files.Add(PWideChar(FileName));
        Files := Files+','+PWideChar(FileName);
        inc(Filename, (Length(PWideChar(FileName)) + 1) * 2);
      end else
      begin
        //Files.Add(Filename);
        Files := Files+','+FileName;
        FileStr1 := FileStr1 +','+FileName;
        inc(Filename, Length(Filename) + 1);
      end;
    end;
  finally
    GlobalUnlock(HGlob);
  end;

  Result := (Length(Files) > 0);
  end;}

{function KeysToShiftState(Keys: Word): Byte;
begin
// did not need key dowm info
  Result := Zero;
  if Keys and MK_SHIFT <> Zero then Result := One;
  if Keys and MK_CONTROL <> Zero then Result := Result or 2;
  if Keys and MK_LBUTTON <> Zero then Result := Result or 4;
  if Keys and MK_RBUTTON <> Zero then Result := Result or 8;
  if Keys and MK_MBUTTON <> Zero then Result := Result or 16;
  //if GetKeyState(VK_MENU) < 0 then Result := Result or 32;
end;}

begin
{this does very little, just gets the file name from the DropFiles, a pointer to
 the TDropFiles in ShlObj.pas  , I only needed a single file name, I only do ONE kind
 of drop data, CF_HDROP, but there are many more}

Result := S_OK;

if DataObj.EnumFormatEtc(DATADIR_GET, Enum) <> S_OK then Exit;

 while Enum.Next(One, Format, @Dummy) = S_OK do
 begin // Enum.Next
 //ComStr := ComStr+' '+ Int2Str(Format.cfFormat);
 //SetWindowText(hWordEdit, Pchar(ComStr));

 if Format.cfFormat = CF_HDROP then
   if DataObj.GetData(Format, Medium) = S_OK then
     begin  // GetData
     try
     //ShiftState := KeysToShiftState(grfKeyState);
      if (medium.tymed = TYMED_HGLOBAL) then
        begin // TYMED_HGLOBAL
       //GetFilesFromHGlobal(medium.HGlobal, FileStr);
       DropFiles := PDropFiles(GlobalLock(medium.HGlobal));
       Link := PChar(DropFiles) + DropFiles^.pFiles;
       while (Link^ <> #0) do
         begin // Link <> 0
         if (DropFiles^.fWide) then // -> NT4 & Asian compatibility
           begin // fWide
           FileStr1 := FileStr1+PWideChar(Link);
           inc(Link, (Length(PWideChar(Link)) + One) * Two);
           end else // fWide
           begin
           FileStr1 := FileStr1 +Link;
           inc(Link, PCharLength(Link) + One);
           end; // else fWide
         end; // Link <> 0

       end; // TYMED_HGLOBAL
      finally
      //Don't forget to clean-up!
      GlobalUnlock(medium.HGlobal);
      ReleaseStgMedium(medium);
      end; // finally
     end;  // GetData
  if Length(FileStr1) > 6 then
    begin
    if FileExists(FileStr1) then
    if LoadIColFile(FileStr1) > mOne then
      begin;
      SetNewFile(FileStr1);
     
      end;
    end;
 end; // Enum.Next

 dwEffect := DROPEFFECT_NONE{DROPEFFECT_LINK};
end;


// TDropTarget finish  = = = = = = = = = =  = =

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

I have no Idea how to incorperate this in to a web browser for editing, and know nothing about the  IDocHostUIHandler_GetDropTarge  function. . ,
I use this code to give my API custom control drop file handling -


var
DropTar: TDropTarget;


if OleInitialize(nil) = S_OK then
  begin
  RegisterDragDrop(hScrollGrid, DropTar);
// hScrollGrid is the control Handle
  end;


- - - - - - - - - - - - - - - - - - - -

there is also an API function  RevokeDragDrop( ) which will Turn OFF the IDropTarget Interface for a control, I do not have time to try it, but you may be able to change the IDtopTarget for your window with -

RevokeDragDrop(WebBrowser.Handle);
RegisterDragDrop(WebBrowser.Handle, DropTar);

but there may be complications with an application as complex as the IE browser!, , like I said I have not tried it.

also, I wonder if you know of the ActiveX control DHTMLEdit, which is a system activeX that is for HTML Editing, and is in the  DHTMLEDLib_TLB.pas and is suppose to be good for an HTML editor, if you can figure out how to use it
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now