青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Dict.CN 在線詞典, 英語學習, 在線翻譯

學海苦作舟,書山勤為徑

留下點回憶

常用鏈接

統計

積分與排名

Denoise

English study

Web技術

數據壓縮

一些連接

最新評論

第六部分:實現Drop目標對象(OLE drag&drop 之旅)

歡迎你到OLE拖放操作的第六章!這里將著重于一個實現了drop-target的小程序,這就意味著我們的程序能夠接收拖到它上面的對象(文件、圖片、文本)了。

我們實現一個IDropTargetCOM接口允許OLE程序拖動數據到我們的程序上;這里僅僅是一個簡單的EDIT控件,所以他將CF_TEXT數據作為目標。

成為一個“Drop Target

為了時窗口可以接收拖放操作的數據,窗口必須注冊為drop目標;有一個OLEAPI調用RegisterDragDrop來完成這個事情,函數的原型是:

WINOLEAPI RegisterDragDrop (HWND hwnd, IDropTarget * pDropTarget);

第一個參數是窗口的HANDLE,這個窗口是拖動的目標窗口;第二個參數是一個指向IDropTarget COM對象的指針,COM/OLE運行時將在拖放操作的過程中調用這個方法。

同樣有一個OLE API調用來將window從拖放操作中刪除:

WINOLEAPI RevokeDragDrop(HWND hwnd);

我們所要做的就是在窗口創建的時候調用RegisterDragDrop,在窗口銷毀的時候調用RevokeDragDrop。在我們調用RegisterDragDrop之前,我們需要構造一個COM對象來支持IDropTarget接口。

IDropTarget接口

IDropTarget接口相對比較簡單,有四個函數需要實現,當然,也要實現IUnknown接口,不過我們前面已經介紹了。

IDropTarget 方法

描述

DragEnter

判斷是否可以接受一個拖操作,以及接受之后的效果

DragOver

提供通過DoDragDrop函數執行的目標反饋

DragLeave

導致一個drop目標掛起它的返回行為

Drop

數據放進目標窗口

這些函數都由COM/OLE運行時在一個對象被拖到我們注冊窗口的時候來調用。就象上表顯示的一樣,每個函數都有不同的任務,我們需要做的就是實現這些函數。

實現IDropTarget

以我的經驗,IDropTarget接口非常難以寫為不涉及特定程序的代碼,例如:寫成可以在所有程序都使用的通用IDropTarget COM對象是很難的。

這是因為IDropTarget要求在一個對象拖過你的目標窗口時顯示圖形效果,且也只有特定程序代碼才可以訪問這些數據對象內容。

在我們的拖放接口之外,IDropTarget是最容易被集成到你窗口類的對象。例如:假定你已經用C++類實現了一個自定義的窗口,為這個窗口添加一個多drop目標支持的最好方法就是從IDropTarget直接繼承,而不需要單獨定義一個CDropTarget類;這意味著你的drop-target代碼能夠訪問所有你的窗口狀態。

然而,我們這里提供完整的CDropTarget類:

class CDropTarget : public IDropTarget
{
public:
    // IUnknown implementation
    HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
    ULONG   __stdcall AddRef (void);
ULONG   __stdcall Release (void);
 
    // IDropTarget implementation
    HRESULT __stdcall DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
    HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
    HRESULT __stdcall DragLeave(void);
    HRESULT __stdcall Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
    // Constructor
    CDropTarget(HWND hwnd);
    ~CDropTarget();
private:
    // internal helper function
    DWORD DropEffect (DWORD grfKeyState, POINTL pt, DWORD dwAllowed);
    bool QueryDataObject(IDataObject *pDataObject);
    // Private member variables
    long   m_lRefCount;
    HWND   m_hWnd;
    bool   m_fAllowDrop;
    // Other internal window members
};

除引用記數器外,我們需要存儲另外兩個變量:m_hWnd變量是drop-target窗口的HANDLE,這個在提供可見效果的時候需要;m_fAllowDrop用來指示被拖動的數據對象是否包含我們需要的有用數據。因此我們沒有連續查詢數據對象,這是一個最優的辦法。

IDropTarget::DragEnter方法

讓我們首先看一下IDropTarget函數,因為這是在一個對象被拖過我們窗口時最先被COM調用的函數:

 

HRESULT DragEnter (
   IDataObject * pDataObject,//指向源數據對象的接口指針
   DWORD         grfKeyState, // 當前鍵盤修飾符的狀態
   POINTL        pt,             // 當前鼠標的坐標
   DWORD *       pdwEffect       // 指向拖放操作的效果指針
   );

仔細看一下上面函數的原型,因為這對于理解每個參數怎么樣使用很重要:

l         IDataObject-第一個參數是拖放操作的源對象通過COM傳遞來的數據對象指針。IDataObject是拖放操作帶來數據的傳輸媒體,我們在DragEnter的時候查看數據對象來看是否有我們想要的任何數據。

l         grfKeyState-保留鍵盤修飾符的狀態,例如:ControlAlt、和Shift以及鼠標按鍵的狀態。是有一到多個MK_CONTROLMK_SHIFTMK_ALTMK_BUTTONMK_LBUTTON等組成的簡單DWORD變量

l         pt-一個POINTL結構體,包含了鼠標進入我們窗口的坐標;在許多程序中,這個參數用來檢查鼠標是否放置在允許的drop區域上,或者用來簡單的放置某些插入光標來指示drop數據放在那里。

l         pdwEffect-一個DWORD的指針,指出drop源允許的drop效果。這個值和DoDragDropdwOKEffect值相同。

我們的DragEnter實現需要做幾個通常的工作,另外畫一個圖形的反饋:

1.       檢查提供的數據對象,然后判斷它是否包含任何有用的數據

2.       檢查存儲在grfKeyState的鍵盤狀態,并且計算應該是什么樣的drop效果,例如:如果Control鍵按下,drop效果應該是復制,如果Shift被按下,drop效果應該是移動。

3.       驗證這些效果是否與drop源的效果相兼容

4.       存儲最終的drop效果到pdwEffectDWORD指針。

不要如此復雜吧!DragEnter的目的就是簡單的對拖放操作說“yes還是NO”,指定采用什么drop效果以便于OLE更新鼠標光標。

HRESULT __stdcall CDropTarget::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
    // does the dataobject contain data we want?
    m_fAllowDrop = QueryDataObject (grfKeyState, pdwEffect, pDataObject);
    if(m_fAllowDrop)
    {
        // get the dropeffect based on keyboard state
        *pdwEffect = DropEffect (grfKeyState, pt, *pdwEffect);
        SetFocus (m_hWnd);
        PositionCursor (m_hWnd, pt);
    }
    else
    {
        *pdwEffect = DROPEFFECT_NONE;
    }
    return S_OK;
}

除了設置光標下的窗口和設置EDIT位置外,DragEnter的功能已經由兩個內部協助函數代理而簡化了:

bool CDropTarget::QueryDataObject(IDataObject *pDataObject)
{
    FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    // does the data object support CF_TEXT using a HGLOBAL?
    return pDataObject->QueryGetData(&fmtetc) == S_OK ? true : false;
}

QueryDataObject是一個私有函數,純粹用來檢查提供的數據,然后決定它是否包含對我們的drop目標有用的數據。在我們的例子中,我們僅僅接受CF_TEXT數據存儲為HGLOBAL,因此這是我們請求的類型。一個私有成員變量m_fAllowDrop用來記住這個決定。

DWORD CDropTarget::DropEffect (DWORD grfKeyState, POINTL pt, DWORD dwAllowed)
{
        DWORD dwEffect = 0;
        // 1. 檢查pt來看是否允許drop操作在某個位置
        // 2. 計算出基于grfKeyStatedrop效果
        if(grfKeyState & MK_CONTROL)
        {
               dwEffect = dwAllowed & DROPEFFECT_COPY;
        }
        else if(grfKeyState & MK_SHIFT)
        {
               dwEffect = dwAllowed & DROPEFFECT_MOVE;
        }
        // 3. 非鍵盤修飾符指定(或drop效果不允許),因此基于drop源的效果
        if(dwEffect == 0)
        {
               if(dwAllowed & DROPEFFECT_COPY) dwEffect = DROPEFFECT_COPY;
               if(dwAllowed & DROPEFFECT_MOVE) dwEffect = DROPEFFECT_MOVE;
        }
        return dwEffect;
}

DropEffect協助函數用來計算基于鍵盤狀態的drop效果,并且這個效果是達到源允許的。

首先grfKeyState變量用來檢查看是否使用了ControlShift鍵;這些鍵的標準的OLE行為是Control應該是復制數據,shift應該是移動數據。如果兩個都按下,數據 應該是連接(例如:源應該建立一個到目標的快捷方式),但我們不支持這個功能。

主要的事情是使用位與操作符來對dwEffectdrop效果值的時候:

dwEffect = dwAllowed & DROPEFFECT_COPY;

這個分配的結構很簡單-dwEffect將擁有DROPEFFECT_COPY,但只有在dwAllowed變量中僅僅包含這個值的時候起作用;這種邏輯用法防止我們強制執行一個源不允許的drop效果。

下面是看一下在沒有鍵盤修飾符的時候怎么做,例如:ControlShift沒有使用。在這種情況我,我們檢查拖放的源對象允許的drop效果,以及選擇使用哪個效果;在我們的實現中,我們是移動數據而不是復制。

IDropTarget::DragOver方法

這個函數在拖放操作的整個生命周期中被多次調用,因此,高效的寫這個函數很重要;DragOver在鍵盤修飾符改變(shift/control等)或當鼠標移動的時候被調用。告訴OLE采用什么樣基于鍵盤狀態和鼠標位置的drop效果是這個函數的責任:

HRESULT __stdcall CDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
{
    if(m_fAllowDrop)
    {
        *pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
        PositionCursor(m_hWnd, pt);
    }
    else
    {
        *pdwEffect = DROPEFFECT_NONE;
    }
    return S_OK;
}

DragOver寫的很簡單,邏輯上與DragEnter相同,我們使用前面計算過的m_fAllowDropDropEffect協助函數來通過pdwEffect指針返回drop效果。

IDropTarget::DragLeave函數

這個函數在鼠標光標移到drop目標窗口外面的時候調用,或者按下Escape鍵來取消拖放操作時。它的原型如下:

HRESULT __stdcall CDropTarget::DragLeave (void)
{
    return S_OK;
}

這是這個函數的基本寫法;這個函數存在的唯一原因是便于程序在鼠標移到窗口外面的時候使用圖形返回效果來得到一個機會清理。例如:想象下面的場景,無論什么東西都拖過目標對象,DragEnter函數用來改變窗口邊界的顏色;在這種情況下,DragLeave函數用來恢復窗口邊界的顏色。

IDropTarget::Drop函數

Drop函數的原型與DragEnter函數相同:

HRESULT __stdcall CDropTarget::Drop (IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
    PositionCursor(m_hWnd, pt);
    if(m_fAllowDrop)
    {
        DropData (m_hWnd, pDataObject);
        *pdwEffect = DropEffect (grfKeyState, pt, *pdwEffect);
    }
    else
    {
        *pdwEffect = DROPEFFECT_NONE;
    }
    return S_OK;
}

OLE判斷拖放操作到頭的時候調用該函數,我們得到一個在DragEnter同樣的IDataObject的接口指針,我們可以從中得到數據并粘貼到我們的編輯窗口中。

DropData協助函數用來訪問數據對象內部的CF_TEXT數據,并插入到edit控件中;這個程序是是純理論的,我們已經知道怎么樣訪問一個數據對象了,這里不在不厭其煩的介紹,你可以看源代碼。

posted on 2006-03-06 08:51 笨笨 閱讀(5355) 評論(12)  編輯 收藏 引用 所屬分類: OLE Drag&Drop

評論

# re: 第六部分:實現Drop目標對象(OLE drag&drop 之旅) 2006-05-24 20:11 王鴻杰

您好~我是來自臺灣的讀者,想要請教您,如果我想要寫一個ActiveX元件,嵌入IE中作為一個檔案拖放的接受器,是否可行呢??

以我的經驗,我將程式寫在一般的桌面應用程式,是可以實現OLE拖放,可是嵌到網頁裡面以後,我將檔案拖進IE當中,我的ActiveX元件卻沒有反應。您是否有可以參考的ActiveX程序呢??

ps.我是使用Borland C++ Builder去開發Active Control和Active Form,結果都沒有用。  回復  更多評論   

# re: 第六部分:實現Drop目標對象(OLE drag&drop 之旅) 2006-05-25 13:19 笨笨

我沒有相關的程序
我想你因看一下IE是如何處理DRAG OVER等事件的,我試驗發現他已經是一個TARGET。
你的ACTIVEX control有窗口嗎?  回復  更多評論   

# re: 第六部分:實現Drop目標對象(OLE drag&drop 之旅)[未登錄] 2007-06-27 01:40 Peter

您好,拜讀您之大作,受益良多,在下最近再撰寫這方面的相關程式,可以限制使用者複製文件、內容,複製檔案的行為,說穿了,就是監控剪貼板來達成。目前唯一的瓶頸就是使用者利用檔案總管來 Drag-Drop 複製檔案的行為無法攔截。因為這動作不透過傳統的剪貼板,也不會透過 OLE 剪貼板,所以監視剪貼板似乎沒有用。不知道可否請您賜教這方面該如何下手呢?

我目前想到的方法,就是利用 APIHook, MouseHook 來攔截這些訊息。看看能不能做到此功能。  回復  更多評論   

# re: 第六部分:實現Drop目標對象(OLE drag&drop 之旅) 2011-03-15 14:25 laocui

說好的源碼demo呢?  回復  更多評論   

# re: 第六部分:實現Drop目標對象(OLE drag&drop 之旅) 2012-02-01 12:11 PRESTONLetha26

Cars and houses are quite expensive and not every person is able to buy it. But, <a href="http://goodfinance-blog.com/topics/business-loans">business loans</a> was created to support different people in such hard situations.   回復  更多評論   

# re: 第六部分:實現Drop目標對象(OLE drag&drop 之旅) 2012-06-15 18:06 article submission

Are thirsting for good traffic? Do not know the way to do that? We are here just because of that! We provide outstanding quality manual article submission options at article submission directory company. We can guarantee you great publicity and great progress of your business.   回復  更多評論   

# re: 第六部分:實現Drop目標對象(OLE drag&drop 之旅) 2015-06-11 17:29 meifeng

IDropTarget可以支持圖片拖拽么  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美系列电影免费观看| 免费欧美日韩| 欧美岛国激情| 一区二区高清视频| 在线视频一区观看| 国产一区香蕉久久| 欧美成人自拍视频| 欧美精品一区二区三区很污很色的| 亚洲精品午夜精品| av成人黄色| 好吊一区二区三区| 亚洲精品韩国| 国产日韩亚洲| 亚洲第一福利视频| 国产欧美精品一区aⅴ影院| 欧美激情1区2区| 午夜精品网站| 欧美大片国产精品| 欧美日韩一区二区三区免费| 这里只有精品丝袜| 久久婷婷人人澡人人喊人人爽| 亚洲黄色在线| 欧美一区二区三区视频免费| 一区二区冒白浆视频| 久久精品伊人| 欧美在线视频一区| 国产精品日韩精品欧美精品| 日韩午夜高潮| 亚洲美女黄网| 欧美国产91| 亚洲精选大片| 亚洲视屏在线播放| 国产精品久久久久9999| 亚洲美女电影在线| 亚洲欧美www| 国产网站欧美日韩免费精品在线观看| 亚洲视频在线观看网站| 午夜电影亚洲| 好吊妞这里只有精品| 久久久久久久91| 亚洲福利视频在线| 亚洲视频大全| 国产亚洲在线| 欧美成人在线免费观看| 中文精品99久久国产香蕉| 亚洲欧美另类在线| 国产综合在线视频| 欧美国产91| 欧美在线看片| 亚洲日本中文字幕| 久久国产精品电影| 亚洲电影视频在线| 国产精品美女久久福利网站| 久久激情五月婷婷| 一本色道精品久久一区二区三区| 欧美一区二区成人6969| 久久久久网址| 久久国产精品一区二区三区四区 | 亚洲精品影视在线观看| 最新国产成人av网站网址麻豆| 怡红院精品视频| 亚洲欧洲日本在线| 亚洲无限乱码一二三四麻| 亚洲视频专区在线| 久久精品日韩一区二区三区| 欧美99在线视频观看| 欧美承认网站| 亚洲欧美精品在线| 亚洲国产日韩一级| 国产亚洲精品v| 欧美久久电影| 欧美高清在线一区| 免费欧美网站| 久久成人国产精品| 午夜精品一区二区三区四区 | 久久精品国产精品亚洲精品| 亚洲精品久久7777| 欧美成人嫩草网站| 老司机免费视频一区二区| 欧美制服第一页| 久久成人18免费观看| 性做久久久久久久免费看| 性欧美大战久久久久久久免费观看| 亚洲国产高清视频| 亚洲精品国产无天堂网2021| 亚洲日本成人在线观看| 亚洲另类一区二区| 一区二区三区精品视频| 亚洲欧洲av一区二区| 久久激情视频免费观看| 久久久久国产精品www| 欧美电影在线观看| 久久狠狠亚洲综合| 欧美国产第二页| 91久久精品美女高潮| 亚洲自拍偷拍麻豆| 亚洲国产精品久久久久| 亚洲香蕉在线观看| 欧美日韩亚洲一区二区三区在线观看| 国产精品高清免费在线观看| 亚洲国产婷婷综合在线精品| 久久精品99无色码中文字幕| 中日韩美女免费视频网址在线观看| 噜噜爱69成人精品| 黄网动漫久久久| 国产在线精品二区| 午夜日韩在线| 欧美一级黄色录像| 国产在线拍偷自揄拍精品| 久久成人亚洲| 欧美h视频在线| 夜夜嗨一区二区| av成人免费观看| 国产伦一区二区三区色一情| 欧美在线视频观看免费网站| 一区二区三区视频观看| 欧美日本簧片| 在线亚洲观看| 亚洲一区二区三区免费视频| 国产精品久久国产三级国电话系列| 在线视频亚洲| 99综合视频| 国产精品观看| 久久综合网络一区二区| 美女久久一区| 亚洲另类黄色| 先锋资源久久| 91久久久久久久久久久久久| 亚洲精选一区| 国内精品久久久久久久97牛牛| 久久综合网色—综合色88| 欧美精品性视频| 久久久久久久久久久一区| 欧美韩国日本一区| 玖玖国产精品视频| 国产三级欧美三级| 亚洲第一页中文字幕| 一本色道久久综合精品竹菊 | 亚洲在线黄色| 夜夜嗨av一区二区三区中文字幕| 久久精品国语| 久久婷婷国产综合国色天香| 国产丝袜一区二区| 久久国产婷婷国产香蕉| 另类天堂av| 99国产精品一区| 国产精品chinese| 亚洲欧美日韩另类| 久久精品在线| 国产真实乱子伦精品视频| 亚洲一区二区精品在线观看| 99www免费人成精品| 蜜臀av性久久久久蜜臀aⅴ四虎 | 欧美中文在线观看| 亚洲图片欧洲图片av| 夜夜躁日日躁狠狠久久88av| 欧美顶级大胆免费视频| 亚洲国产精品专区久久| 亚洲第一页自拍| 亚洲欧洲日韩在线| 日韩一级网站| 免费黄网站欧美| 亚洲丶国产丶欧美一区二区三区| 亚洲电影毛片| 欧美激情四色| 亚洲天堂av图片| 国产永久精品大片wwwapp| 久久xxxx| 亚洲电影免费观看高清完整版在线观看| 精品不卡在线| 国产精品jizz在线观看美国| 久久亚洲国产精品一区二区| 亚洲国产高清一区二区三区| 欧美日韩一区三区| 久久精品国产视频| 一区二区电影免费观看| 久久视频国产精品免费视频在线 | 国产丝袜美腿一区二区三区| 久久久福利视频| 亚洲国产毛片完整版| 欧美视频精品在线| 久久欧美中文字幕| 亚洲免费小视频| 亚洲人成网站777色婷婷| 国产婷婷色综合av蜜臀av| 欧美日韩视频一区二区三区| 久久精品五月| 久久av一区二区三区漫画| 亚洲一区二区三| 一本一本久久| 亚洲精品免费观看| 日韩视频一区二区三区在线播放免费观看 | 欧美日韩中文| 欧美精品1区2区3区| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲在线一区二区三区| 一区二区三区欧美在线| 亚洲视频在线一区| 亚洲一区二区三区视频播放| 中文在线不卡视频|