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

思勤無邪

上學時,因我年齡最小,個頭也最小,上課時,就像大猩猩堆里的猴一般。如今,這猴偶爾也把最近的一些情況寫在這里。

   :: 首頁 :: 聯系 :: 聚合  :: 管理
  132 Posts :: 1 Stories :: 178 Comments :: 0 Trackbacks

公告

     吾日常三省吾身,曰思、曰勤、曰無邪。

積分與排名

  • 積分 - 186419
  • 排名 - 140

最新隨筆

最新評論

閱讀排行榜

評論排行榜

 最近在寫Shell Extension方面的東西,看到了這篇文章,抄在這里。
原文地址http://blog.csdn.net/vcbear/archive/2002/01/25/5990.aspx
同時也找到了一個與Drag and Drop有關的例子,地址:http://www.codeproject.com/useritems/NSExtDragDrop.asp

vcbear

關于

Windows 的外殼擴展編程,拖放是比較簡單的一種,在網上可以找到不少介紹這個技巧的文章。大部分是介紹使用 MFC COleDropTarget 實現的,我覺得一般使用 COleDropTarget 已經很好了,但是我習慣在一些程序模塊中,完全的不使用 MFC, 比如純 SDK 編程 , 還有用在 ATL 的時候 ,MFC 是相當累贅的。所以 COleDropTarget 在這個意義上講不夠完美。

參考了

MSDN 以及 www.CodeProject.com 的相關文章和代碼( by Thomas Blenkers )之后,我發現拖放實際上主要使用了 IDropTarget 的接口方法,非常簡單,不妨直接面對原始 IDropTarget 實現自己的拖放類。

作為學習筆記,就有了這么一篇文字,以拋磚引玉:

IDropTarget

是系統留給支持拖放的客戶程序的一個純虛接口,事先沒有對接口的任何函數進行實現,而是讓用戶通過實現接口函數來接管拖放的結果。IDropTarget接口有以下成員函數:

  • 基本
COM成員函數

 

QueryInterface

AddRef

Release

  • 接管拖放事件的成員函數:

     

    DragEnter

    DragOver

    DragLeave

    Drop

    也就是說,要在客戶程序里實現以上

    7個函數的實體。

    系統在檢測到拖放發生的時候,會在合適的時候依次調用客戶程序里實現的

    IDropTarget接口相應函數,檢查用戶在這些函數里返回的標志,決定鼠標外觀表現和拖放結果。

     


     

     

    實現

    IDropTarget接口

    為此建立一個基類為IDropTarget的類:

    class CDropTargetEx : public IDropTarget

    IDropTarget接口在OLEIDL.h里定義,為純虛接口。

    CDropTargetEx里依次聲明接口所包含的7個函數,原形為:

    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);

    ULONG STDMETHODCALLTYPE AddRef(void);

    ULONG STDMETHODCALLTYPE Release(void);

    HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState,

    POINTL pt,

    DWORD *pdwEffect);

    HRESULT STDMETHODCALLTYPE DragEnter(IDataObject * pDataObject,

    DWORD grfKeyState, POINTL pt,

    DWORD * pdwEffect);

    HRESULT STDMETHODCALLTYPE DragLeave(void);

    HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj,

    DWORD grfKeyState,

    POINTL pt,

    DWORD __RPC_FAR *pdwEffect);

    (為了實現Addref計數,還有一個ULONG tb_RefCount成員變量是必須的。QueryInterfaceAddRef,Release3個函數的實現是COM知識中最基本的,請參見附例)

    在講解

    IDropTarget其他函數的具體實現之前,有必要介紹一下一個你可能永遠不會直接調用但是確實存在的函數:DoDragDrop函數.此函數在某數據源的數據被拖動的時候就被調用,它負責

    • 檢測目標窗口是否支持拖放,發現目標窗口的
    IDropTarget接口

     

  • 隨時跟蹤鼠標和鍵盤的狀態,根據狀態決定調用其DrageEnter,DragMove,DropDragLeave接口

     

  • 從這些接口獲取客戶程序的返回值,根據這些值和用戶界面以及數據源進行交互。

     

    可以說

    DoDragDrop控制拖放的整個過程,我們要做的,只是將這個過程里發生的事件,接管下來并得到相應的信息,和DoDragDrop進行交互而已。了解了這一點有助于我們理解為什么通過區區一個接口4個函數就可以實現了拖放的效果,因為系統為我們已經做了很多。

    另一個非常重要的

    APIRegisterDragDrop,這個函數的原形是這樣的:

    WINOLEAPI RegisterDragDrop(

    HWND hwnd,

    IDropTarget * pDropTarget

    );

    不用被

    WINOLEAPI嚇到,這是一個宏:

    #define STDAPI EXTERN_C HRESULT STDAPICALLTYPE

    也就是表示一個標準的

    WIN API函數,返回一個HRESULT的值。

    函數

    RegisterDragDrop的作用是告訴系統:某個窗口(hwnd參數指定)可以接受拖放,接管拖放的接口是pDropTarget

    記住在調用

    RegisterDragDrop之前,一定要先調用OleInitialize初始化OLE環境。

    在類

    CDropTargetEx里設計了一個函數

    BOOL CDropTargetEx::DragDropRegister(HWND hWnd,

    DWORD AcceptKeyState=|MK_LBUTTON)

    {

    if(!IsWindow(hWnd))return false;

    HRESULT s = ::RegisterDragDrop (hWnd,this);

    if(SUCCEEDED(s))

    {

    m_hTargetWnd = hWnd;

    m_AcceptKeyState = AcceptKeyState;

    return true;

    }

    else { return false; }

    }

    在這個函數里調用

    RegisterDragDrop,this指針傳入,表示本類實現了IDropTarget.,由本類接管拖放事件。另外順便定義了一下拖放鼠標和鍵盤特性常數,對這個類來說,我希望默認的只接受鼠標左鍵的拖放,所以,默認的AcceptKeyState值是MK_LBUTTON。相關的鍵盤鼠標常數還有MK_SHIFT,MK_ALT,MK_RBOTTON,MK_MBUTTON,MK_BOTTON等幾個,我想這個幾個常數從字面上就可以理解它的意思了。這些常數可以用“位與”的操作組合。

    以下具體討論

    IDropTarget的拖放相關接口函數(4個),這里的拖放對象以文本和文件為主。

     


     

    • DragEnter

       

      當你用鼠標選中了某一個文件或一段文本,并且將鼠標移到某個可以接受拖放(已經調用過

      RegisterDragDrop)的窗口里,DragEnter將第一時間被調用。再看一下其原形:

      HRESULT DragEnter( IDataObject * pDataObject,

           DWORD grfKeyState,

           POINTL pt,

            DWORD * pdwEffect   )

      pDataobject

      是從拖放的原數據中傳遞過來的一個IDataObject接口實例,包含數據對象的一些相關方法,可以通過此接口獲得數據。

      grfKeyState

      DragEnter被調用時當前的鍵盤和鼠標的狀態,包含上面介紹過的鍵盤鼠標狀態常數。

      pt

      表示鼠標所在的點。是以整個屏幕為參考坐標的。

      pdwEffect

      DoDragDrop提供的一個DWORD指針,客戶程序通過這個指針給DoDragDrop返回特定的狀態。有效的狀態包括:

      DROPEFFECT_NONE=0 表示此窗口不能接受拖放。

      DROPEFFECT_MOVE=1 表示拖放的結果將使源對象被刪除

      DROPEFFECT_COPY=2 表示拖放將引起源對象的復制。

      DROPEFFECT_LINK =4 表示拖放源對象創建了一個對自己的連接

      DROPEFFECT_SCROLL=0x80000000表示拖放目標窗口正在或將要進行卷滾。此標志可以和其他幾個合用

      對于拖放對象來說,一般只要使用DROPEFFECT_NONEDROPEFFECT_COPY即可。

      DragEnter里要做什么呢?主要是告知拖放已經進入窗口區域,并判斷是否支持某具體類型的拖放。

      首先,要判斷鍵盤的狀態。在調用DragDropRegister時我傳入了一個AcceptKeyState并將其保存在m_AcceptKeyState成員變量里,現在可以拿它跟這里得到的grfKeyState比較:

      if(grfKeyState!=m_AcceptKeyState )

      {

      *pdwEffect = DROPEFFECT_NONE;

      return S_OK;

      }

      如果鍵盤和鼠標的狀態和我期望的不一樣,那么

      pdwEffect里返回DROPEFFECT_NONE表示不接受拖放。

      然后

      ,判斷拖放過來的IDataObject對象里有沒有我感興趣的數據。

      這里要介紹的是兩個關鍵的結構體

      FORMATETCSTDMEDIUM

      FORMATETC

      OLE數據交換的一個關鍵結構,對某種設備,數據,和相關媒體做了格式上的描述。

      其定義為

      typedef struct tagFORMATETC

      {

      CLIPFORMAT cfFormat;

      DVTARGETDEVICE *ptd;

      DWORD dwAspect;

      LONG lindex;

      DWORD tymed;

      }

      FORMATETC, *LPFORMATETC;

      在這里我們最感興趣的是

      cfFormattymed兩個數據。cfFormat是標準的“粘帖板”數據類型比如CF_TEXT之類。tymed表示數據所依附的媒介,比如內存,磁盤文件,存儲對象等等。其他的成員可以參見MSDN

      一個典型的

      FORMATETC結構變量定義如下:

      FORMATETC cFmt = {(CLIPFORMAT) CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};

      IDataObject提供了一個GetData接口來獲取其實例里包含的數據,比如:

      STGMEDIUM stgMedium;

      ret = pDataObject->GetData(&cFmt, &stgMedium);

      GetData傳入cFmt,以指出所感興趣的數據,并將返回在stgMedium結構里。

      STGMEDIUM

      的定義如下1

      typedef struct tagSTGMEDIUM

      {

      DWORD tymed;

      [switch_type(DWORD), switch_is((DWORD) tymed)]

      union {

      [case(TYMED_GDI)] HBITMAP hBitmap;

      [case(TYMED_MFPICT)] HMETAFILEPICT hMetaFilePict;

      [case(TYMED_ENHMF)] HENHMETAFILE hEnhMetaFile;

      [case(TYMED_HGLOBAL)] HGLOBAL hGlobal;

      [case(TYMED_FILE)] LPWSTR lpszFileName;

      [case(TYMED_ISTREAM)] IStream *pstm;

      [case(TYMED_ISTORAGE)] IStorage *pstg;

      [default] ;

      };

      [unique] IUnknown *pUnkForRelease;

      }STGMEDIUM;

      typedef STGMEDIUM *LPSTGMEDIUM;

      看起來頗為復雜,其實主要是一系列句柄或數據對象接口的聯合,根據數據具體的類型,使用其中之一即可。

      tymedFORMATETC里一樣,指出數據的載體類型(遺憾的是它不能指出具體的標準類型比如CF_TEXT或者其他)。至于pUnkForRelease,是源數據指定的一個接口,用來傳遞給ReleaseStgMedium函數,如果它不為NULL,則ReleaseStgMedium函數使用這個接口釋放數據。如果為NULL,ReleaseStgMedium函數使用默認的IUnknown接口。對于常規的拖放來說,這個對象指針應該為NULL.

      得到了句柄或數據對象接口,也相當于得到了拖放的數據。

      定義一個特定的

      FORMATETC結構實例傳遞給IDataObjectGetData,可以直接詢問和獲取某一種特定的數據。如果我們對我們想要的數據是非常確定的,這是比較有效率的方法。但是如果我們期望能夠對拖放的對象進行自適應的話,我們可以采取枚舉IDataObject里包含的所有數據類型的方案。這就要用到IEnumFORMATETC接口了。

      IEnumFORMATETC接口從IDataObject接口里獲取:

      IEnumFormatETC *pEnumFmt = NULL;

      ret = pDataObject->EnumFormatEtc (DATADIR_GET,&pEnumFmt);

      如果獲取成功,則可以通過

      IEnumFORMATETC接口的Next方法,來枚舉所有的數據格式:

      pEnumFmt->Reset ();

      HRESULT Ret=S_OK

      while(Ret!=S_OK)

      {

      Ret

      =pEnumFmt->Next(1,&cFmt,&Fetched);

      if(SUCCEEDED(ret))

      if( cFmt.cfFormat == CF_TEXT

      ||cFmt.cfFormat == CF_HDROP)

      {

      if(GetDragData(pDataObject,cFmt))

      EnterResult = true;

      }

      }

      第一個參數表示一次獲取的

      FORMATETC結構數據的數量,cFmt是一個FORMATETC指針,指向一個數據緩沖,用來返回FORMATETC數據。,FetchedNext調用后得到的FORMATETC數據個數。一般一次獲取一個,直到Next返回不為S_OK。

      我們可以對每個得到

      cFmt調用IDataObject->GetData方法,但是一般來說,一個數據對象包含的數據不止一種,而且一般有一些自定義的數據類型(關于自定義數據類型,參見:RegisterClipboardFormat,如果要自己實現Drag/Drop源數據,這個函數是有用的),對此我們不感興趣,因為這里只要求處理文本和文件的拖動,為此,只處理cfFormatCF_TEXTCF_HROP的數據:

      GetDragData

      CDropTargetEx類的一個成員函數:

      ///////////////////////////////////////////////////

      //Get The DragData from IDataObject ,save in HANDEL

      BOOL CDropTargetEx::GetDragData(IDataObject *pDataObject,FORMATETC cFmt)

      {

      HRESULT ret=S_OK;

      STGMEDIUM stgMedium;

      ret = pDataObject->GetData(&cFmt, &stgMedium);//GetData(CF_TEXT, &stgMedium);

      if (FAILED(ret))

      {

      return FALSE;

      }

      if (stgMedium.pUnkForRelease != NULL)

      {

      return FALSE;

      }

      ///////////////////////////////////////////

      switch (stgMedium.tymed)

      {

      case TYMED_HGLOBAL:

      {

      LPDRAGDATA pData = new DRAGDATA;

      pData->cfFormat = cFmt.cfFormat ;

      memcpy(&pData->stgMedium,&stgMedium,sizeof(STGMEDIUM));

      m_Array.push_back(pData);

      return true;

      break;

      }

      default:

      // type not supported, so return error

      {

      ::ReleaseStgMedium(&stgMedium);

      }

      break;

      }

      return false;

      }

      在這個成員函數里,根據

      cFmt,調用IDataObject->GetData函數獲得數據(對于CF_TEXTCF_HROP來說,數據的媒介載體tymed都是HGLOBAL類型的)。

      在具體實現的時候,我定義了一個結構:

      typedef struct _DRAGDATA

      {

      int cfFormat;

      STGMEDIUM stgMedium;

      }DRAGDATA,*LPDRAGDATA;

       

      STGMEDIUM和數據類型(比如CF_TEXT,記錄在cfFormat)都記錄在DRAGDATA里。并且使用了一個vector數組,將這個結構保存在數組里。對于不是我們想要的STGMEDIUM數據,我們馬上調用ReleaseStgMedium函數進行釋放,免得造成內存泄露。

      這樣,

      DragEnter的工作就基本完成了,最后需要做的就是給DoDragDrop返回相應的狀態:如果我們獲得了想要的數據就給* pdwEffect賦值為DROPEFFECT_COPY,否則,就是DROPEFFECT_NONE

      如果支持拖放,鼠標形狀將變成一個有接受意義的圖標,否則,是一個拒絕意義的圖標。

       


       

      • DragOver

         

        鼠標拖動對象進入窗口之后,將會在窗口范圍內移動,這時

        DoDragDrop就會調用IDropTargetDragOver接口。其原形為:

        HRESULT DragOver(

        DWORD grfKeyState

        POINTL pt,

        DWORD * pdwEffect

        )

        相對來說對于這個接口方法的實現可以簡單的多:只要根據

        grfKeyState判斷鍵盤和鼠標的狀態是否符合要求,根據pt傳入的鼠標點判斷該點是否支持拖放(比如將拖放區域限制在窗口的一部分的話),然后為*pdwEffect賦值為DROPEFFECT_COPYDROPEFFECT_NONE.當然,還可以做一些你喜歡的事情,比如把鼠標坐標打印到屏幕上。不過為了性能和安全起見,建議不要做延時明顯的操作。

         


         

        • DragLeave:

           

          這個方法沒有傳入參數,相當簡單。

          當拖動的鼠標離開了窗口區域,這個方法將被調用,你可以在這里寫一些清理內存的代碼。在

          CDropTargetEx類里,由于在DragEnternew了一些數據結構,并加到一個指針數組里,所以我必須在這里對此數據進行清理,對此結構里的STDMEDIUM調用ReleaseStgMedium然后Delete該結構。

          另外,如果需要的話,可以通知用戶鼠標指針已經離開了拖放區域。

           


           

          • Drop

            如果鼠標沒有離開窗口,而是在窗口內釋放按紐,那么拖放時間的“放”就在這時發生,

            IDropTarget接口的Drop方法被調用。其原形為

            HRESULT Drop(

            IDataObject * pDataObject,

             

            DWORD grfKeyState,

            POINTL pt,

             

            DWORD * pdwEffect

             

            )

            有些資料建議在這里才調用

            pDataObject->GetData方法獲取數據,在CDropTargetEx類里,數據實際上已經在DragEnter里獲取了。這樣做的理由是我希望一開始就獲得數據,從它本身進行判斷是否支持拖放,而不是在“放”的時候才判斷是否合法數據。

            既然數據已經獲得,那么我就可以從保存數據的指針數組里提取出

            STGMEDIUM數據來,并根據數據的具體格式進行處理(最后一定要記住對STGMEDIUM進行ReleaseStgMedium

            對于

            CF_TEXT類型的數據,STGMEDIUM的成員hGlobal里包含的是一段全局內存數據。獲取這些數據的方法是:

            TCHAR *pBuff = NULL;

            pBuff=(LPSTR)GlobalLock(hText);

            GlobalUnlock(hText);

            則得到一個指向內存數據的指針pBuff。在我這個例子里一般是一段

            "\0"結尾的文本字符串。這樣就實現了文本的拖放。

            對于

            CF_HDROP類型的數據,STGMEDIUM成員hGlobal是一個HDROP類型的句柄。通過這個句柄,可以獲得拖放的文件列表。如:

            BOOL CDropTargetEx::ProcessDrop(HDROP hDrop)

            {

            UINT iFiles,ich =0;

            TCHAR Buffer[MAX_PATH]="";

            memset(&iFiles,0xff,sizeof(iFiles));

            int Count = ::DragQueryFile(hDrop,iFiles,Buffer,0); //Get the Drag _Files Number.

             

            if(Count)

            for (int i=0;i<Count;i++)

            {

            if(::DragQueryFile(hDrop,i,Buffer,sizeof(Buffer)))

            {

            //Got the FileName in Buffer

            }

            }

             

            ::DragFinish(hDrop);

            return true;

            }

            獲得的

            Buffer是就是拖放的文件名,如果拖放的是多個文件,在for循環里可以依次獲取這些文件的文件名。這樣就實現了文件的拖放。

             


             

             

            CDropTargetEx

            類使用非常簡單:

            在客戶窗口的相關文件中,定義一個

            CDropTargetEx實例:CDropTargetEx DropTarget;

            在窗口創建之后,將窗口句柄進行拖放注冊:

            DropTarget.DragDropRegister(hWnd);

            或者

            DropTarget.DragDropRegister(hWndMK_CONTROL|MK_LBUTTON);

            表示鼠標左鍵按下并且按住

            Ctrl鍵的拖放有效;

            對于獲取拖放的結果,我使用的是回調函數方式:

            回調原形

            typedef VOID (_stdcall *DROPCALLBACK)(LPCSTR Buffer,int type);

            在適當的地方(比如窗口的實現

            CPP里)定義函數DropCallback

            void _stdcall DropCallBack(LPCSTR Buffer,int type)

            并且將其地址賦于

            DropTarget實例:

            DropTarget.SetCallBack(DropCallBack);

            這樣,拖放文本到客戶窗口,回調函數將被調用,參數

            Buffer為拖放的文本,formatCF_TEXT。而拖放文件的時候,對每個被拖放的文件都調用一次回調函數,參數Buffer為文件全路徑名,formatCF_HDROP

            示例的

            DropCallBack代碼為:

            void _stdcall DropCallBack(LPCSTR Buffer,int format)

            {

            switch(format)

            {

            case CF_TEXT:

            {

            SetWindowText(hEdit,Buffer);

            break;

            }

            case CF_HDROP:

            {

            TCHAR Buf[2048]="";

            sprintf(Buf,"File : <%s> is Drag and Drop to this Windows ,Open it?",Buffer);

            if(MessageBox(hMainWnd,Buf,"Question",MB_YESNO)==IDYES)

            {

            ShellExecute(0,"open",Buffer,"","",SW_SHOW);

            }

            }

            default:

            break;

            }

            }

             

            總結

            :使用
            IDropTarget實現通用的拖放,只要實現其7個接口,并且對得到的IDataObject用正確的格式(FORMATETC)調用正確的GetData獲取數據,返回DROPEFFECT決定拖放的特征和結果,并處理拖放結果即可。

            要注意的小問題是:

            • 要調用OleInitialize而不是CoInitialize或CoInitializeEx對COM進行初始,否則RegisterDragDrop將不會成功,返回的錯誤是E_OUTOFMEMORY--內存不夠,無法進行該操作。

               

            • 調用ReleaseStgMedium釋放STGMEDIUM里的數據,而不是直接對其hGlobal成員調用CloseHandle.

               

            • 拖放操作關系到兩個進程的數據交換,會將兩個進程都堵塞,直到拖放完成為止,所以,在接管拖放的接口方法中,不要進行過于耗時的運算。

               

            這個例子相當簡單,還可以簡化,比如取消

            vector,將獲得HGLOBAL句柄作為成員變量存儲,或者將獲取數據的操作全部放到Drop方法里。

            對于拖放文件,還有一個更簡單的方法:響應

            WM_DROPFILES消息。步驟是:

            • 對客戶窗口調用
            DropAccepFiles,使該窗口可以接受文件拖放。

             

          • 響應WM_DROPFILES消息,其wParam就是HDROP句柄

             

          • 對此句柄調用DropQueryFiles獲取拖放文件列表并結束拖放,參見上面關于ProcessDrop的代碼

             

            對于拖放的全面闡述,請參見

            MSDN->PlatformSDK Document->User Interface Services->Windows Shell里關于Transferring Shell Objects with Drag-and-Drop and the Clipboard”一章。Windows Shell系統提供了很多接口,讓用戶利用和擴充這些接口,很方便的開發和使用豐富的shell服務,確實是一種很聰明的設計。

             

            例子和代碼
          • posted on 2007-03-05 12:52 思勤無邪 閱讀(5344) 評論(0)  編輯 收藏 引用 所屬分類: C++
            青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
          • <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网站| 国产一本一道久久香蕉| 欧美三级资源在线| 亚洲香蕉在线观看| 日韩视频不卡中文| 国产精品黄页免费高清在线观看| 亚洲深夜福利| 亚洲免费人成在线视频观看| 国产精品一区二区三区四区五区| 午夜一区二区三视频在线观看| 亚洲影院高清在线| 国产综合精品一区| 亚洲第一精品久久忘忧草社区| 久久夜色精品国产欧美乱| 亚洲区国产区| 一本色道久久综合亚洲精品按摩 | 先锋影音国产精品| 欧美一区观看| 在线观看三级视频欧美| 亚洲精品1234| 国产精品家教| 久久精品国产视频| 久久综合久久综合久久综合| 亚洲日本在线观看| 亚洲在线观看免费视频| 国产一区清纯| 亚洲精选在线| 黄色一区二区在线| 亚洲精品免费在线播放| 国产伦精品一区二区三区视频孕妇| 久久久久久久一区二区| 欧美激情综合亚洲一二区| 亚洲欧美在线一区二区| 久热精品视频在线免费观看| 亚洲校园激情| 久久亚洲综合网| 香蕉久久夜色精品国产使用方法| 久久黄色网页| 午夜精品久久| 欧美电影免费观看高清| 久久久美女艺术照精彩视频福利播放| 欧美大胆a视频| 久久久久成人网| 欧美日韩一区自拍| 亚洲国产精品悠悠久久琪琪| 国产欧美在线观看| 一本大道久久精品懂色aⅴ| 影音先锋在线一区| 欧美一区二区高清| 亚洲主播在线| 欧美精品一区二区久久婷婷 | 国产午夜精品久久久久久免费视 | 亚洲特色特黄| 欧美成人一二三| 女人天堂亚洲aⅴ在线观看| 国产精品久久久久一区二区| 亚洲激情电影中文字幕| 国内精品99| 性欧美18~19sex高清播放| 亚洲摸下面视频| 国产精品99久久久久久久女警| 亚洲黑丝在线| 欧美一区二区网站| 欧美一区二区女人| 国产麻豆日韩| 亚洲欧美日韩在线播放| 亚洲永久免费av| 国产精品久久二区二区| 一区二区三区四区五区精品| 一本一本a久久| 欧美日韩一区二区在线视频| 91久久精品国产91性色| 亚洲伦理一区| 欧美人成在线| 一区二区三区国产精华| 亚洲先锋成人| 国产欧美精品日韩精品| 午夜在线电影亚洲一区| 久久久国产成人精品| 黄色综合网站| 欧美大胆成人| 一区二区欧美国产| 欧美中文在线观看国产| 国产亚洲一区在线播放| 久久日韩粉嫩一区二区三区| 欧美激情第六页| 99伊人成综合| 国产精品乱码一区二三区小蝌蚪| 亚洲桃花岛网站| 欧美在线一二三| 今天的高清视频免费播放成人| 久久噜噜噜精品国产亚洲综合 | 在线激情影院一区| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美在线观看视频在线| 一区二区三区在线视频观看| 美日韩丰满少妇在线观看| 亚洲欧洲精品一区二区三区不卡| 一区二区三区日韩| 国产日韩一区二区三区在线播放 | 欧美激情片在线观看| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 国产视频综合在线| 久久久久久免费| 亚洲精选大片| 久久这里只有| 中日韩午夜理伦电影免费| 国产欧美一区二区三区国产幕精品| 久久精品午夜| 欧美成人亚洲成人日韩成人| 亚洲永久免费观看| 亚洲福利视频网| 欧美亚洲一区在线| 亚洲精品久久久久久久久久久久久| 国产精品国产三级国产专区53 | 国产午夜精品视频| 欧美肥婆bbw| 欧美一区国产一区| 夜夜嗨av一区二区三区| 老司机精品视频网站| 午夜久久tv| 一区二区电影免费观看| 国产一区二区三区直播精品电影| 欧美精品亚洲二区| 免费成人小视频| 欧美在线一区二区| 亚洲香蕉在线观看| 亚洲日本欧美天堂| 欧美高清在线观看| 久久精品72免费观看| 亚洲欧美视频在线| 一区二区三区四区五区精品视频| 在线观看视频日韩| 狠狠88综合久久久久综合网| 国产精品久久午夜| 欧美日韩国产免费| 欧美成人综合一区| 久久综合久久综合这里只有精品| 欧美一区二区在线看| 亚洲欧美日韩国产另类专区| 亚洲乱码国产乱码精品精| 亚洲国产第一| 欧美激情一区二区三区蜜桃视频 | 中文av一区二区| 一本一道久久综合狠狠老精东影业| 在线看片一区| 在线视频国产日韩| 一区福利视频| 亚洲国产视频一区| 亚洲娇小video精品| 亚洲国产精品久久久久久女王| 国色天香一区二区| 黄色成人av在线| 亚洲国产成人不卡| 亚洲精品乱码久久久久久蜜桃91 | 在线观看一区二区视频| 精品1区2区| 亚洲激情av| 正在播放欧美一区| 亚洲欧美国产另类| 欧美一二三视频| 久久久九九九九| 欧美激情按摩在线| 日韩亚洲欧美在线观看| 中文日韩在线| 欧美一区二区视频免费观看| 久久国产精品99精品国产| 久久久女女女女999久久| 免费看亚洲片| 欧美亚州一区二区三区| 国产精品自拍视频| 在线观看三级视频欧美| 99v久久综合狠狠综合久久| 亚洲一区自拍| 久久美女性网| 亚洲精品久久久蜜桃| 亚洲视频久久| 美女在线一区二区| 国产精品老女人精品视频| 伊人成人在线视频| 夜夜嗨av一区二区三区免费区| 午夜精品久久| 欧美刺激午夜性久久久久久久| 亚洲精品欧美日韩| 欧美亚洲视频在线观看| 伊人婷婷久久| 午夜精品免费在线| 老色鬼久久亚洲一区二区| 91久久久在线| 欧美亚洲免费| 欧美日韩视频在线第一区| 国产偷自视频区视频一区二区| 91久久黄色| 久久久久免费观看| 亚洲无线观看| 欧美精品少妇一区二区三区| 国产亚洲视频在线观看| 亚洲小说欧美另类社区| 欧美成人综合在线| 欧美在线观看视频|