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

WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd)

轉(zhuǎn)載必須注明原文轉(zhuǎn)自C++博客(cppblog),作者畢達(dá)哥拉斯半圓,謝謝合作。

上一篇序言得到了很多高人的幫助鼓勵(lì)和意見(jiàn),并且給出了一些框架做參考,我這幾天拼命消化這些信息,比較了一些架構(gòu),最終決定以完整的應(yīng)用框架為主,并不先開(kāi)發(fā)完整的控件庫(kù),可以先采用Windows自帶的控件,或者DX控件,@vczh 的Gac控件也是可以用的嘛,@fzy 提出了快速的迭代開(kāi)發(fā)方法,對(duì)我是非常好的建議,但是個(gè)人水平問(wèn)題速度很可能快不起來(lái)。^_^

Any Way, 千里之行始于足下,就從最簡(jiǎn)單的窗口應(yīng)用開(kāi)始,請(qǐng)各位朋友繼續(xù)批評(píng)指正以及各種吐槽~,哈哈。

Windows是以消息循環(huán)為主體,面向過(guò)程的軟件結(jié)構(gòu),這是匯編、C語(yǔ)言對(duì)OS開(kāi)發(fā)的必然結(jié)果,所以開(kāi)發(fā)框架的第一步就構(gòu)建面向?qū)ο蟮捏w系結(jié)構(gòu),其核心使用了CBThook,下面逐步闡述。

先回顧一個(gè)典型的Windows App是這樣的:
 1 int APIENTRY _tWinMain(HINSTANCE hInstance,
 2                      HINSTANCE hPrevInstance,
 3                      LPTSTR    lpCmdLine,
 4                      int       nCmdShow)
 5 {
 6     UNREFERENCED_PARAMETER(hPrevInstance);
 7     UNREFERENCED_PARAMETER(lpCmdLine);
 8 
 9     MSG msg;
10     HACCEL hAccelTable;
11 
12     // 初始化全局字符串
13     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
14     LoadString(hInstance, IDC_TESTWIN32, szWindowClass, MAX_LOADSTRING);
15     //注冊(cè)窗口
16     MyRegisterClass(hInstance, szWindowClass, WndProc);
17 
18     // 執(zhí)行應(yīng)用程序初始化:
19     if (!InitInstance (hInstance, nCmdShow))
20     {
21         return FALSE;
22     }
23 
24     while (GetMessage(&msg, NULL, 00))
25     {
26         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
27         {
28             TranslateMessage(&msg);
29             DispatchMessage(&msg);
30         }
31     }
32 
33     return (int) msg.wParam;
34 }
35

然后是很熟悉的WndProc
 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 2 {
 3     int wmId, wmEvent;
 4     PAINTSTRUCT ps;
 5     HDC hdc;
 6     switch (message)
 7     {
 8     case WM_PAINT:
 9         break;
10 
11     //message
12     //message
13     //message
14 
15     case WM_COMMAND:
16         break;
17     case WM_CREATE:
18         return 0;
19     case WM_DESTROY:
20         PostQuitMessage(0);
21         break;
22     default:
23         return DefWindowProc(hWnd, message, wParam, lParam);
24     }
25     return 0;
26 }
27 
上面的MyRegisterClass調(diào)用WinApi RegisterClassEx 注冊(cè)窗口,InitInstance調(diào)用CreateWindow創(chuàng)建窗口,而while循環(huán)做消息處理,直到應(yīng)用退出。

作為WarmGUI的第一個(gè)類CWindow,應(yīng)該像MFC::CWnd那樣中封裝RegisterClass和CreateWindow,這應(yīng)該是很平凡的事情,照做就可以了,麻煩在于對(duì)WndProc封裝時(shí),WndProc必須是一個(gè)全局的函數(shù),只能作為CWindow的靜態(tài)函數(shù),而static修飾的函數(shù)是沒(méi)有this指針的,因此在消息循環(huán)中,我們只能得到HWND句柄,卻不知道這個(gè)句柄是哪一個(gè)CWindow的實(shí)例。

MFC解決的辦法是使用CBT鉤子,HCBT_CREATEWND類型的CBT鉤子可以在窗口創(chuàng)建時(shí)指定回調(diào)函數(shù),在這個(gè)回調(diào)函數(shù)中,將HWND和CWnd做一個(gè)映射,CWnd::Attach函數(shù)完成這個(gè)功能,這樣WndProc就可以用FromHandlePermanent函數(shù)從hwnd找到CWnd實(shí)例,然后可以在消息處理中調(diào)用CWnd::On-Message()什么的了。

WARMGUI::CWindow將采用CBT的方法,下面是山寨過(guò)程,應(yīng)該有更好的實(shí)現(xiàn)方法,請(qǐng)各位大佬多指教 ^_^
首先類CWindowManager繼承std::map,定義一個(gè)HWND-CWindow map,
 1 //the CWindowManager is a map of HWND-CWindow
 2 class CWindow;
 3 //define the HWND-CWindow map
 4 typedef map <HWND, CWindow*> CWindowMap;
 5 typedef pair<HWND, CWindow*> WindowPair;
 6 typedef map <HWND, CWindow*>::iterator WndIterator;
 7 typedef pair<WndIterator, bool> IterBool;
 8 
 9 class CWindowManager : private CWindowMap
10 {
11 private:
12     CWindowManager(void);
13     ~CWindowManager(void);
14 public:
15     bool Add(CWindow* pwnd);  //add a window to map
16     bool Remove(HWND hwnd);     //remove a window by hwnd
17     void Clear();               //remove all items
18     CMyWindow* Find(HWND hwnd); //find the window by hwnd
19 
20 public:
21     //get CWindowManager instance as singleton pattern
22     static CWindowManager * GetInstance();
23 };
24 
其中的代碼是很平凡的,調(diào)用std::map的函數(shù)而已,不做舉例了。
用一個(gè)全局變量
1 CWindow* gpInitWnd;
記住當(dāng)前正在創(chuàng)建的CWindow*,并用互斥鎖保證不會(huì)對(duì)其發(fā)生讀寫(xiě)沖突。事實(shí)上只要保證當(dāng)前線程內(nèi)不發(fā)生讀寫(xiě)沖突就可以了,因?yàn)镃BT是以線程為單位創(chuàng)建的,不過(guò)第一個(gè)版本的CWindow暫時(shí)不考慮,以后再說(shuō)。
這是CBT-hook代碼:
 1 static HHOOK ghook = 0;
 2 
 3 //Create a WH_CBT Hook
 4 static bool HookCrate()
 5 {
 6    HANDLE hThread = GetCurrentThread();
 7    DWORD dwThreadId = GetThreadId(hThread);
 8    if (hThread) {
 9         ghook = SetWindowsHookEx(
10             WH_CBT,
11             MyCBTProc,    //set the CBT proc
12             0,
13             dwThreadId);
14         if (!ghook)
15             return false;
16    }
17 
18    return (0);
19 }
20 
21 //Destroy WH_CBT Hook
22 static void HookDestroy()
23 {
24    if (ghook) {
25         UnhookWindowsHookEx(ghook);
26         ghook = 0;
27    }
28 }
29 
他的回調(diào)函數(shù)如下:
 1 static LRESULT CALLBACK MyCBTProc(int nCode, WPARAM wParam, LPARAM lParam)
 2 {
 3     if (nCode == HCBT_CREATEWND) {
 4         //GetInitPwnd() return gpInitWnd, the window is creating
 5         CWindow * pwnd = GetInitPwnd();
 6         if (pwnd) {
 7             HWND hwnd = pwnd->GetSafeHwnd();//return pwnd->_hwnd
 8             if (!hwnd) {
 9                 //first time call this proc, the CWindow have no HWND yet,
10                 //Attach() will attach the wParam to pwnd, eg. pwnd->_hwnd = wParam
11                 pwnd->Attach((HWND)wParam);
12                 //call the PreCreateWindow before WM_CREATE
13                 if (!(pwnd->PreCreateWindow((LPCREATESTRUCT)lParam)))
14                     return (1);
15                 return (0);
16             } else {
17                 //second time call this proc, i donw know why for now.
18                 //but this is second chance to decide what is the style
19                 //of the window, or the window should will be created or not,
20                 //if you want create it, return 0, else return non-zero.
21                 return (0);
22             }
23         } else {
24             return (1);
25         }
26     } else
27         return CallNextHookEx(ghook, nCode, wParam, lParam);
28 }
29 
注釋中我解釋了每個(gè)步驟的含義,MyCBTProc返回0則窗口被創(chuàng)建,返回非零則窗口被銷毀。尤其要注意的是這個(gè)回調(diào)會(huì)被調(diào)用兩次,我還不知道為什么,暫時(shí)也沒(méi)時(shí)間搞了,請(qǐng)教一下高人指點(diǎn)。

CWindow的Create函數(shù)是這樣的:
 1 bool CWindow::Create(TCHAR *  szClassName,    //NULL for default class name
 2                             TCHAR * szWindowName,
 3                                        DWORD dwStyle,
 4                                              RECT& rect,
 5                             CWindow * pParentWnd,
 6                                       LPVOID lpParam)
 7 {
 8     if (!pParentWnd)
 9         return false;
10 
11     TCHAR * szcn = (szClassName) ? szClassName : _gszClassName;
12 
13     _hInst = pParentWnd->GetInstance();
14     if (!MyRegisterClass(_hInst, szcn)) {
15         DWORD dwErr = GetLastError();
16         if (dwErr != ERROR_CLASS_ALREADY_EXISTS) //0x00000582
17             return false;
18     }
19 
20     SetInitWnd(this);    //gpInitWnd = this
21     HookCrate();
22     
23     HWND hWnd = CreateWindow(szcn,
24                         szWindowName,
25                         dwStyle,
26                         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
27                         pParentWnd->GetSafeHwnd(),
28                         NULL,    //menu
29                         _hInst,
30                         lpParam);
31     HookDestroy();
32     UnsetInitWnd();    //gpInitWnd = 0;
33 
34     if (!hWnd)
35         return FALSE;
36 
37     _pParent = pParentWnd;
38 
39     ShowWindow(hWnd, SW_SHOW);
40     UpdateWindow(hWnd);
41 
42     return TRUE;
43 }
過(guò)程如下:首先注冊(cè)窗口類,然后設(shè)定gpInitWnd=自己,創(chuàng)建CBTHook,創(chuàng)建窗口,銷毀CBTHook,設(shè)定gpInitWnd=0,最后顯示窗口。

CWindow的WndProc如下:
 1 LRESULT CALLBACK CWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 2 {
 3     //FromHandlePermanent get CWindow* from CWindowManager(a HWND-CWindow* map)
 4     //it call CWindowManager::Find(HWND hwnd) function and return CWindow*
 5     //it is MFC::CWnd Function
 6     CWindow * pwnd = FromHandlePermanent(hWnd);
 7     if (!pwnd) return FirstDefaultWndProc(hWnd, message, wParam, lParam);
 8 
 9     //Message Message and Message
10     LRESULT r = 0;
11     switch (message)
12     {
13         case WM_CREATE                      :
14             r = pwnd->OnCreate((LPCREATESTRUCT)lParam);
15             if (r)
16                 return (r);
17             break;
18         case WM_DESTROY                     :
19             pwnd->OnDestroy();
20             return (0);
21         case WM_PAINT:
22             pwnd->WindowPaint();
23             return (0);
24         case WM_SIZE                        :
25             pwnd->OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam));
26             return (0);
27         case WM_DISPLAYCHANGE               :
28             pwnd->WindowPaint();
29             return (0);
30         //message
31         //message
32         //and message
33         default:
34             return DefWindowProc(hWnd, message, wParam, lParam);
35     }
36     return DefWindowProc(hWnd, message, wParam, lParam);
37 }
現(xiàn)在可以對(duì)各種消息機(jī)制做一個(gè)比較好的封裝,比如對(duì)WM_PAINT調(diào)用WindowPaint函數(shù):
 1 void CWindow::WindowPaint()
 2 {
 3     PAINTSTRUCT ps;
 4     HDC hdc = BeginPaint(_hwnd, &ps);;
 5 
 6     OnPaint(hdc, &ps);
 7 
 8     EndPaint(_hwnd, &ps);
 9 }
在這個(gè)函數(shù)內(nèi)部實(shí)現(xiàn)BeginPaint和EndPaint對(duì),保證我們不會(huì)因?yàn)槊y而忘記這對(duì)冤家(常見(jiàn)錯(cuò)誤之一呀),CWindow和他的子類只要重寫(xiě)OnPaint就可以了。
現(xiàn)在可以把消息循環(huán)封裝進(jìn)來(lái)了:
 1 void CWindow::RunMessageLoop(HACCEL hAccelTable)
 2 {
 3     MSG msg;
 4 
 5     while (GetMessage(&msg, NULL, 00))
 6     {
 7         if (hAccelTable) {
 8             if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
 9             {
10                 TranslateMessage(&msg);
11                 DispatchMessage(&msg);
12             }
13         } else {
14             TranslateMessage(&msg);
15             DispatchMessage(&msg);
16         }
17     }
18 }

差不多已經(jīng)做完了,我們看看CWindow的聲明:
 1 #define msgfun virtual
 2 namespace WARMGUI {
 3     class WARMGUI_API CWindow
 4     {
 5     public:
 6         CWindow(void);
 7         virtual ~CWindow(void);
 8 
 9         HWND GetSafeHwnd();
10         HINSTANCE GetInstance();
11 
12         void Attach(HWND hwnd);
13         void Dettach();
14         virtual BOOL InitInstance(  HINSTANCE hInstance,
15                                     HINSTANCE hPrevInstance,
16                                     LPTSTR lpCmdLine,
17                                     int nCmdShow,
18                                     TCHAR * szClassName,
19                                     LPTSTR szTitle);
20 
21         virtual void  RunMessageLoop(HACCEL hAccelTable);
22         virtual BOOL PreCreateWindow(LPCREATESTRUCT cs);
23 
24         bool Create(TCHAR *  szClassName,
25                     TCHAR * szWindowName,
26                            DWORD dwStyle,
27                               RECT& rect,
28                     CWindow * pParentWnd,
29                       LPVOID lpParam = 0);
30 
32         void WindowPaint();
33 
34     protected:
35         HWND      _hwnd;
36         HINSTANCE _hInst;
37         CWindow * _pParent;
38 
39     protected:
40         ///OnCreate must return 0 to continue the creation of the CWnd object. If the application returns –1, the window will be destroyed. 
41         msgfun int  OnCreate                    (LPCREATESTRUCT cs);
42         msgfun void OnDestroy                   ();
43         msgfun void OnSize                      (UINT nType, int cx, int cy);
44         //bla bla bla hao duo message
45         //bla bla and bla hai you hao duo message
46 
47     protected:
48         static CWindow * FromHandlePermanent(HWND hWnd);
49         static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
50 
51     private:
52         virtual ATOM MyRegisterClass(HINSTANCE hInstance, TCHAR * szClassName);
53     };
54 }
現(xiàn)在可以從CWindow繼承,并重載他的各種消息函數(shù),并在WinMain中調(diào)用,一個(gè)最簡(jiǎn)單的應(yīng)用框架已經(jīng)有了,顯然,他必須是Hello, World:
 1 using namespace WARMGUI;
 2 
 3 class CMyWindow : public CWindow {
 4 public:
 5     CMyWindow();
 6     ~CMyWindow();
 7     
 8     msgfun void OnPaint(LPPAINTSTRUCE ps);x
 9 };
10 
11 void CMyWindow::OnPaint(HDC hdc, LPPAINTSTRUCT /*ps*/)
12 {
13     HBRUSH brush = CreateSolidBrush(RGB(00255));
14     
15     TCHAR hello[] = L"Hello, World!";
16     RECT rect;
17     rect.left = 100, rect.top = 100, rect.right = 200, rect.bottom = 200;
18     COLORREF oldBkg = SetBkColor(hdc, RGB(2552550));
19     COLORREF oldClr = SetTextColor(hdc, RGB(00255));
20     DrawText(hdc, hello, _tcslen(hello), &rect, DT_CENTER);
21     SetTextColor(hdc, oldClr);
22     SetBkColor(hdc, oldBkg);
23     DeleteObject(brush);
24 }
25 
26 int APIENTRY _tWinMain(HINSTANCE hInstance,
27                      HINSTANCE hPrevInstance,
28                      LPTSTR    lpCmdLine,
29                      int       nCmdShow)
30 {
31     CMyWindow mainwnd;
32 
33     if (mainwnd.InitInstance(hInstance, hPrevInstance, lpCmdLine, nCmdShow, szClassName, szTitle)) {
34         mainwnd.RunMessageLoop(0);
35     } else {
36         return (-1);
37     }
38 
39     return (0);
40 }
41 

posted on 2012-09-04 00:25 畢達(dá)哥拉斯半圓 閱讀(2131) 評(píng)論(14)  編輯 收藏 引用

評(píng)論

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 09:21 萬(wàn)連文

1.return路徑太多,不容易排錯(cuò)
2.CMyWindow* Find(HWND hwnd);我想是應(yīng)該加一個(gè)const
3.Add和Remove方法的參數(shù)不對(duì)稱,你確信是這樣子嗎?
4.CWindow * pwnd指針前后都有空格是排版導(dǎo)致的嗎?
5.WndIterator為何不用CWindowMap::iterator去定義,名字上有那么大差別,它們表達(dá)的含義真的不是一個(gè)事物嗎?
6.RECT rect = { 100, 100, 200, 200 };不好嗎?

因?yàn)槟阏f(shuō)了“代碼簡(jiǎn)潔漂亮”,吸引了我,結(jié)果有點(diǎn)失望。Any Way, 千里之行始于足下。  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 09:22 Richard Wei

對(duì)于如何關(guān)聯(lián)HWND和CWnd常用有3種方法:
(1)MFC的Map,就是博主上面用的
(2)把CWnd指針?lè)旁贑reateWindowEx的最后一個(gè)參數(shù)里,在回調(diào)WM_NCCREATE里從CREATESTRUCT里取出來(lái),再保存CWnd*到SetWindowLong(GWL_USERDATA)中,后面其他消息就直接取出CWnd*調(diào)用
(3)ATL的Thunk機(jī)制

第一種方法容易理解,但是低效
第二種方法把CreateParams和UserData用掉了,別人沒(méi)法再用了,通用性不是很好
第三種方法簡(jiǎn)單高效,但是會(huì)涉及到機(jī)器碼  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 09:34 溪流

class CWindowManager : private CWindowMap
對(duì)這個(gè)有異議,把CwindowMap作為CWindowManager的一個(gè)成員貌似也可以滿足需求?  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 09:35 畢達(dá)哥拉斯半圓

@萬(wàn)連文
多謝幫助啊多謝!按你說(shuō)的修改修改!  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 09:37 畢達(dá)哥拉斯半圓

@Richard Wei
多謝指教!第三個(gè)我還真不會(huì)呢,能甩個(gè)鏈接學(xué)習(xí)一下嗎?  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 09:41 畢達(dá)哥拉斯半圓

@溪流
當(dāng)然可以了,我考慮WindowManager這個(gè)類除了做map沒(méi)有其他任何工作,所以就用繼承了,如果他還有其他方面的工作,我就把map作為成員組合進(jìn)來(lái),不知道會(huì)不會(huì)更好?  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 10:09 Richard Wei

@畢達(dá)哥拉斯半圓
貌似上面的朋友 溪流 寫(xiě)過(guò),http://m.shnenglu.com/Streamlet/archive/2010/10/24/131064.aspx  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 10:13 Richard Wei

高級(jí)點(diǎn)的可以參考下這個(gè)http://m.shnenglu.com/cexer/archive/2008/08/06/58169.html  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 10:15 畢達(dá)哥拉斯半圓

@萬(wàn)連文
按您說(shuō)的改了改,發(fā)現(xiàn)一個(gè)問(wèn)題,
1. return路徑太多,不容易排錯(cuò)
這個(gè)是從MFC的習(xí)慣而來(lái)的,當(dāng)OnMESSAGE函數(shù)調(diào)用時(shí),如果返回非0值,就從消息循環(huán)中返回這個(gè)值,如果是0值,則有兩種情況,一種是直接返回,另一種是繼續(xù)執(zhí)行DefWndProc. 如果保持與MFC的習(xí)慣一致,不知道有沒(méi)有更好的辦法,請(qǐng)教一下。

我把宣傳中的簡(jiǎn)潔漂亮什么的去掉了,在高人眼中,我這還是太業(yè)余啦!哈哈  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 10:24 畢達(dá)哥拉斯半圓

@Richard Wei
@溪流
剛看到這個(gè),相見(jiàn)恨晚相見(jiàn)恨晚! 我向你們好好學(xué)習(xí)學(xué)習(xí).  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 10:50 溪流

@畢達(dá)哥拉斯半圓
感覺(jué)沒(méi)事不用繼承的好……如此,C++中的private繼承就想不到什么應(yīng)用場(chǎng)景了,困惑中……  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 10:50 溪流

@畢達(dá)哥拉斯半圓
互相學(xué)習(xí),不同的方案各有各的優(yōu)缺點(diǎn)唄~  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 11:42 畢達(dá)哥拉斯半圓

@溪流
額,也不是吧,畢竟WindowManager就是個(gè)map,或者改名叫CWndMap就理順了?  回復(fù)  更多評(píng)論   

# re: WarmGUI(1) 第一個(gè)類,用CBTHook構(gòu)建CWindow (山寨版MFC::Cwnd) 2012-09-04 11:50 溪流

@畢達(dá)哥拉斯半圓
也不順,我就是覺(jué)得private繼承一點(diǎn)也沒(méi)有存在的必要……感覺(jué)你的場(chǎng)景就是一個(gè)典型的組合場(chǎng)景……  回復(fù)  更多評(píng)論   


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


<2012年9月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

留言簿(3)

隨筆檔案

相冊(cè)

contact

搜索

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美刺激午夜性久久久久久久| 美女国产精品| 国产亚洲欧美日韩在线一区| 欧美视频在线观看 亚洲欧| 欧美大片一区二区三区| 欧美精品粉嫩高潮一区二区| 欧美日韩免费在线视频| 国产精品二区影院| 国产日韩欧美| 亚洲国产mv| 亚洲视频久久| 久久久综合网| 亚洲欧洲视频在线| 一区二区三区四区在线| 亚洲午夜激情| 卡一卡二国产精品| 欧美视频在线观看 亚洲欧| 国外成人性视频| 一本色道久久综合一区| 欧美专区在线| 亚洲精品视频在线观看免费| 香蕉久久夜色精品国产使用方法| 久久亚洲精品欧美| 国产精品普通话对白| 亚洲电影在线看| 亚洲在线电影| 欧美国产日韩一二三区| 亚洲专区国产精品| 欧美电影免费观看网站| 国产亚洲aⅴaaaaaa毛片| 日韩一级成人av| 久久久亚洲午夜电影| 夜夜夜精品看看| 国产精品久久久久aaaa| 久久久综合视频| 亚洲黄色尤物视频| 亚洲欧美激情诱惑| 欧美高清视频在线 | 国产精品h在线观看| 国产午夜精品美女毛片视频| 99视频有精品| 欧美二区视频| 久久精品夜色噜噜亚洲a∨| 国产精品亚洲片夜色在线| 亚洲视频在线视频| 亚洲国产一区二区三区高清| 欧美专区18| 国产欧美日韩一区二区三区在线| 中日韩男男gay无套| 亚洲激情视频在线观看| 欧美~级网站不卡| 亚洲国产日韩在线一区模特| 久久精品免费播放| 午夜精品婷婷| 国产精品永久免费在线| 亚洲欧美日韩国产综合在线| 亚洲精品免费在线观看| 欧美国产日韩一区二区在线观看| 在线观看91精品国产入口| 久久久www成人免费精品| 亚洲欧美视频在线| 国产欧美一区二区三区久久人妖| 欧美一级欧美一级在线播放| 亚洲视频国产视频| 国产麻豆视频精品| 久久亚洲综合色一区二区三区| 性久久久久久久久久久久| 国产欧美精品一区| 久久久久久久久久看片| 久久久久国色av免费观看性色| 韩国精品主播一区二区在线观看| 久久久久青草大香线综合精品| 欧美专区一区二区三区| 在线看一区二区| 亚洲精品国精品久久99热一| 欧美色道久久88综合亚洲精品| 亚洲综合日本| 久久99伊人| 亚洲免费av电影| 亚洲无吗在线| 激情欧美一区| 亚洲裸体视频| 国产亚洲欧美日韩精品| 欧美国产在线视频| 国产精品初高中精品久久| 久久精品在线播放| 欧美国产一区二区在线观看| 亚洲中字黄色| 久久天天躁夜夜躁狠狠躁2022| 亚洲欧美日韩一区二区在线| 中文国产亚洲喷潮| 国外成人免费视频| 亚洲国产精品www| 国产精品久久久久久久久久ktv| 久久久久欧美| 欧美视频日韩| 麻豆久久久9性大片| 欧美激情在线有限公司| 欧美在线免费一级片| 欧美成人精品福利| 午夜一级在线看亚洲| 免费日韩成人| 久久精品中文| 欧美视频一区二区三区在线观看 | 欧美高清视频在线播放| 香蕉久久夜色精品国产| 欧美—级高清免费播放| 久久久www| 国产精品久久久久久模特| 亚洲成人自拍视频| 国产亚洲免费的视频看| 一本大道久久a久久精二百| 亚洲国产精品久久人人爱蜜臀 | 午夜精品理论片| 一本在线高清不卡dvd| 久久久综合视频| 欧美一区二区三区播放老司机| 欧美国产免费| 欧美国产日韩一区二区三区| 国产综合色产| 性久久久久久久久| 欧美在线综合| 国产欧美日韩视频| 亚洲主播在线播放| 午夜激情综合网| 欧美日韩国产综合视频在线| 亚洲高清久久| 影音先锋欧美精品| 久久精品中文字幕一区二区三区| 亚洲自拍偷拍一区| 欧美日韩一级大片网址| 日韩天堂av| 亚洲视频一区二区| 欧美日韩一区二区三区免费看| 亚洲经典自拍| 夜夜嗨av一区二区三区四季av | 亚洲精品国产精品久久清纯直播| 在线观看福利一区| 麻豆91精品| 亚洲国产精品黑人久久久 | 久久精品国产96久久久香蕉| 国产精品女主播一区二区三区| avtt综合网| 欧美一二三视频| 国产一区清纯| 久久久久久久成人| 亚洲福利视频网站| 日韩午夜在线观看视频| 亚洲一区二区在线看| 久久精品三级| 久久精品99国产精品| 一区二区三区视频在线| 亚洲视频一区二区| 亚洲中字黄色| 久久亚洲国产精品日日av夜夜| 欧美成人午夜激情| 国产久一道中文一区| 欧美制服丝袜第一页| 国产美女诱惑一区二区| 亚洲欧美综合国产精品一区| 久久黄色级2电影| 在线观看福利一区| 欧美国产一区在线| 日韩视频免费| 久久久久**毛片大全| 亚洲国产精品精华液2区45| 日韩亚洲欧美在线观看| 国产精品免费视频xxxx| 久久xxxx精品视频| 亚洲国产高清自拍| 亚洲制服少妇| 一区二区三区在线免费播放| 欧美激情综合色综合啪啪| 国产精品99久久不卡二区 | 黑人巨大精品欧美黑白配亚洲| 另类欧美日韩国产在线| 日韩一二三区视频| 久久这里只有| 亚洲一区中文| 亚洲精品国产系列| 国产日韩精品一区二区三区| 久久视频这里只有精品| 亚洲午夜精品一区二区| 亚洲国产精品电影| 美乳少妇欧美精品| 久久精品72免费观看| 亚洲视频精品在线| 亚洲精品在线电影| 在线免费精品视频| 国产美女精品人人做人人爽| 欧美啪啪成人vr| 麻豆精品一区二区综合av| 亚洲欧美中文另类| 一本到12不卡视频在线dvd| 欧美成人视屏| 老鸭窝毛片一区二区三区| 欧美一区二区三区另类 | 国产精品国产三级国产专播品爱网 | 欧美二区视频| 免费观看久久久4p|