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

cexer

cexer
posts - 12, comments - 334, trackbacks - 0, articles - 0
  C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

轉(zhuǎn)帖請(qǐng)注明出處 http://www.shnenglu.com/cexer/archive/2008/08/18/59285.html

  拋棄了上一個(gè)消息機(jī)制,因?yàn)樗膶?shí)現(xiàn)不得不多用了幾個(gè)模板函數(shù),在使用的時(shí)候有代碼膨脹的現(xiàn)象。雖然其程度不如 win32gui,SmartWin,不過(guò)因?yàn)楸救擞悬c(diǎn)極端,所以相當(dāng)?shù)夭粷M意。于是又開始寫一個(gè)新的消息機(jī)制,它的外表看起來(lái)像是 SmartWin++ 和 AWT 的混血兒。 

  SmartWin++ 的想法極富創(chuàng)意,但是其實(shí)現(xiàn)卻不怎么漂亮,就像魯迅先生說(shuō)的:離的越近,傷痕和不足越容易看見。或者更專業(yè)一點(diǎn),借用一個(gè)朋友的 QQ 簽名說(shuō)的:每個(gè)整潔的接口后面,都有一個(gè)齷齪的實(shí)現(xiàn)。仔細(xì)看過(guò)它的的齷齪實(shí)現(xiàn)之后,我想大概是永遠(yuǎn)不會(huì)用它寫程序了,不過(guò)同樣要對(duì)作者的靈感表示敬佩和感謝。自己寫這個(gè)框架到后來(lái),竟然也有向 SmartWin++ 靠攏的趨勢(shì)。

  AWT 的接口和實(shí)現(xiàn)很漂亮,不過(guò)看它在 C++ 上的這個(gè)實(shí)現(xiàn),因?yàn)?C++ 與 java 一些語(yǔ)言特性上的差別,導(dǎo)致這個(gè)照搬過(guò)來(lái)的實(shí)現(xiàn)并不適用于 C++,一是性能很低,二是使用起來(lái)會(huì)比較麻煩。大概是因?yàn)樽髡咭繎]跨平臺(tái)的因素,所以縛手縛腳的沒(méi)有能放開寫。其實(shí)在這個(gè)基礎(chǔ)上好好地優(yōu)化改進(jìn)一下,會(huì)是個(gè)很不錯(cuò)的框架。

  自己的這個(gè)框架的消息機(jī)制是介于 SmartWin++ 的 Aspects 與 AWT 的 Listener 這間的一種機(jī)制。底層實(shí)現(xiàn)很簡(jiǎn)單,在上面再包裝出一些 Listener 。這些 Listener 的結(jié)構(gòu)看起來(lái)像 AWT 的 Listener,完成的功能卻是 SmartWin++ 的 Aspects 的功能。可以對(duì)比一下看看


AWT ( C++的一個(gè)移植版)

  比如說(shuō)在 AWT 當(dāng)中鼠標(biāo)相關(guān)的 Listener 大概是這樣的:

   1: class MouseListener : public EventListener 
   2: {
   3:  
   4: public:
   5:  
   6:     virtual void mouseClicked( MouseEvent& ) = 0;
   7:     virtual void mousePressed( MouseEvent& ) = 0;
   8:     virtual void mouseReleased( MouseEvent& ) = 0;
   9:     virtual void mouseEntered( MouseEvent& ) = 0;
  10:     virtual void mouseExited( MouseEvent& ) = 0;
  11:  
  12: };

 
  如果一個(gè)類想處理自己的鼠標(biāo)消息,則必須在這個(gè)類上派生,然后調(diào)用addListener 將自己添加進(jìn) Listeners 當(dāng)中即可。比如說(shuō)要寫一個(gè)按鈕類 Button* button,它要處理自己的鼠標(biāo)按下的消息,代碼大概會(huì)是這個(gè)樣子:

   1: class Button:public Component,
   2:             ,public MouseListener  // 從 MouseListener 接口派生
   3:             ,public SomethingElse
   4: {
   5:     Button()
   6:     {
   7:         addMouseListener( this );
   8:  
   9:         // do something else
  10:     }
  11:  
  12:     virtual void mousePressed( MouseEvent& me )
  13:     {
  14:         // button is pressed
  15:         // do something
  16:     }
  17: };


  如果還有外部的類想要處理這個(gè)按鈕的鼠標(biāo)按下消息,那么這個(gè)外部的類也必須從 MouseListener 派生,然后將自己添加進(jìn)按鈕的 Listeners 當(dāng)中。代碼大概像這個(gè)樣子:

   1: // 從 MouseListener 接口派生
   2: class MouseEventTester:public MouseListener,public SomethingElse
   3: {
   4:     // 實(shí)現(xiàn) mousePreseed 函數(shù)
   5:     virtual void mousePressed( MouseEvent& )
   6:     {
   7:         // mouse is pressed
   8:         // do something;
   9:     }
  10: };
  11:  
  12: // 添加到按鈕的鼠標(biāo) Listener 列表當(dāng)中
  13:  
  14: Button* button = new Button();
  15: button->addMouseListener( new MouseEventTester() );


  AWT 都是使用虛函數(shù)實(shí)現(xiàn)的,其性能上會(huì)有一些問(wèn)題,誰(shuí)叫是從 java 移植的呢。而且消息處理函數(shù)的名字被限定死了,至少那些有特定名字習(xí)慣(比如很多人寫的函數(shù)非得用大寫字母開始)的程序會(huì)一定不會(huì)滿意的。另外,消息的種類也被接口限制死了,除了接口提供的 mousePressed,mouseClicked 等消息的函數(shù),要添加其它消息的處理能力就比較麻煩。


SmartWin++

  再看看 SmartWin++ Aspect 方式。SmartWin++ 關(guān)于鼠標(biāo)消息的 Aspect 像這個(gè)樣子:

   1:  
   2: template</*一大堆模板參數(shù)*/>
   3: class AspectMouseClicks
   4: {
   5:     void onLeftMouseUp( Handler eventHandler );
   6:     void onLeftMouseUp( Handler eventHandler);
   7:  
   8:     void onLeftMouseDown( Handler eventHandler);
   9:     void onLeftMouseDown( Handler eventHandler);
  10:  
  11:     void onMouseMove( Handler eventHandler);
  12:     void onMouseMove( Handler eventHandler);
  13:  
  14:     // 其它一些鼠標(biāo)消息
  15:     // .....
  16:  
  17: protected:
  18:     virtual ~AspectMouseClicks()
  19:     {}
  20: };


  還是寫一個(gè)按鈕,它想處理自己的鼠標(biāo)按下消息,代碼大概像這樣:

   1: class Button:public AspectMouseClicks</*一大堆參數(shù)*/>
   2: {
   3:     Button()
   4:     {
   5:         onLeftMouseUp( &Button::mousePressed );
   6:     }
   7:     
   8:     void mousePressed( MouseEvent& me )
   9:     {
  10:         // mouse is pressed
  11:         // do something
  12:     }
  13: };


  而因?yàn)?SmartWin++ 的設(shè)計(jì)上的問(wèn)題,除了按鈕本身之外,僅有按鈕的祖先窗口(包括父窗口)對(duì)象也能夠處理它的鼠標(biāo)消息。比如一個(gè)窗口 TestWindow,在它之上創(chuàng)建了按鈕 Button,則這個(gè)按鈕的消息要么被 TestWindow 處理,要么被自己處理,不能被其它的外部類或函數(shù)處理。TestWndow 當(dāng)中處理這個(gè)按鈕的鼠標(biāo)按下的消息的代碼大概像這樣:

   1: class TestWindow:public Something
   2: {
   3:  
   4: public:
   5:  
   6:     TestWindow()
   7:     {
   8:         Button* button = createButton();
   9:         button->onLeftMouseUp( &TestWindow::mousePressed );
  10:     }
  11:  
  12:     void mousePressed( MouseEvent& me )
  13:     {
  14:         // mouse is pressed
  15:         // do something
  16:     }
  17: };


  SmartWin++ 表面上看起來(lái)是使用的函數(shù)指針,效率應(yīng)該會(huì)比 AWT 的虛函數(shù)高一些,其它不然。看看上面的代碼,指定消息處理函數(shù)的時(shí)候,并沒(méi)有把消息處理函數(shù)的擁有者的指針傳進(jìn)去。因此在用函數(shù)指針調(diào)用函數(shù)的時(shí)候,SmartWin++ 框架為了尋找到函數(shù)的擁有者指針,用了很齷齪低效的的一個(gè)方法,也正是這樣的方法,使得父窗口類之外的其它類或函數(shù)不可能參與到消息的處理當(dāng)中來(lái)。

自己的機(jī)制:
  
  像上面說(shuō)的,自己新寫的這個(gè)消息機(jī)制介于 AWT 的 Listeners 與 SmartWin 的 Aspects 之間。這個(gè)框架當(dāng)中的MouseListener 的定義看起來(lái)像這樣:

   1: <typename TImpl>
   2: class MouseListener
   3: {
   4:  
   5: public:
   6:  
   7:     void onMouseClicked( TOwner* owner,MemberHandler handler );
   8:     void onMousePressed( TOwner* owner,MemberHandler handler );
   9:     void onMouseReleased( TOwner* owner,MemberHandler handler );
  10:     void onMouseDblclk( TOwner* owner,MemberHandler handler );
  11:     void onMouseEntered( TOwner* owner,MemberHandler handler );
  12:     void onMouseExited( TOwner* owner,MemberHandler handler );
  13:     void onMouseMoved( TOwner* owner,MemberHandler handler );
  14:  
  15: };


  有鼠標(biāo)消息的 GUI 類都已經(jīng)從這個(gè) Listener 繼承,比如說(shuō)如果要寫一個(gè)按鈕類,想要它有響應(yīng)鼠標(biāo)按下消息的能力,則代碼大概是這樣:

   1:  
   2: // 從 MouseListener 繼承
   3: class Button:public MouseListener<Button>
   4:             ,public SomethingElse
   5: {
   6:  
   7: public:
   8:  
   9:     Button()
  10:     {
  11:         onMousePressed( this,&Button::mousePressed );
  12:     }
  13:     
  14:     void mousePressed( UINT keys,POINT cursor )
  15:     {
  16:         // mouse is pressed
  17:         // do something
  18:     }
  19: };


  因?yàn)?Button 已經(jīng)從 MouseListener 派生,所以所有它的祖先窗口和父窗口都能用 MouseListener 的函數(shù) onMousePressed 來(lái)注冊(cè)自己的處理函數(shù):

   1: class TestWindow
   2: {
   3:  
   4: public:
   5:  
   6:     TestWindow()
   7:     {
   8:         Button* button = new Button();
   9:         button->onMousePressed( this,&TestWindow::mousePressed );
  10:     }
  11:  
  12:     void mousePressed( Widget* source,UINT keys,POINT cursor )
  13:     {
  14:         // mouse is pressed
  15:         // do something
  16:     }
  17: };


  需要注意的,這個(gè) mousePressed 函數(shù)多了一個(gè) Widget* 類型的 source 參數(shù),以便在一個(gè)函數(shù)處理多個(gè) GUI 對(duì)象的鼠標(biāo)消息的時(shí)候,用來(lái)區(qū)別鼠標(biāo)消息是來(lái)自哪一個(gè) GUI 對(duì)象。因?yàn)樵诎粹o類當(dāng)中,知道是處理的自己的消息,所以就不需要這樣一個(gè)額外的參數(shù)。

  到目前為止看起來(lái)好像都跟 SmartWin++ 沒(méi)有多大的區(qū)別。不過(guò)這個(gè)框架允許任何類甚至全局函數(shù)也能處理任何 GUI 對(duì)象對(duì)外公開的消息。比如說(shuō)有一個(gè)額外的類想處理上面那個(gè)按鈕的鼠標(biāo)按下消息,其代碼大概像這樣:

   1: // 從 MouseListener 接口派生
   2: class MouseEventTester:public MessageListener
   3: {
   4:  
   5: public:
   6:  
   7:     void mousePressed( Widget* source,UINT keys,POINT cursor )
   8:     {
   9:         // mouse is on source,and it is pressed
  10:         // do something;
  11:     }
  12: };
  13:  
  14:  
  15: MouseEventTester* tester = new MouseEventTester();
  16:  
  17: // 添加到按鈕的鼠標(biāo) Listener 列表當(dāng)中
  18: Button* button = new Button();
  19: button->addListener( &tester );


  這個(gè)類不用派生自 MouseListener,而是直接派生自了底層的 MessageListener(其實(shí) MessageListener 對(duì)外只提供了一個(gè)函數(shù) handleMessage)

  除了上面的方式,也可以這樣干,更簡(jiǎn)單一些,甚至不用任何派生。

   1: // 從 MouseListener 接口派生
   2: class MouseEventTester
   3: {
   4:  
   5: public:
   6:  
   7:     void mousePressed( Widget* source,UINT keys,POINT cursor )
   8:     {
   9:         // mouse is on source,and it is pressed
  10:         // do something;
  11:     }
  12: };
  13:  
  14:  
  15: MouseEventTester* tester = new MouseEventTester();
  16:  
  17:  
  18:  
  19:  
  20: // 直接添加消息處理函數(shù)
  21: Button* button = new Button();
  22: button->onMousePressed( tester,&MouseEventTester::mousePressed );


  也提供對(duì)全局函數(shù)的支持比如:

   1:  
   2: // 全局函數(shù)
   3: void mousePressed( Widget* source,UINT keys,POINT cursor )
   4: {
   5:     // mouse is on source,and it is pressed
   6:     // do something
   7: }
   8:  
   9:  
  10: // 直接添加為消息處理函數(shù)
  11: Button* button = new Button();
  12: button->onMousePressed( &::mousePressed );


  這個(gè)版本的消息機(jī)制雖然不如上一個(gè)消息機(jī)制方便,需要手動(dòng)地消息映射,不過(guò)極大地增加了靈活性,消除了代碼膨脹的問(wèn)題。

  下面是一個(gè)完整的測(cè)試程序代碼:

   1: // cexer
   2: #include "../../cexer/include/GUI/panel.h"
   3: #include "../../cexer/include/GUI/window.h"
   4: #include "../../cexer/include/GUI/button.h"
   5: #include "../../cexer/include/GUI/checkbox.h"
   6: #include "../../cexer/include/GUI/radiobox.h"
   7: #include "../../cexer/include/GUI/GUI.h"
   8:  
   9: using namespace cexer;
  10: using namespace cexer::gui;
  11: using namespace cexer::gdi;
  12:  
  13: // c++ std
  14: #include <iostream>
  15: using namespace std;
  16:  
  17:  
  18: class TestWindow:public Window
  19: {
  20:  
  21: public:
  22:  
  23:     TestWindow( ):Window( NULL,_T("test window") )
  24:     {
  25:         onCreated( this,&TestWindow::windowCreated );
  26:         onClosing( this,&TestWindow::windowClosing );
  27:         onDestroy( this,&TestWindow::windowDestroy );
  28:         onResized( this,&TestWindow::windowResized );
  29:         onErasing( this,&TestWindow::windowErasing );
  30:  
  31:         onMouseClicked( this,&TestWindow::mouseClicked );
  32:         onMouseEntered( this,&TestWindow::mouseEntered );
  33:         onMouseExited(  this,&TestWindow::mouseExited );
  34:         onMousePressed( this,&TestWindow::mousePressed );
  35:         onMouseReleased( this,&TestWindow::mouseReleased );
  36:     }
  37:  
  38: public:
  39:  
  40:     LRESULT windowCreated( Widget*,CREATESTRUCT& )
  41:     {
  42:         wcout<<L"創(chuàng)建成功!"<<endl;
  43:  
  44:         Panel* panel = new Panel( this,_T("panel") );
  45:         panel->create( _T(""),10,10 );
  46:         panel->onResized( this,&TestWindow::windowResized );
  47:  
  48:         Button* button = new Button( panel,_T("button") );
  49:         button->create( _T("測(cè)試按鈕"),10,10 );
  50:         button->onClicked( this,&TestWindow::buttonClicked );
  51:  
  52:         Checkbox* checkbox = new Checkbox( panel,_T("checkbox") );
  53:         checkbox->create( _T("測(cè)試多選框"),10,40 );
  54:         checkbox->onClicked( this,&TestWindow::buttonClicked );
  55:  
  56:         
  57:         Radiobox* radiobox = new Radiobox( panel,_T("radiobox") );
  58:         radiobox->create( _T("測(cè)試單選框"),10,70 );
  59:         radiobox->onClicked( this,&TestWindow::buttonClicked );
  60:  
  61:         return 0;
  62:     }
  63:  
  64:     LRESULT windowDestroy( Widget* )
  65:     {
  66:         wcout<<L"銷毀成功!"<<endl;
  67:         ::PostQuitMessage(0);
  68:  
  69:         return 0;
  70:     }
  71:  
  72:     LRESULT windowClosing( Widget* )
  73:     {
  74:         if ( IDNO == confirmBox(_T("確定關(guān)閉窗口?")) )
  75:         {
  76:             return 0;
  77:         }
  78:  
  79:         destroy();
  80:  
  81:         return 0;
  82:     }
  83:  
  84:     LRESULT windowErasing( Widget*,Canvas& canvas )
  85:     {
  86:         canvas.fillRect( clientBounds() );
  87:         canvas.drawText( 100,100,_T("測(cè)試窗口") );
  88:  
  89:         return 0;
  90:     }
  91:  
  92:     LRESULT windowResized( Widget* source,UINT,SIZE size )
  93:     {
  94:         if ( source->name() == m_name )
  95:         {
  96:             long panelWidth  = ( size.cx-20 );
  97:             long panelHeight = ( size.cy-20 );
  98:  
  99:             resizeChild( _T("panel"),panelWidth,panelHeight );
 100:         }
 101:         else if ( source->name() == _T("panel") )
 102:         {
 103:             long childWidth  = ( size.cx-20 );
 104:             long childHeight = 20;
 105:  
 106:             resizeChild( _T("button")  ,childWidth,childHeight );
 107:             resizeChild( _T("checkbox"),childWidth,childHeight );
 108:             resizeChild( _T("radiobox"),childWidth,childHeight );
 109:         }
 110:         
 111:         return 0;
 112:     }
 113:  
 114:     LRESULT buttonClicked( Button* button )
 115:     {
 116:         messageBox( button->text() + _T("被點(diǎn)擊了!") );
 117:         return 0;
 118:     }
 119:  
 120:  
 121:     LRESULT mouseClicked( Widget*,UINT,POINT cursor)
 122:     {
 123:         wcout<<L"鼠標(biāo)點(diǎn)擊\t"<<L"位置";
 124:         wcout<<L"("<<cursor.x<<L","<<cursor.y<<L")"<<endl;
 125:         return 0;
 126:     }
 127:  
 128:     LRESULT mouseEntered( Widget*,UINT,POINT cursor )
 129:     {
 130:         wcout<<L"鼠標(biāo)進(jìn)入\t"<<L"位置";
 131:         wcout<<L"("<<cursor.x<<L","<<cursor.y<<L")"<<endl;
 132:         return 0;
 133:     }
 134:  
 135:     LRESULT mouseExited( Widget*,UINT,POINT cursor )
 136:     {
 137:         wcout<<L"鼠標(biāo)離開\t"<<L"位置";
 138:         wcout<<L"("<<cursor.x<<L","<<cursor.y<<L")"<<endl;
 139:         return 0;
 140:     }
 141:  
 142:     LRESULT mousePressed( Widget*,UINT,POINT cursor )
 143:     {
 144:         wcout<<L"鼠標(biāo)按下\t"<<L"位置";
 145:         wcout<<L"("<<cursor.x<<L","<<cursor.y<<L")"<<endl;
 146:         return 0;
 147:     }
 148:  
 149:     LRESULT mouseReleased( Widget*,UINT,POINT cursor )
 150:     {
 151:         wcout<<L"鼠標(biāo)釋放\t"<<L"位置";
 152:         wcout<<L"("<<cursor.x<<L","<<cursor.y<<L")"<<endl;
 153:         return 0;
 154:     }
 155:  
 156: };
 157:  
 158:  
 159:  
 160: int _tmain( int argc,TCHAR** argv )
 161: {
 162:     CEXER_GUI_THREAD();
 163:  
 164:     wcout.imbue( std::locale("") );
 165:  
 166:     TestWindow* window = new TestWindow();
 167:     window->create();
 168:  
 169:     return runGUIthread();
 170: }

Feedback

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2008-08-19 12:37 by Touchsoft
只看了開頭的鼠標(biāo)消息定義
如果一個(gè)類想處理自己的鼠標(biāo)消息,則必須在這個(gè)類上派生,然后調(diào)用addListener
像Decorator Pattern。

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2008-08-19 14:03 by 空明流轉(zhuǎn)
函數(shù)指針比虛方法更慢。。。

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2008-08-19 16:11 by cexer
@空明流轉(zhuǎn)
的確是半斤八兩,不過(guò)虛函數(shù)還得查一下虛表,生成的匯編代碼會(huì)有多幾個(gè)寄存器操作,而靜態(tài)的函數(shù)指針是直接call地址的。

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2008-08-20 01:24 by 陳梓瀚(vczh)
很好,已經(jīng)快接近我那個(gè)了……

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2008-08-24 16:06 by dell
每個(gè)整潔的接口后面,都有一個(gè)齷齪的實(shí)現(xiàn)。真是深刻。

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2008-12-22 01:45 by null
to cexer

你都是怎么看源代碼的 我也下了個(gè)超小型的GUI庫(kù) 不知道從哪看起

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2009-10-12 00:56 by XML
請(qǐng)教一下,你的MemberHandler 是怎么定義的?是如何讓onXXEvent接收任意類的成員函數(shù)的?

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2009-11-16 00:57 by 暗涌
消息處理函數(shù)有點(diǎn)像C#中的EventHandler,總是把消息的發(fā)送者傳給處理函數(shù)。把發(fā)送者類型放到模板參數(shù)里是個(gè)不錯(cuò)的辦法,有點(diǎn)像Singleton的模板。。。

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2009-11-17 17:13 by cexer
@null
讀書千遍其義自現(xiàn)啊,最主要是悶著看代碼。
從示例代碼,最高層開始往底層追溯

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2009-11-17 17:13 by cexer
@XML
那個(gè)代碼找不到了,不過(guò)實(shí)現(xiàn)還記得,以后會(huì)寫一下實(shí)現(xiàn)。

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2009-11-17 17:14 by cexer
@暗涌
嗯呵呵

# re: 拋棄了上一個(gè) GUI 消息機(jī)制,重寫了一個(gè)更靈活高效的  回復(fù)  更多評(píng)論   

2010-02-22 21:01 by jom
能寫自己的GUI框架,不錯(cuò)啊,呵呵。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国内精品久久久久久久影视麻豆| 国产精品自在在线| 亚洲精品四区| 亚洲国产成人精品女人久久久| 久久九九久久九九| 亚洲激情成人网| 亚洲美女精品一区| 国产精品视频观看| 久久中文欧美| 欧美成人亚洲成人日韩成人| 中文在线一区| 性色一区二区三区| 91久久精品国产91久久| 日韩视频在线一区二区| 国产一区视频网站| 亚洲国产小视频| 国产精品午夜国产小视频| 久久综合网络一区二区| 欧美电影在线观看完整版| 亚洲欧美一区二区激情| 久久中文久久字幕| 亚洲免费视频观看| 久久精品综合网| 亚洲欧美色婷婷| 免费欧美日韩国产三级电影| 亚洲欧美日韩综合| 玖玖视频精品| 性欧美大战久久久久久久久| 欧美一区二区三区在线看| 亚洲人永久免费| 欧美一区二区三区精品| 一区二区电影免费观看| 欧美一区二区三区视频免费播放| 亚洲麻豆一区| 久久久久久亚洲精品中文字幕| 正在播放亚洲一区| 久久伊人免费视频| 久久精品国产第一区二区三区| 欧美精品色综合| 欧美大色视频| 黑人操亚洲美女惩罚| 一区二区高清视频| 亚洲欧洲日韩综合二区| 久久久精品日韩欧美| 欧美一区二区黄色| 欧美日韩中文精品| 亚洲精品一区二区三区蜜桃久| 狠狠色综合一区二区| 亚洲一区二区视频在线| 一区二区三区久久| 欧美国产1区2区| 亚洲国产日本| 亚洲精品国产系列| 欧美不卡高清| 欧美国产日韩一区二区| 精品999在线观看| 久久国产一区二区三区| 欧美一区二粉嫩精品国产一线天| 欧美日本一区二区视频在线观看| 欧美不卡高清| 狠狠干狠狠久久| 久久精品夜色噜噜亚洲a∨| 午夜日韩av| 国产精品卡一卡二| 夜夜嗨av一区二区三区四区| 亚洲美女免费视频| 欧美日韩123| 99精品视频免费| 亚洲主播在线观看| 国产精品久久久久久影视 | 亚洲激情视频在线| 理论片一区二区在线| 免费观看30秒视频久久| 亚洲国产99| 欧美激情视频网站| 99re热这里只有精品视频| 亚洲视频一起| 国产农村妇女精品| 久久久久国产精品一区| 欧美粗暴jizz性欧美20| 亚洲毛片播放| 欧美激情亚洲激情| 制服丝袜激情欧洲亚洲| 久久国产精品99久久久久久老狼| 国产一区美女| 欧美激情亚洲视频| 亚洲国产精品一区二区第一页| 免费亚洲电影在线| 亚洲网站视频福利| 久久综合国产精品| 一本色道久久综合亚洲精品按摩 | 欧美一级免费视频| 另类图片国产| 亚洲在线中文字幕| 亚洲国产精品第一区二区三区| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 亚洲精品在线电影| 国产精品久久久久一区二区三区| 欧美亚洲午夜视频在线观看| 亚洲成色www8888| 亚洲欧美在线aaa| 亚洲二区在线| 国产精品亚洲综合一区在线观看| 久久亚洲国产成人| 亚洲午夜视频在线| 亚洲国产精品黑人久久久| 亚洲欧美一区二区在线观看| 亚洲啪啪91| 国产一区二区三区视频在线观看| 欧美精品一区二区在线观看| 久久精品一区二区国产| 亚洲网址在线| 亚洲日本在线观看| 美女图片一区二区| 久久国产精品久久精品国产| 日韩亚洲欧美在线观看| 亚洲成色www8888| 国产亚洲激情视频在线| 欧美日韩三级| 欧美激情一区二区在线| 性做久久久久久免费观看欧美| 亚洲激情一区| 亚洲国产cao| 欧美福利一区| 麻豆av一区二区三区| 欧美在线视频导航| 亚洲免费视频成人| 中文精品视频| 一本久久青青| 亚洲精品在线看| 亚洲日本成人| 亚洲国产日韩在线一区模特| 亚洲成人原创| 91久久在线播放| 亚洲精品女av网站| 亚洲精品一区二区三区樱花| 亚洲国产导航| 最新日韩av| 亚洲人成网站在线播| 亚洲精品久久久久久下一站| 亚洲精品你懂的| 一本色道久久综合亚洲精品不卡| 亚洲最新在线视频| 一本色道久久99精品综合| 一本大道久久a久久精二百| 日韩午夜在线播放| 在线综合亚洲| 亚洲一区精品视频| 午夜亚洲影视| 麻豆久久精品| 亚洲破处大片| 一区二区三区精品视频| 亚洲无线视频| 欧美在线视频播放| 久久久久久久成人| 欧美激情亚洲综合一区| 欧美日韩一区在线播放| 国产精品色婷婷| 国产一区二区在线观看免费播放| 狠狠入ady亚洲精品| 亚洲高清网站| 中文精品视频| 久久在线播放| 91久久精品日日躁夜夜躁欧美 | 亚洲免费视频在线观看| 久久国内精品视频| 亚洲国产高清高潮精品美女| 亚洲人成亚洲人成在线观看| 亚洲综合色在线| 欧美激情aⅴ一区二区三区| 欧美日韩dvd在线观看| 欧美午夜电影在线| 黑人中文字幕一区二区三区| 亚洲人屁股眼子交8| 亚洲欧美视频一区二区三区| 久久亚洲色图| 亚洲精选视频在线| 欧美一区二区日韩一区二区| 模特精品在线| 国产精品稀缺呦系列在线| 亚洲高清资源| 久久av红桃一区二区小说| 欧美成人精品三级在线观看| 一本色道久久综合亚洲精品不卡| 欧美在线网址| 欧美日韩亚洲高清一区二区| 狠狠色狠狠色综合| 亚洲午夜国产成人av电影男同| 久久九九热re6这里有精品| 亚洲精品一区二区三区四区高清| 欧美一区二区在线| 欧美午夜电影在线| 最新69国产成人精品视频免费| 欧美在线二区| 宅男噜噜噜66国产日韩在线观看| 久久人人爽人人爽| 国产一区二区三区四区在线观看| 夜夜嗨一区二区| 欧美电影电视剧在线观看| 欧美在线一区二区三区|