亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

使用OLE拖放不同程序間的數據

2019-11-18 18:30:21
字體:
來源:轉載
供稿:網友

使用OLE拖放不同程序間的數據

(OLE Drag and Drop)

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

上一篇:數據錄入時自動復制原記錄

下一篇:win32調試API學習心得(三)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美www| 国产精品久久久久久影视| 国产精品无码专区在线观看| 亚洲人成网站在线播| 欧美性xxxxxx| 日韩高清a**址| 日韩中文娱乐网| 精品少妇一区二区30p| 欧美激情综合色综合啪啪五月| 亚洲欧洲在线免费| 国内精品国产三级国产在线专| 国产一区二区三区高清在线观看| 97国产精品免费视频| 欧美丰满老妇厨房牲生活| 精品国产一区二区三区久久久狼| 一本大道香蕉久在线播放29| 国产精品爽黄69| 久久久国产一区二区三区| 国产91在线播放九色快色| 精品欧美aⅴ在线网站| 成人av在线天堂| 久久久久女教师免费一区| 日韩精品福利网站| 国产精品视频在线播放| 欧美在线激情视频| 国内外成人免费激情在线视频网站| 日本成人在线视频网址| 97色在线视频观看| 亚洲综合一区二区不卡| 精品国产乱码久久久久久虫虫漫画| 国产午夜精品一区理论片飘花| 91精品国产91久久久久久久久| 欧美一级bbbbb性bbbb喷潮片| 欧美怡春院一区二区三区| 久久激情五月丁香伊人| 91国产中文字幕| 午夜精品久久久久久99热软件| 亚洲一区二区三区乱码aⅴ| 97色在线观看免费视频| 久久成人亚洲精品| 欧美巨乳美女视频| 精品久久久久久久久久| 亚洲国产成人在线视频| 亚洲欧美日韩国产中文专区| 日韩av三级在线观看| 欧美富婆性猛交| 亚洲国产成人av在线| 成人福利视频在线观看| 高清在线视频日韩欧美| 成人羞羞国产免费| 欧美精品videos另类日本| 久久777国产线看观看精品| 538国产精品视频一区二区| 欧美大奶子在线| 成年无码av片在线| 欧美激情女人20p| 亚洲精品美女久久久| 粉嫩av一区二区三区免费野| 欧美精品aaa| 久久天天躁狠狠躁夜夜爽蜜月| 91香蕉国产在线观看| 亚洲精品动漫久久久久| 久久999免费视频| 亚洲日韩欧美视频| 国产精品久久久久久久久借妻| 国产精品久久久av久久久| 欧美福利视频在线观看| 欧美日韩激情美女| 亚洲人成自拍网站| 98精品国产高清在线xxxx天堂| 91精品国产综合久久香蕉最新版| 亚洲精品乱码久久久久久按摩观| 久久天天躁狠狠躁夜夜躁| 日韩欧美国产高清91| 懂色av影视一区二区三区| 亚洲欧美自拍一区| 丰满岳妇乱一区二区三区| 国产精品久久久久久搜索| 在线观看视频99| 国产精品夜间视频香蕉| 欧美性色视频在线| 亚洲国产美女久久久久| 亚洲精品美女免费| 久久久精品久久久久| 国内精品久久影院| 欧亚精品在线观看| 亚洲精品白浆高清久久久久久| 插插插亚洲综合网| 91av视频在线免费观看| 日韩精品中文字幕在线观看| 欧美国产精品人人做人人爱| 欧美高清在线观看| 911国产网站尤物在线观看| 国产精品扒开腿做爽爽爽视频| 欧美日本在线视频中文字字幕| 91精品久久久久久久久久久久久| 国产精品1区2区在线观看| 国产在线不卡精品| 亚洲aⅴ日韩av电影在线观看| 国产欧美日韩中文字幕在线| 欧美高清在线观看| 国产欧美精品一区二区三区-老狼| 国产精品99免视看9| 亚洲国产私拍精品国模在线观看| 欧美性猛交99久久久久99按摩| 红桃视频成人在线观看| 在线观看日韩www视频免费| 日韩免费在线播放| 亚洲国产精品高清久久久| 日韩国产欧美区| 欧美激情视频免费观看| 国产一区视频在线| 亚洲视频精品在线| 91精品久久久久久久久中文字幕| 久久天天躁狠狠躁夜夜躁| 久久久电影免费观看完整版| 91麻豆国产语对白在线观看| 色七七影院综合| 国产一区二区丝袜高跟鞋图片| xvideos国产精品| 国产精品99蜜臀久久不卡二区| 日韩成人xxxx| 8090理伦午夜在线电影| 欧美日韩第一视频| 成人妇女免费播放久久久| 91av免费观看91av精品在线| 欧美天堂在线观看| 欧美有码在线视频| 国产精品白丝jk喷水视频一区| 97人洗澡人人免费公开视频碰碰碰| 亚洲免费视频在线观看| 自拍偷拍亚洲精品| 91热福利电影| 日韩在线中文视频| 国产一区二区美女视频| 亚洲a级在线播放观看| 最新69国产成人精品视频免费| 日韩电影在线观看永久视频免费网站| 日韩的一区二区| 久久久久久亚洲| 欧美极品少妇与黑人| 亚洲电影免费观看高清完整版在线| 欧美丝袜美女中出在线| 亚洲第一色在线| 热99精品里视频精品| 久久高清视频免费| 久久精品99国产精品酒店日本| 九九久久久久99精品| 岛国av午夜精品| 日韩精品视频在线免费观看| 国产精品www| 九九热这里只有在线精品视| 91精品啪在线观看麻豆免费| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产精品久久久久久久久久久新郎| 久久久人成影片一区二区三区观看| 国产精品偷伦视频免费观看国产| 久久天堂av综合合色| 色综合视频一区中文字幕| 欧美怡春院一区二区三区| 欧美日韩国产区| 欧美洲成人男女午夜视频| 91精品91久久久久久| 精品国产户外野外|