麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

使用OLE拖放不同程序間的數(shù)據(jù)

2019-11-18 18:30:21
字體:
供稿:網(wǎng)友

使用OLE拖放不同程序間的數(shù)據(jù)

(OLE Drag and Drop)

難度:★★★☆☆
先行知識:Delphi / 接口 / Win32 / OLE or COM
 
從一個程序拖動數(shù)據(jù)到另一個程序(典型的情況是拖動文本)已經(jīng)不是什么新鮮事了,很多共享軟件都支持這個功能(比如說著名的FlashGet、netants等的浮動窗口功能)。作者一直想在自己的軟件中實現(xiàn)這個功能,經(jīng)過一段時間的資料搜索,有了部分的了解,但這些文檔大多數(shù)使用C++描述。于是,好東西(也算不上好好的吧J)不敢獨享,經(jīng)過整理我將自己用delphi的實現(xiàn)方法寫出來,并簡單的講解一下OLE Drag and Drop機(jī)制。
所謂OLE Drag and Drop不用翻譯大家一看就能知道它的意思了,它使不同的程序(或同一個程序)通過相互拖動數(shù)據(jù)來進(jìn)行交互成為可能。 在這方面windows為我們在后面做了很復(fù)雜的工作,幸運的是我們不用擔(dān)心它的復(fù)雜性,windows已經(jīng)為我們提供了兩個相當(dāng)關(guān)鍵的接口:IDropSource、IDropTarget,我們只用實現(xiàn)這兩個接口便可以方便的實現(xiàn)OLE Drag and Drop,前者由允許拖放自己數(shù)據(jù)的數(shù)據(jù)源程序?qū)崿F(xiàn),后者由允許接收拖放數(shù)據(jù)的數(shù)據(jù)目標(biāo)程序所實現(xiàn)。在本文中,我們只討論后者,因為我們只希望接收來自其它程序拖放過來的數(shù)據(jù),而前者已經(jīng)被大多數(shù)程序?qū)崿F(xiàn)了(如IE、windows幫助系統(tǒng)等,如果想了解更多關(guān)于IDropSource的實現(xiàn)請參看win32 sdk幫助文件)。
接下來我們簡單的了解一下windows是怎樣在后面實現(xiàn)數(shù)據(jù)拖放的,然后我們實現(xiàn)IDropTarget的一個例子程序(關(guān)于程序中的api和格式會在出現(xiàn)的時候給予說明)。Windows在后臺調(diào)用了一個重要的DoDragDrop函數(shù)來檢測接口和調(diào)用有我們實現(xiàn)的接口方法,下面是這個函數(shù)工作時大概的步驟:
·當(dāng)我們開始向可以接收數(shù)據(jù)的窗體拖動數(shù)據(jù)時,DoDragDrop首先檢查鼠標(biāo)下的窗體是否被注冊為可以接收的窗體(通過RegisterDragDrop api來注冊,該函數(shù)有兩個參數(shù),第一個為要注冊的窗體的句柄,第2個為指向我們實現(xiàn)IDropTarget的類的一個對象指針,在我們的窗體不需要再接收任何拖動過來的數(shù)據(jù)時使用RevokeDragDrop來解除注冊,它只有一個參數(shù),就是欲解除的窗體句柄,另外重要的一點是要成功的調(diào)用這些函數(shù),我們必須在程序開始時使用OleInitialize(nil)在結(jié)束時調(diào)用OleUninitialize以便初始化OLE library。)
·如果窗體可以接收拖動,DoDragDrop便調(diào)用IDropTarget接口的DragEnter方法,該方法通過一個引用參數(shù)返回一個拖動的效果dwEffect,它可以有不同的取值(通過檢查IDataObject來決定),你可以在幫助中找到這些值,其中有表示復(fù)制、剪切等的操作(指對于實現(xiàn)IDropSource的程序),具體的你還會在下文的代碼中看到。然后DoDragDrop通過調(diào)用IDropSource::GiveFeedback來將dwEffect傳遞給IDropSource。
·接下來DoDragDrop根據(jù)鼠標(biāo)的狀態(tài)調(diào)用諸如IDropTarget接口的DragOver、DragLeave方法,整個過程是在循環(huán)中不斷的檢測鼠標(biāo)的狀態(tài)來實現(xiàn)的,如果這時你改變了拖動目標(biāo)它會再次檢測新的目標(biāo)并重復(fù)上面的過程,如果你在鍵盤上同時按住了其它的鍵,它會調(diào)用IDropSource::QueryContinueDrag并在改變了鍵盤狀態(tài)碼(你可以通過DragEnter、DragOvert中的grfKeyState參數(shù)來檢測改值,并根據(jù)它做相應(yīng)的工作)后繼續(xù)重復(fù)上面的過程。
·當(dāng)我們最后松開鼠標(biāo)后DoDragDrop將調(diào)用IDropTarget的Drop方法,它最后一次返回dwEffect,最后根據(jù)dwEffect我們可以在這個方法中得到IDataObject中的數(shù)據(jù),一次完整的拖放操作就完成了。下面的圖說明一次拖放操作的過程:
上面說了這么多,其實都是windows在后臺為我們所做的工作,我們只是大概的了解一下這個過程,下面我們通過一個例子來實現(xiàn)一個可以接受文本的memo,窗體中只有一個Tmemo,請注意代碼中的注釋。我們先來看看在程序主窗口創(chuàng)建和撤消時需要做的一些必要的初始化和結(jié)束操作:
constructor TForm1.Create(AOwner: TComponent);
begin
  inherited Create(AOWner);
  OleInitialize(nil);
  DragAndDropOLE:=TDragAndDropOLE.Create;
  // TDragAndDropOLE便是我們要實現(xiàn)IDropTarget接口的類
end;
 
destructor TForm1.Destroy;
begin
  DragAndDropOLE.Free;
  OleUninitialize;
  inherited;
end;
下面我們來看看關(guān)鍵的TDragAndDropOLE的實現(xiàn),首先他應(yīng)該實現(xiàn)IunKnown接口,這是一個基本的接口用來實現(xiàn)引用計數(shù),熟悉COM的朋友應(yīng)該都知道這個接口及其實現(xiàn)方法,下面只給出實現(xiàn)它的代碼不做詳細(xì)說明,主要要注意的是IDropTarget的實現(xiàn)方法:
首先是TDragAndDropOLE的聲明部分:
type
  TDragAndDropOLE=Class(TObject,IUnknown,IDropTarget)
  PRivate
   CanDrop:HResult;
   fe:TFormatEtc;//數(shù)據(jù)的格式,在實現(xiàn)部分給出詳細(xì)說明
   FRefCount:integer;//引用計數(shù)
  protected
   { Iunkown }
   function _AddRef:integer;stdcall;
   function _Release:integer;stdcall;
   function QueryInterface(const IID:TGUID;out Obj):HResult;stdcall;
   { IdropTarget }
   function DragEnter(const dataObj: IDataObject; grfKeyState: Longint;
      pt: TPoint; var dwEffect: Longint): HResult;stdcall;
   function DragOver(grfKeyState: Longint; pt: TPoint;var dwEffect: Longint):HResult;stdcall;
   function DragLeave: HResult;stdcall;
   function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
    var dwEffect: Longint): HResult; stdcall;
  public
   constructor Create;
   destructor Destroy;override;
  end;
下面是實現(xiàn)部分,首先初始化部分:
constructor TDragAndDropOLE.Create;
begin
  FRefCount:=0;
  RegisterDragDrop(Form1.Memo1.Handle,self);//上文提到的函數(shù)
end;
 
destructor TDragAndDropOLE.Destroy;
begin
  RevokeDragDrop(Form1.Memo1.Handle);
  inherited;
end;
接下來實現(xiàn)Iunknown,不再做詳細(xì)說明:
function TDragAndDropOLE._AddRef: integer;
begin
 result:=InterLockedDecrement(FRefCount);
 if Result=0 then Destroy;
end;
 
function TDragAndDropOLE._Release: integer;
begin
 result:=InterLockedIncrement(FRefCount);
end;
 
function TDragAndDropOLE.QueryInterface(const IID: TGUID;
  out Obj): HResult;
begin
 if GetInterface(IID,Obj) then
  result:=S_OK
 else result:=E_NOINTERFACE;
end;
最重要的IDropTarget實現(xiàn):
function TDragAndDropOLE.DragEnter(const dataObj: IDataObject;
  grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
begin
 result:=E_FAIL;
 CanDrop:=E_Fail;
 if assigned(dataObj) then
 begin
  with fe do
  begin
   cfFormat:=CF_TEXT;
   ptd:=nil;
   dwaspect:=DVASPECT_CONTENT;
   lindex:=-1;
   tymed:=TYMED_HGLOBAL;
  end;
  //大家從上面看到的fe是一種我們處理內(nèi)存數(shù)據(jù)時常用的轉(zhuǎn)換格式
  //這里它表示將數(shù)據(jù)格式作為文字(cfFormat),并將其存入一塊
  //全局的內(nèi)存區(qū)域(tymed:=TYMED_HGLOBAL),更多的格式請在win32
  //幫助中搜索TFormatEtc
  CanDrop:=dataObj.QueryGetData(fe);//按照fe指定的格式檢查數(shù)據(jù)
  result:=CanDrop;
  if not Failed(result) then
   dwEffect:=DROPEFFECT_COPY
  else dwEffect:=DROPEFFECT_NONE;
  //注意這里我們設(shè)置了dwEffect,更多的取值請查看win32幫助
 end;
end;
 
function TDragAndDropOLE.DragLeave: HResult;
begin
 result:=S_OK;
end;
 
function TDragAndDropOLE.DragOver(grfKeyState: Integer; pt: TPoint;
  var dwEffect: Integer): HResult;
begin
 result:=S_OK;
 //我們不需要在這里做其余的操作,當(dāng)然你可以根據(jù)自己的需要完成自己的方法
end;
 
function TDragAndDropOLE.Drop(const dataObj: IDataObject;
  grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
var
 medium:stgMedium;
 hData:HGLOBAL;
begin
 result:=E_Fail;
 if not Failed(CanDrop) then
 begin
   result:=dataObj.GetData(fe,medium);
   //按照fe的格式將數(shù)據(jù)存入內(nèi)存的一塊全局區(qū)域,注意medium
   hData:=HGLOBAL(GlobalLock(medium.hGlobal));
   //GlobalLock鎖定這塊區(qū)域,并返回指向它的指針
   Form1.Memo1.Text:=pchar(hData);
   GlobalUnlock(hData);//接觸鎖定
   GlobalFree(hData);//釋放
 end;
end;
現(xiàn)在我們可以測試它了。本文只是大概的介紹了一下OLE Drag and Drop,只要仔細(xì)研究,大家可以實現(xiàn)更復(fù)雜的操作。 

上一篇:數(shù)據(jù)錄入時自動復(fù)制原記錄

下一篇:win32調(diào)試API學(xué)習(xí)心得(三)

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 成人在线精品视频 | 免费毛片电影 | 精品一区二区三区中文字幕老牛 | 欧产日产国产精品99 | 中文字幕综合在线观看 | 沉沦的校花奴性郑依婷c到失禁 | 久久伊人国产精品 | 91精品国产91久久久久久 | 精品国产一区二区久久 | sese在线视频 | 黄色大片在线免费观看 | 亚洲成人涩涩 | 国产精品久久久久国产精品三级 | 欧美日本91精品久久久久 | 欧美亚洲国产成人 | 九九精品在线观看视频 | 九色91视频 | 精品国产九九九 | 欧美精品电影一区 | 高清国产在线 | 久久国产在线观看 | 亚洲无av| 成人区精品一区二区婷婷 | 欧美精品一区二区性色 | 日日操日日操 | 亚洲国产成人久久一区www妖精 | 久久久中精品2020中文 | 操你啦免费视频 | 欧美成年人在线视频 | 国产精品久久久久久久久久三级 | 日本欧美一区二区三区在线播 | 久久久婷婷 | 中文字幕免费看 | 成年性羞羞视频免费观看无限 | 久久网站热最新地址4 | 狠狠婷婷综合久久久久久妖精 | 亚洲第一综合 | 国产做爰全免费的视频黑人 | 51国产偷自视频区视频小蝌蚪 | 国产乱淫a∨片免费观看 | 精品一区久久久 |