为可视控件提供OLE拖放支持的MOleDragDrop控件

这个单元包含了一个非可视的控件,用于为可视控件提供OLE拖放支持。
目前支持以下格式的拖入:

  • 纯文本(包括UNICODE)
  • HTML文本
  • URL
  • 图片(包括BITMAP和DIB)
  • 文件

增加了:

属性:

  • DropControl--关联用于接受拖入的可视控件;
  • EnableTarget--设置是否允许拖入。
方法:
  • 无。
事件:
  • OnDragEnter、OnDragOver、OnDragLeave、OnDragDrop:是四个 IDropTarget接口的标准事件,用于自定义扩充格式拖放的支持。
  • OnTextDrop、OnHTMLDrop、OnURLDrop、OnBitmapDrop、OnFileDrop: 分别用于支持文本、HTML、URL、图片、文件的拖入响应。

由于在COM技术的实现上,Delphi与C++Builder有较大的差异,Delphi版的控件不能直接用于C++Builder,故单独提供了C++Builder版。

另C++Builder版控件有一个无法解决的问题就是在使用本控件的程序退出时,在Notification方法中将DropControl = NULL时会发生异常。经查,可能是由于DropControl中设置的控件的父控件(如窗体)的先释放导致的,说明在C++Builder中控件的释放顺序与Delphi可能不同,因为在Delphi版中是没有问题的。

目前这个问题我是通过在SetDropControl中将此异常屏蔽来解决的,最好是能在DropControl属性中设置的控件的父控件(如FORM)的析构函数中手工将DropControl属性清空。


1.1版改进了一个BUG,增加对UNICODE的支持(仍然支持得不好)。


1.2版(C++Builder)改进了拖入的事件响应,将原来的多个事件简化为只有一个
OnSimpleDrop事件,可以在一次拖放操作中同时接受多种拖入的数据。用法如下:

void __fastcall TForm1::MOleDragDrop1SimpleDrop(TObject *Sender,
IDataObject *aDataObj, TMDropTypes aDropTypes)
{
AnsiString s;
TMauto_ptr ss( new TStringList( ) );
TMauto_ptr bm( new TGBitmap( ) );
if ( aDropTypes.Contains( dtText ) )
{
MOleDragDrop1->GetDropData( aDataObj, dtText, s );
Memo1->Lines->Add( s );
}
if ( aDropTypes.Contains( dtUnicodeText ) )
{
MOleDragDrop1->GetDropData( aDataObj, dtUnicodeText, s );
Memo1->Lines->Add( s );
}
if ( aDropTypes.Contains( dtUrl ) )
{
MOleDragDrop1->GetDropData( aDataObj, dtUrl, s );
Memo1->Lines->Add( s );
}
if ( aDropTypes.Contains( dtHtml ) )
{
MOleDragDrop1->GetDropData( aDataObj, dtHtml, s );
Memo1->Lines->Add( s );
}
if ( aDropTypes.Contains( dtFiles ) )
{
MOleDragDrop1->GetDropData( aDataObj, dtFiles, ss );
Memo1->Lines->AddStrings( ss );
}
if ( aDropTypes.Contains( dtBitmap ) )
{
MOleDragDrop1->GetDropData( aDataObj, dtBitmap, bm );
Image1->Picture->Assign( bm );
}
}


1.3版(C++Builder)改进了:

OnDragEnter事件,可以取得DropTypes;

OnSimpleDrop事件,可以取得KeyState和Point;

增加TTempSaveOleDragDropControl类,用于当DropControl是ListView时,改变ViewStyle后不能拖入的问题。因为ListView改变ViewStyle会使RegisterDragDrop失效,需要重新注册,这个类为避免这种情况提供的解决办法,用法很简单:

void __fastcall TMainForm::miListViewReport( TObject * Sender )
{
TTempSaveOleDragDropControl tsoddc( MOleDragDrop1 ); // MOleDragDrop1是控件名

ListView1->ViewStyle = vsReport;
}

如此即可。


1.4版(C++Builder)改正了几个BUG

修改了UNICODE的支持(取消Unicode属性)

OnSimpleDrop事件中增加DropEffect参数

通过HOOK FORM的OnDestroy事件来解决前述错误,如果在应用中有设置Form的OnDestroy事件,请注意这一点。


1.5版(C++Builder)最终解决释放顺序造成的异常问题,不再需要HOOK FORM的OnDestroy事件了。


安装:
-------------
新建一个Package,在Package中需要加上vcl.bpi。

在此下载源程序:15KB

Dec.03-03, 09, 27, Dec.06-04, 08