• <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>

            兔子的技術(shù)博客

            兔子

               :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

            留言簿(10)

            最新評論

            閱讀排行榜

            評論排行榜


            下載源代碼

            Microsoft© Active Accessibility 2.0 is a COM-based technology that improves the  way accessibility aids work with applications running on Microsoft Windows?. It  provides dynamic-link libraries that are incorporated into the operating system  as well as a COM interface and application programming elements that provide  reliable methods for exposing information about user interface elements.      
            基礎
            Microsoft© Active Accessibility 是一種相對較新的技術(shù)(1.0版在1997年5月份推出)。目的是方便身患殘疾的人士使用電腦——可用于放大器、屏幕閱讀器,以及觸覺型鼠標。同樣還可以用來開發(fā)驅(qū)動其它軟件的應用程序,其模擬用戶輸入的能力尤其適合測試軟件的開發(fā)。
            Active Accessibility 的主要思想是提供一種以程序方式訪問UI元素信息或操作這些UI元素的功能。支持這種功能的 UI(User Interface) 元素是可訪問的。在大多數(shù)情況下,這意味著一個UI元素支持 IAccessible 接口。你也可以說在 Active Accessibility 的世界里,一個可訪問的UI元素可表示為 IAccessible 接口。
            每當你需要得到有關(guān)一個元素的信息,在其上執(zhí)行一個動作,或者使用 Active Accessibility 做其它的什么,你通常需要通過使用代表這個元素的 IAccessible 接口的一種方法或者屬性來引用這個元素。

            Active Accessibility 原理
            Active Accessibility? 的核心功能由 OLEACC.DLL 提供的。每次當你調(diào)用一個函數(shù)來返回一個 IAccessible 接口指針,其與一個UI元素相對應,OLEACC.DLL就檢查此元素是否內(nèi)在支持 IAccessible。內(nèi)在的支持意思是該元素的 IAccessible 是用程序?qū)崿F(xiàn)的。
            當一個UI元素不能內(nèi)在的支持 IAccessible 時,OLEACC.DLL 檢查該元素的Windows 類名。如果該類是一個 USER 或者 COMCTL32 支持的類,OLEACC.DLL 就創(chuàng)建一個代理為 UI 元素實現(xiàn) IAccessible 接口。大多數(shù)--但不是全部--COMCTL32 控件都具有被 OLEACC.DLL 支持的 IAccessible 接口。
            內(nèi)在支持 IAccessible 的 UI 元素的例子是定制控件,owner-drawn 和無窗口的控件。因為開發(fā)者創(chuàng)建的程序包含這些UI元素,同樣就實現(xiàn)了這些元素的接口,他們有責任為這些方法和屬性提供正確的支持。
            如果你用標準控件,這也意味著你不必重寫你的應用,這些應用自動與Active Accessibility兼容。
            Active Accessibility 名字是基于 Win32 控件的名字給出的,角色基于控件的功能定義。

            如何得到 IAccessible 接口指針
            每當你需要有關(guān)一個元素的信息,在其上執(zhí)行一個動作,或者使用 Active Accessibility 做其它的什么,你只需要通過使用代表這個元素的 IAccessible 接口的一種方法或者屬性來引用這個元素。
            有幾種方法取得代表一個可訪問 UI 元素的 IAccessible 接口的指針。最普通的方法是使用 Active Accessibility 提供的一種函數(shù),例如 AccessibleObjectFromPoint,AccessibleObjectFromWindow 等等,或者使用 IAccessible 支持的方法,例如 get_accChild,get_accParent。
            IAccessible 接口支持允許你得到各 UI 元素信息的屬性,而其中對于例子程序最重要的屬性是名字、角色和狀態(tài)。
            Active Accessibility SDK提供了一些方便的工具,其中的 Object Inspector 能顯示光標指向的UI元素的屬性。Object Inspector 顯示了Active Accessibility 的世界如何因為具有支持一個選定窗口內(nèi)的 IAccessible 接口的控制而變得通用了。除了搜索有關(guān)元素的信息和通過 IAccessible 接口控制元素以外,Active Accessibility? 還有兩種對于例子程序非常有用的特性:監(jiān)視UI元素發(fā)生的事件和模擬鍵盤、鼠標輸入。由可訪問的元素激發(fā)的事件稱為 WinEvents,當可訪問的元素創(chuàng)建或者名字、狀態(tài)、位置或者鍵盤焦點發(fā)生變化時,就激發(fā)這些事件(事件機制類似于標準的 Windows 的 hook 機制。監(jiān)視事件我們將在后面介紹。)。這些事件的清單見文件 WINABLE.H。每個事件的名字以 EVENT_OBJECT 或 EVENT_SYSTEM 開始。
            好,我們言歸正傳,來介紹如何得到 IAccessible 接口指針。前面已經(jīng)提到過 AccessibleObjectFromWindow 這個 Active Accessibility 提供的函數(shù),從字面上大家可以看出是通過窗口來得到對應的 IAccessible 接口指針。
            因為 IAccessible 接口的數(shù)量比窗口要多(因為大多數(shù)--但不是全部--COMCTL32 控件都有被 OLEACC.DLL 支持的 IAccessible 接口。),使用 Win32 函數(shù)來搜索一個窗口將會比使用 Active Accessibility 樹搜索與該窗口相應的 IAccessible 接口要占用少得多的時間。這就意味著為了提高性能,你應該使用 FindWindow 和 EnumWindows 這樣的 Win32 函數(shù)來找到與希望的UI元素最接近的窗口。當然,在權(quán)衡 Win32 函數(shù)和 Active Accessibility 函數(shù)時,上面的規(guī)則只是使用它們的一般標準而不能盲目的遵照執(zhí)行,重要的是理解它們的本來意義。
            下面結(jié)合代碼介紹一下它的用法。
            我們來得到下面運行窗口的 IAccessible 接口指針。


            圖一

            HWND hWndMainWindow; IAccessible *paccMainWindow = NULL; HRESULT hr; //得到標題為"運行"的窗口的句柄 if(NULL == (hWndMainWindow = FindWindow(NULL, "運行"))) { 	MessageBox(NULL, "沒有發(fā)現(xiàn)窗口!", "錯誤", MB_OK); } else { 	//通過窗口句柄得到窗口的 IAccessible 接口指針。 	if(S_OK == (hr = AccessibleObjectFromWindow(hWndMainWindow,  	                                            OBJID_WINDOW,  	                                            IID_IAccessible, 	                                            (void**)&paccMainWindow))) 	{ 		//……我們可以通過這個指針paccMainWindow進行操作。 		paccMainWindow->Release();         } }    
            現(xiàn)在我們已經(jīng)得到窗口的 IAccessible 接口指針了(paccMainWindow),那么,我們可以干什么呢?我們怎么得到窗口中某個控件的 IAccessible 接口指針呢?我們就以上面的運行窗口為例??纯慈绾蔚玫轿谋究虻?IAccessible 接口指針??!
            首先我們啟動 inspect32.exe,什么?你不知道這是什么東西?趕緊先下載個Active Accessibility SDK看看吧……
            然后,把鼠標放到所關(guān)注的控件上(即上圖中的文本輸入框),你會得到如下信息:


            圖二

            我們現(xiàn)在主要關(guān)注的信息是:Name、Role、Window className。
            Name = "打開(O):" Role = "可編輯文字" Window className = "Edit"  
            當開發(fā)自定義、owner drawn 或者無窗口的控件時,為同一窗口的每個"角色-名字"指定獨一無二的表示是一個非常好的編程習慣。然而,如果由于某種原因,同一窗口中的2個 UI 元素具有同樣的"角色-名字"對,那么就需要增加一個參數(shù)--windows 類--以唯一的來表示這個元素。
            FindChild 函數(shù)顯示了一個基于 Active Accessibility 父/子(你可以理解成父窗口/子窗口的關(guān)系,只是為了便于理解:-P)導航的搜索例程的實現(xiàn)。這個函數(shù)有6個參數(shù)。前4個包含傳遞給函數(shù)的信息,后2個包含了 IAccessible 接口/子ID對(見附錄)。
            下面我們開始取文本輸入框的 IAccessible 接口指針。
            IAccessible*	paccControl = NULL;//輸入框的 IAccessible 接口 VARIANT		varControl;    		//子ID。  FindChild( paccMainWindow,             "打開(O):",             "可編輯文字",             "Edit",             &paccControl,             &varControl )    
            第一個參數(shù)是先前得到的窗口 IAccessible 接口指針。
            第二、三、四個參數(shù)分別是名字、角色、類。
            后2個為返回參數(shù)包含了 IAccessible 接口/子ID對。下面是FindChild的實現(xiàn)。
            BOOL FindChild (IAccessible* paccParent,                           LPSTR szName, LPSTR szRole,                           LPSTR szClass,                           IAccessible** paccChild,                           VARIANT* pvarChild) { 	HRESULT hr; 	long numChildren; 	unsigned long numFetched; 	VARIANT varChild; 	int index; 	IAccessible* pCAcc = NULL; 	IEnumVARIANT* pEnum = NULL; 	IDispatch* pDisp = NULL; 	BOOL found = false; 	char szObjName[256], szObjRole[256], szObjClass[256], szObjState[256]; 	 		//得到父親支持的IEnumVARIANT接口 	hr = paccParent -> QueryInterface(IID_IEnumVARIANT, (PVOID*) & pEnum); 	 	if(pEnum) 		pEnum -> Reset(); 	 //取得父親擁有的可訪問的子的數(shù)目 	paccParent -> get_accChildCount(&numChildren); 	 //搜索并比較每一個子ID,找到名字、角色、類與輸入相一致的。 	for(index = 1; index <= numChildren && !found; index++) 	{ 		pCAcc = NULL;		 		// 如果支持IEnumVARIANT接口,得到下一個子ID //以及其對應的 IDispatch 接口 		if (pEnum) 			hr = pEnum -> Next(1, &varChild, &numFetched);	 		else 	{ 		//如果一個父親不支持IEnumVARIANT接口,子ID就是它的序號 			varChild.vt = VT_I4; 			varChild.lVal = index; 		} 		 		// 找到此子ID對應的 IDispatch 接口 		if (varChild.vt == VT_I4) 		{ 			//通過子ID序號得到對應的 IDispatch 接口 			pDisp = NULL; 			hr = paccParent -> get_accChild(varChild, &pDisp); 		} 		else 			//如果父支持IEnumVARIANT接口可以直接得到子IDispatch 接口 			pDisp = varChild.pdispVal; 		 		// 通過 IDispatch 接口得到子的 IAccessible 接口 pCAcc 		if (pDisp) 		{ 			hr = pDisp->QueryInterface(IID_IAccessible, (void**)&pCAcc); 			hr = pDisp->Release(); 		} 		 		// Get information about the child 		if(pCAcc) 		{ 			//如果子支持IAccessible 接口,那么子ID就是CHILDID_SELF 			VariantInit(&varChild); 			varChild.vt = VT_I4; 			varChild.lVal = CHILDID_SELF; 			 			*paccChild = pCAcc; 		} 		else 			//如果子不支持IAccessible 接口 			*paccChild = paccParent; 		 		//跳過了有不可訪問狀態(tài)的元素 		GetObjectState(*paccChild,  		               &varChild,  		               szObjState,  		               sizeof(szObjState)); 		if(NULL != strstr(szObjState, "unavailable")) 		{ 			if(pCAcc) 				pCAcc->Release(); 			continue; 		} 		//通過get_accName得到Name 		GetObjectName(*paccChild, &varChild, szObjName, sizeof(szObjName)); 		//通過get_accRole得到Role 		GetObjectRole(*paccChild, &varChild, szObjRole, sizeof(szObjRole)); 		//通過WindowFromAccessibleObject和GetClassName得到Class 		GetObjectClass(*paccChild, szObjClass, sizeof(szObjClass)); 		//以上實現(xiàn)代碼比較簡單,大家自己看代碼吧。  			//如果這些參數(shù)與輸入相符或輸入為NULL 		if ((!szName ||  		     !strcmp(szName, szObjName)) &&  		     (!szRole ||  		      !strcmp(szRole, szObjRole)) &&  		     (!szClass ||  		      !strcmp(szClass, szObjClass))) 		{ 			found = true; 			*pvarChild = varChild; 			break; 		} 		if(!found && pCAcc) 		{ 			// 以這次得到的子接口為父遞歸調(diào)用 			found = FindChild(pCAcc,  			                  szName,  			                  szRole,  			                  szClass,  			                  paccChild,  			                  pvarChild); 			if(*paccChild != pCAcc) 				pCAcc->Release(); 		} 	}//End for 	 	// Clean up 	if(pEnum) 		pEnum -> Release(); 	 	return found; }  // UI元素的狀態(tài)也表示成整型形式。因為一個狀態(tài)可以有多個值, //例如可選的、可做焦點的,該整數(shù)是反映這些值的位的或操作結(jié)果。 //將這些或數(shù)轉(zhuǎn)換成相應的用逗號分割的狀態(tài)字符串。 UINT GetObjectState(IAccessible* pacc,                      VARIANT* pvarChild,                      LPTSTR lpszState,                      UINT cchState) {     HRESULT hr;     VARIANT varRetVal; 	     *lpszState = 0; 	     VariantInit(&varRetVal); 	     hr = pacc->get_accState(*pvarChild, &varRetVal); 	 	if (!SUCCEEDED(hr))         return(0); 	 	DWORD dwStateBit; 	int cChars = 0;     if (varRetVal.vt == VT_I4) 	{ 		// 根據(jù)返回的狀態(tài)值生成以逗號連接的字符串。         for (dwStateBit = STATE_SYSTEM_UNAVAILABLE;                 dwStateBit < STATE_SYSTEM_ALERT_HIGH;                 dwStateBit <<= 1)         {             if (varRetVal.lVal & dwStateBit)             {                 cChars += GetStateText(dwStateBit,                                         lpszState + cChars,                                         cchState - cChars); 				*(lpszState + cChars++) = '','';             }         } 		if(cChars > 1) 			*(lpszState + cChars - 1) = ''\0'';     }     else if (varRetVal.vt == VT_BSTR)     {         WideCharToMultiByte(CP_ACP,                              0,                              varRetVal.bstrVal,                              -1,                              lpszState,                             cchState,                              NULL,                              NULL);     } 	     VariantClear(&varRetVal); 	     return(lstrlen(lpszState)); }
            好了!!我們已經(jīng)成功得到文本框的 IAccessible 接口指針了??!現(xiàn)在你可以用這個接口指針為所欲為了?。?!呵呵:)

            在 IAccessible 接口上執(zhí)行動作
            有了表示一個可訪問的 UI 元素的 IAccessible 接口/子ID對,你也有了搜索該元素一個名字(get_accName)、角色(get_accRole)、類和狀態(tài)(get_accState)的方法。讓我們看看你還可以干什么!get_accDescription 能取得UI元素的描述,get_accValue 能取得一個值。
            最重要的函數(shù)之一是 accDoDefaultAction。每個可訪問的UI元素都有一個缺省定義的動作。例如,一個按鈕的缺省動作是"按下這個按鈕",一個檢查框的缺省動作是"不選"。為了確定一個元素的缺省動作,請參考 Active Accessibility 文檔或者調(diào)用 get_accDefaultAction。
            如果我想起動注冊表編輯器,該怎么辦呢?如果是我們手動做的話,無非是在文本輸入框輸入"regedit",然后按確定按鈕,就這么簡單。下面我們來看看用 Active Accessibility 是怎么來實現(xiàn)的。
            //在文本輸入框輸入"regedit" if(1 == FindChild (paccMainWindow, "打開(O):",                     "可編輯文字",                     "Edit",                     &paccControl,                     &varControl)) { 	//在這里修改文本編輯框的值 	hr = paccControl->put_accValue(varControl,  	                                  CComBSTR("regedit")); 	paccControl->Release(); 	VariantClear(&varControl); } 		 // 找到確定按鈕,并執(zhí)行默認動作。 if(1 == FindChild (paccMainWindow,                     "確定",                     "按下按鈕",                     "Button",                     &paccControl,                     &varControl)) { 	//這里執(zhí)行按鈕的默認動作,即"按下這個按鈕" 	hr = paccControl->accDoDefaultAction(varControl); 	paccControl->Release(); 	VariantClear(&varControl); }
            現(xiàn)在,你會發(fā)現(xiàn)已經(jīng)成功啟動了注冊表編輯器!!

            模擬鍵盤和鼠標輸入
            讓我們假設你需要操作一個新的不完全支持 Windows 消息和 IAccessible 接口方法的 UI 元素。如果它不支持你需要的消息和方法,最簡單的解決辦法就是模擬鍵盤和鼠標輸入。例如,你可以用Tab模擬轉(zhuǎn)移到期望的控件。
            使你能夠?qū)崿F(xiàn)這些的函數(shù)就是 SendInput 一個一般的USER API。雖然不屬于Active Accessibility,把他們聯(lián)合使用很自然。
            SendInput 接受三個參數(shù):要執(zhí)行的鼠標鍵盤動作個數(shù)、INPUT結(jié)構(gòu)數(shù)組和結(jié)構(gòu)數(shù)組的大小。每個INPUT結(jié)構(gòu)描述一個要執(zhí)行的動作。注意,按下一個按鈕和釋放一個按鈕是兩個不同的動作,所以必須創(chuàng)建兩個不同的INPUT結(jié)構(gòu)。
            下面的代碼將模擬 ALT+F4 按鍵來關(guān)閉窗口。
            INPUT input[4];	 memset(input, 0, sizeof(input));  //設置模擬鍵盤輸入 input[0].type = input[1].type = input[2].type = input[3].type = INPUT_KEYBOARD; input[0].ki.wVk  = input[2].ki.wVk = VK_MENU; input[1].ki.wVk  = input[3].ki.wVk = VK_F4;  // 釋放按鍵,這非常重要 input[2].ki.dwFlags = input[3].ki.dwFlags = KEYEVENTF_KEYUP;  SendInput(4, input, sizeof(INPUT));
            具體用法大家還是查MSDN吧,這里就不羅嗦了?。。海?br />
            監(jiān)視WinEvents
            監(jiān)視 WinEvents 非常像通過 Windows Hook 監(jiān)視 Windows 消息。最重要的區(qū)別就是從另一個進程監(jiān)視 UI 元素發(fā)出的 WinEvents 時,你不需要創(chuàng)建一個單獨的DLL來注入那個進程的地址空間。
            監(jiān)視 WinEvents 有兩種選擇:通過設置 SetWinEventHook 函數(shù)的最后一個參數(shù)來確定是在上下文之外還是之內(nèi)監(jiān)視。如果是在上下文之外,不需要額外的DLL,回調(diào)函數(shù)運行在目標進程之外。如果是在上下文之內(nèi),回調(diào)函數(shù)必須放在額外的DLL,并注入目標進程的地址空間。第二種方法寫代碼比較麻煩,但是運行效率高。
            好,現(xiàn)在回到上面的例子。上面例子能夠執(zhí)行的前提條件是能夠找到標題為"運行"的窗口?,F(xiàn)在可以先檢查運行窗口是否存在,如果不存在就設置WinEvents 鉤子去監(jiān)視,直到"運行"窗口被創(chuàng)建??聪旅娲a:
            if(NULL == (hWndMainWindow = FindWindow(NULL, szMainTitle))) { hEventHook = SetWinEventHook( 	EVENT_MIN,	// eventMin ID 	EVENT_MAX,	// eventMax ID 	NULL,		// always NULL for outprocess hook 	WinCreateNotifyProc,		// call back function 	0,				// idProcess 	0,				// idThread           // always the same for outproc hook 	WINEVENT_SKIPOWNPROCESS | WINEVENT_OUTOFCONTEXT); }    
            第一、二個參數(shù)用來指定監(jiān)視事件的范圍。第四個參數(shù)是定義的回調(diào)函數(shù)。
            下面是回調(diào)函數(shù):
            void CALLBACK WinCreateNotifyProc(  HWINEVENTHOOK  hEvent,  DWORD   event,  HWND    hwndMsg,  LONG    idObject,  LONG    idChild,  DWORD   idThread,  DWORD   dwmsEventTime  ) { 	 	if( event != EVENT_OBJECT_CREATE) 		return; 	 	char bufferName[256]; 	IAccessible *pacc=NULL; 	VARIANT varChild;     VariantInit(&varChild); 	//得到觸發(fā)事件的 UI 元素的 IAccessible 接口/子ID對 	HRESULT hr= AccessibleObjectFromEvent(hwndMsg,  	                                      idObject,  	                                      idChild,  	                                      &pacc,  	                                      &varChild); 	 	if(!SUCCEEDED(hr)) 	{ 		VariantClear(&varChild); 		return; 	} 	//得到 UI 元素的Name,并比較,如果是"運行"就發(fā)送消息給主線程。 	GetObjectName(pacc, &varChild, bufferName, sizeof(bufferName)); 	if(strstr(bufferName, szMainTitle)) 		PostThreadMessage(GetCurrentThreadId(),  		                  WM_TARGET_WINDOW_FOUND,  		                  0,  		                  0); 	 	return; }    
            恩…………,一個應用基本成型了,雖然比較簡單。就先寫這么多吧,請關(guān)注后續(xù)介紹。

            附錄:

            關(guān)于IAccessible 接口/子ID對:
            讓我們來考慮這樣一個控件,他支持 IAccessible 接口并且包含一些子控件,比如 listbox 就包含很多 items 。有兩種方法讓他可以被訪問:第一種,提供listbox的 IAccessible 接口和每一個 item 自己的 IAccessible 接口。另一種是只提供一個控件的 IAccessible 接口,這個接口能夠提供基于某種識別方法來訪問每一個子控件的功能。
            第一種方法,需要為這個控件和每一個子控件創(chuàng)建單獨的 COM 對象,這會比第二種方法(每一個子控件不支持自己的 IAccessible 接口,而是通過父接口來訪問)增加內(nèi)存消耗。第二種方法里,通過增加一個參數(shù)--子ID--同父的IAccessible 接口一起表示這個子控件。子ID 是一個 VT_I4 型的 VARIANT 值,包含一個由程序決定的獨特的值,或只是一個子控件的序號。序號意味著第一個子控件的ID為1,第二個子控件的ID為2,依次增長!
            這樣,如果一個子控件不支持自己的 IAccessible 接口,而其父控件支持,那么這個子控件可以用它的父控件的 IAccessible 接口/子ID 對來表示。通常,一個支持 IAccessible 接口的父UI元素也是通過這樣的 IAccessible 接口/子對表示的,這時候其子ID號為 CHILDID_SELF (就是0)。
            記住,子ID號總是相對于 IAccessible 接口的。例如,一個可訪問的元素可以同相對于其父 IAccessible 接口的一個非子 CHILDID_SELF 的 ID 及其父IAccessible 接口表示,如果他支持 IAccessible 接口,此元素的子ID就是相對于自己 IAccessible 接口的CHILDID_SELF。
            呵呵,翻譯的有點別扭,意思就是說,如果這個控件支持 IAccessible 接口,那么它的子ID就是0(CHILDID_SELF),可以用它自己的 IAccessible 接口和0這個對來表示這個控件。如果控件不支持 IAccessible 接口,就用它父控件的 IAccessible 接口,和一個相對于父 IAccessible 接口的子ID來表示。哎呀??!不知道說明白沒有。郁悶?。。。?br />
            注:
            我也是剛開始學習怎么使用MSAA,但是苦于很難找到中文資料。希望這篇文章對大家能有所幫助。由于了解的還很膚淺,錯誤難免,望諒解!?。海?br /> 還有,這篇文章基本編譯自Dmitri Klementiev的《Software Driving Software: Active Accessibility-Compliant Apps Give Programmers New Tools to Manipulate Software》,只是按自己的理解重新編排了一下,如果覺得不符合自己的學習習慣可以看原文。并且我的文章省略了很多東西,呵呵。

            參考資料:
            • 1、 Dmitri Klementiev寫的《Software Driving Software: Active Accessibility-Compliant Apps Give Programmers New Tools to Manipulate Software》及其源程序。http://msdn.microsoft.com/msdnmag/issues/0400/aaccess/default.aspx
            • 2、 MSDN中的相關(guān)章節(jié)。 


              轉(zhuǎn)自:http://www.vckbase.com/document/viewdoc/?id=883
            posted on 2011-09-21 22:33 會飛的兔子 閱讀(1163) 評論(0)  編輯 收藏 引用 所屬分類: 系統(tǒng)API,底層技術(shù)
            欧美国产精品久久高清| 亚洲国产精品久久久天堂| 久久精品国产只有精品2020| 久久综合久久综合久久综合| 久久91这里精品国产2020| 久久久久久精品无码人妻| 国产精品久久久天天影视| 亚洲国产成人精品91久久久| 久久精品国产久精国产思思| 久久亚洲中文字幕精品一区| 久久A级毛片免费观看| 久久久艹| 国产女人aaa级久久久级| 久久精品国产久精国产果冻传媒 | 无码任你躁久久久久久老妇App| 久久久久久精品免费免费自慰 | 免费无码国产欧美久久18| 2021精品国产综合久久| 亚洲熟妇无码另类久久久| 久久综合伊人77777麻豆| 青青草原1769久久免费播放| 77777亚洲午夜久久多人| 久久99亚洲综合精品首页| 久久不射电影网| 久久综合给合久久狠狠狠97色 | 亚洲AV日韩AV天堂久久| 亚洲国产成人精品久久久国产成人一区二区三区综 | 亚洲成色WWW久久网站| 久久91精品综合国产首页| 欧美777精品久久久久网| 国产成人精品久久二区二区| 久久亚洲私人国产精品| 人妻无码久久一区二区三区免费 | 久久国产三级无码一区二区| 久久综合久久综合九色| 久久综合丝袜日本网| 天天爽天天爽天天片a久久网| 国产精品久久久久天天影视| 久久精品这里热有精品| 亚洲一区二区三区日本久久九| 国产人久久人人人人爽|