• <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>
            Dict.CN 在線詞典, 英語(yǔ)學(xué)習(xí), 在線翻譯

            學(xué)海苦作舟,書山勤為徑

            留下點(diǎn)回憶

            常用鏈接

            統(tǒng)計(jì)

            積分與排名

            Denoise

            English study

            Web技術(shù)

            數(shù)據(jù)壓縮

            一些連接

            最新評(píng)論

            第六部分:實(shí)現(xiàn)Drop目標(biāo)對(duì)象(OLE drag&drop 之旅)

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

            我們實(shí)現(xiàn)一個(gè)IDropTargetCOM接口允許OLE程序拖動(dòng)數(shù)據(jù)到我們的程序上;這里僅僅是一個(gè)簡(jiǎn)單的EDIT控件,所以他將CF_TEXT數(shù)據(jù)作為目標(biāo)。

            成為一個(gè)“Drop Target

            為了時(shí)窗口可以接收拖放操作的數(shù)據(jù),窗口必須注冊(cè)為drop目標(biāo);有一個(gè)OLEAPI調(diào)用RegisterDragDrop來(lái)完成這個(gè)事情,函數(shù)的原型是:

            WINOLEAPI RegisterDragDrop (HWND hwnd, IDropTarget * pDropTarget);

            第一個(gè)參數(shù)是窗口的HANDLE,這個(gè)窗口是拖動(dòng)的目標(biāo)窗口;第二個(gè)參數(shù)是一個(gè)指向IDropTarget COM對(duì)象的指針,COM/OLE運(yùn)行時(shí)將在拖放操作的過程中調(diào)用這個(gè)方法。

            同樣有一個(gè)OLE API調(diào)用來(lái)將window從拖放操作中刪除:

            WINOLEAPI RevokeDragDrop(HWND hwnd);

            我們所要做的就是在窗口創(chuàng)建的時(shí)候調(diào)用RegisterDragDrop,在窗口銷毀的時(shí)候調(diào)用RevokeDragDrop。在我們調(diào)用RegisterDragDrop之前,我們需要構(gòu)造一個(gè)COM對(duì)象來(lái)支持IDropTarget接口。

            IDropTarget接口

            IDropTarget接口相對(duì)比較簡(jiǎn)單,有四個(gè)函數(shù)需要實(shí)現(xiàn),當(dāng)然,也要實(shí)現(xiàn)IUnknown接口,不過我們前面已經(jīng)介紹了。

            IDropTarget 方法

            描述

            DragEnter

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

            DragOver

            提供通過DoDragDrop函數(shù)執(zhí)行的目標(biāo)反饋

            DragLeave

            導(dǎo)致一個(gè)drop目標(biāo)掛起它的返回行為

            Drop

            數(shù)據(jù)放進(jìn)目標(biāo)窗口

            這些函數(shù)都由COM/OLE運(yùn)行時(shí)在一個(gè)對(duì)象被拖到我們注冊(cè)窗口的時(shí)候來(lái)調(diào)用。就象上表顯示的一樣,每個(gè)函數(shù)都有不同的任務(wù),我們需要做的就是實(shí)現(xiàn)這些函數(shù)。

            實(shí)現(xiàn)IDropTarget

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

            這是因?yàn)?/SPAN>IDropTarget要求在一個(gè)對(duì)象拖過你的目標(biāo)窗口時(shí)顯示圖形效果,且也只有特定程序代碼才可以訪問這些數(shù)據(jù)對(duì)象內(nèi)容。

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

            然而,我們這里提供完整的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
            };

            除引用記數(shù)器外,我們需要存儲(chǔ)另外兩個(gè)變量:m_hWnd變量是drop-target窗口的HANDLE,這個(gè)在提供可見效果的時(shí)候需要;m_fAllowDrop用來(lái)指示被拖動(dòng)的數(shù)據(jù)對(duì)象是否包含我們需要的有用數(shù)據(jù)。因此我們沒有連續(xù)查詢數(shù)據(jù)對(duì)象,這是一個(gè)最優(yōu)的辦法。

            IDropTarget::DragEnter方法

            讓我們首先看一下IDropTarget函數(shù),因?yàn)檫@是在一個(gè)對(duì)象被拖過我們窗口時(shí)最先被COM調(diào)用的函數(shù):

             

            HRESULT DragEnter (
               IDataObject * pDataObject,//指向源數(shù)據(jù)對(duì)象的接口指針
               DWORD         grfKeyState, // 當(dāng)前鍵盤修飾符的狀態(tài)
               POINTL        pt,             // 當(dāng)前鼠標(biāo)的坐標(biāo)
               DWORD *       pdwEffect       // 指向拖放操作的效果指針
               );

            仔細(xì)看一下上面函數(shù)的原型,因?yàn)檫@對(duì)于理解每個(gè)參數(shù)怎么樣使用很重要:

            l         IDataObject-第一個(gè)參數(shù)是拖放操作的源對(duì)象通過COM傳遞來(lái)的數(shù)據(jù)對(duì)象指針。IDataObject是拖放操作帶來(lái)數(shù)據(jù)的傳輸媒體,我們?cè)?/SPAN>DragEnter的時(shí)候查看數(shù)據(jù)對(duì)象來(lái)看是否有我們想要的任何數(shù)據(jù)。

            l         grfKeyState-保留鍵盤修飾符的狀態(tài),例如:ControlAlt、和Shift以及鼠標(biāo)按鍵的狀態(tài)。是有一到多個(gè)MK_CONTROLMK_SHIFTMK_ALTMK_BUTTONMK_LBUTTON等組成的簡(jiǎn)單DWORD變量

            l         pt-一個(gè)POINTL結(jié)構(gòu)體,包含了鼠標(biāo)進(jìn)入我們窗口的坐標(biāo);在許多程序中,這個(gè)參數(shù)用來(lái)檢查鼠標(biāo)是否放置在允許的drop區(qū)域上,或者用來(lái)簡(jiǎn)單的放置某些插入光標(biāo)來(lái)指示drop數(shù)據(jù)放在那里。

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

            我們的DragEnter實(shí)現(xiàn)需要做幾個(gè)通常的工作,另外畫一個(gè)圖形的反饋:

            1.       檢查提供的數(shù)據(jù)對(duì)象,然后判斷它是否包含任何有用的數(shù)據(jù)

            2.       檢查存儲(chǔ)在grfKeyState的鍵盤狀態(tài),并且計(jì)算應(yīng)該是什么樣的drop效果,例如:如果Control鍵按下,drop效果應(yīng)該是復(fù)制,如果Shift被按下,drop效果應(yīng)該是移動(dòng)。

            3.       驗(yàn)證這些效果是否與drop源的效果相兼容

            4.       存儲(chǔ)最終的drop效果到pdwEffectDWORD指針。

            不要如此復(fù)雜吧!DragEnter的目的就是簡(jiǎn)單的對(duì)拖放操作說“yes還是NO”,指定采用什么drop效果以便于OLE更新鼠標(biāo)光標(biāo)。

            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;
            }

            除了設(shè)置光標(biāo)下的窗口和設(shè)置EDIT位置外,DragEnter的功能已經(jīng)由兩個(gè)內(nèi)部協(xié)助函數(shù)代理而簡(jiǎn)化了:

            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是一個(gè)私有函數(shù),純粹用來(lái)檢查提供的數(shù)據(jù),然后決定它是否包含對(duì)我們的drop目標(biāo)有用的數(shù)據(jù)。在我們的例子中,我們僅僅接受CF_TEXT數(shù)據(jù)存儲(chǔ)為HGLOBAL,因此這是我們請(qǐng)求的類型。一個(gè)私有成員變量m_fAllowDrop用來(lái)記住這個(gè)決定。

            DWORD CDropTarget::DropEffect (DWORD grfKeyState, POINTL pt, DWORD dwAllowed)
            {
                    DWORD dwEffect = 0;
                    // 1. 檢查pt來(lái)看是否允許drop操作在某個(gè)位置
                    // 2. 計(jì)算出基于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協(xié)助函數(shù)用來(lái)計(jì)算基于鍵盤狀態(tài)的drop效果,并且這個(gè)效果是達(dá)到源允許的。

            首先grfKeyState變量用來(lái)檢查看是否使用了ControlShift鍵;這些鍵的標(biāo)準(zhǔn)的OLE行為是Control應(yīng)該是復(fù)制數(shù)據(jù),shift應(yīng)該是移動(dòng)數(shù)據(jù)。如果兩個(gè)都按下,數(shù)據(jù) 應(yīng)該是連接(例如:源應(yīng)該建立一個(gè)到目標(biāo)的快捷方式),但我們不支持這個(gè)功能。

            主要的事情是使用位與操作符來(lái)對(duì)dwEffectdrop效果值的時(shí)候:

            dwEffect = dwAllowed & DROPEFFECT_COPY;

            這個(gè)分配的結(jié)構(gòu)很簡(jiǎn)單-dwEffect將擁有DROPEFFECT_COPY,但只有在dwAllowed變量中僅僅包含這個(gè)值的時(shí)候起作用;這種邏輯用法防止我們強(qiáng)制執(zhí)行一個(gè)源不允許的drop效果。

            下面是看一下在沒有鍵盤修飾符的時(shí)候怎么做,例如:ControlShift沒有使用。在這種情況我,我們檢查拖放的源對(duì)象允許的drop效果,以及選擇使用哪個(gè)效果;在我們的實(shí)現(xiàn)中,我們是移動(dòng)數(shù)據(jù)而不是復(fù)制。

            IDropTarget::DragOver方法

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

            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寫的很簡(jiǎn)單,邏輯上與DragEnter相同,我們使用前面計(jì)算過的m_fAllowDropDropEffect協(xié)助函數(shù)來(lái)通過pdwEffect指針返回drop效果。

            IDropTarget::DragLeave函數(shù)

            這個(gè)函數(shù)在鼠標(biāo)光標(biāo)移到drop目標(biāo)窗口外面的時(shí)候調(diào)用,或者按下Escape鍵來(lái)取消拖放操作時(shí)。它的原型如下:

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

            這是這個(gè)函數(shù)的基本寫法;這個(gè)函數(shù)存在的唯一原因是便于程序在鼠標(biāo)移到窗口外面的時(shí)候使用圖形返回效果來(lái)得到一個(gè)機(jī)會(huì)清理。例如:想象下面的場(chǎng)景,無(wú)論什么東西都拖過目標(biāo)對(duì)象,DragEnter函數(shù)用來(lái)改變窗口邊界的顏色;在這種情況下,DragLeave函數(shù)用來(lái)恢復(fù)窗口邊界的顏色。

            IDropTarget::Drop函數(shù)

            Drop函數(shù)的原型與DragEnter函數(shù)相同:

            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判斷拖放操作到頭的時(shí)候調(diào)用該函數(shù),我們得到一個(gè)在DragEnter同樣的IDataObject的接口指針,我們可以從中得到數(shù)據(jù)并粘貼到我們的編輯窗口中。

            DropData協(xié)助函數(shù)用來(lái)訪問數(shù)據(jù)對(duì)象內(nèi)部的CF_TEXT數(shù)據(jù),并插入到edit控件中;這個(gè)程序是是純理論的,我們已經(jīng)知道怎么樣訪問一個(gè)數(shù)據(jù)對(duì)象了,這里不在不厭其煩的介紹,你可以看源代碼。

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

            評(píng)論

            # re: 第六部分:實(shí)現(xiàn)Drop目標(biāo)對(duì)象(OLE drag&drop 之旅) 2006-05-24 20:11 王鴻杰

            您好~我是來(lái)自臺(tái)灣的讀者,想要請(qǐng)教您,如果我想要寫一個(gè)ActiveX元件,嵌入IE中作為一個(gè)檔案拖放的接受器,是否可行呢??

            以我的經(jīng)驗(yàn),我將程式寫在一般的桌面應(yīng)用程式,是可以實(shí)現(xiàn)OLE拖放,可是嵌到網(wǎng)頁(yè)裡面以後,我將檔案拖進(jìn)IE當(dāng)中,我的ActiveX元件卻沒有反應(yīng)。您是否有可以參考的ActiveX程序呢??

            ps.我是使用Borland C++ Builder去開發(fā)Active Control和Active Form,結(jié)果都沒有用。  回復(fù)  更多評(píng)論   

            # re: 第六部分:實(shí)現(xiàn)Drop目標(biāo)對(duì)象(OLE drag&drop 之旅) 2006-05-25 13:19 笨笨

            我沒有相關(guān)的程序
            我想你因看一下IE是如何處理DRAG OVER等事件的,我試驗(yàn)發(fā)現(xiàn)他已經(jīng)是一個(gè)TARGET。
            你的ACTIVEX control有窗口嗎?  回復(fù)  更多評(píng)論   

            # re: 第六部分:實(shí)現(xiàn)Drop目標(biāo)對(duì)象(OLE drag&drop 之旅)[未登錄] 2007-06-27 01:40 Peter

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

            我目前想到的方法,就是利用 APIHook, MouseHook 來(lái)攔截這些訊息。看看能不能做到此功能。  回復(fù)  更多評(píng)論   

            # re: 第六部分:實(shí)現(xiàn)Drop目標(biāo)對(duì)象(OLE drag&drop 之旅) 2011-03-15 14:25 laocui

            說好的源碼demo呢?  回復(fù)  更多評(píng)論   

            # re: 第六部分:實(shí)現(xiàn)Drop目標(biāo)對(duì)象(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.   回復(fù)  更多評(píng)論   

            # re: 第六部分:實(shí)現(xiàn)Drop目標(biāo)對(duì)象(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.   回復(fù)  更多評(píng)論   

            # re: 第六部分:實(shí)現(xiàn)Drop目標(biāo)對(duì)象(OLE drag&drop 之旅) 2015-06-11 17:29 meifeng

            IDropTarget可以支持圖片拖拽么  回復(fù)  更多評(píng)論   

            久久w5ww成w人免费| 久久久久亚洲av成人网人人软件 | 国产精品永久久久久久久久久| 99久久精品午夜一区二区| 色综合久久综精品| 2021最新久久久视精品爱 | 久久99国产精品99久久| 国产精品久久久久久久午夜片 | 香港aa三级久久三级老师2021国产三级精品三级在 | 久久人人超碰精品CAOPOREN| 国产精品久久久久蜜芽| 国产精品99久久久久久人| 国内精品久久久久影院网站| 久久久久久精品免费免费自慰 | 丰满少妇高潮惨叫久久久| 久久久久黑人强伦姧人妻| 久久天天躁狠狠躁夜夜躁2O2O | 久久ww精品w免费人成| 狠狠色丁香婷婷久久综合五月 | 欧美午夜精品久久久久久浪潮| 天天躁日日躁狠狠久久| 亚洲伊人久久综合中文成人网| 久久久久中文字幕| AV无码久久久久不卡网站下载 | 亚洲国产精品18久久久久久| 久久久久国产精品麻豆AR影院 | 欧美久久综合性欧美| 亚洲AV乱码久久精品蜜桃| 一本久久综合亚洲鲁鲁五月天| 久久996热精品xxxx| 成人亚洲欧美久久久久 | 91麻豆国产精品91久久久| 欧美色综合久久久久久| 久久国产视屏| 久久久久一本毛久久久| 久久精品无码av| 久久精品国产99久久久香蕉| 国产精品亚洲美女久久久| 精品综合久久久久久88小说 | 一本久道久久综合狠狠爱| 久久久久久久精品妇女99|