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

積木

No sub title

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  140 Posts :: 1 Stories :: 11 Comments :: 0 Trackbacks

常用鏈接

留言簿(1)

我參與的團隊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

#

CCSprite的動作總結

1) CCAction如果是用具體類的actionWithFile(.....)或類似這樣的接口的,則系統默認都是有自動維護引用計數的。即:這類對象創建出來后我們不需要釋放。
2) CCSprite::runAction()接口請一定要與CCSprite::stopAction()或CCSprite::stopAllActions()配合使用。
3) CCSprite在執行CCMoveTo動作時,此時如果再對其設置幀動畫動作,則這兩個動作將是會共存執行的。
------
以上3點很重要。
posted @ 2011-12-30 18:23 Jacc.Kim 閱讀(819) | 評論 (0)編輯 收藏

在介紹前,先介紹說幾點:
像opengl、directx是沒有自帶界面的,不過cocos可以為我們創建一個主界面,以用于顯示游戲場景等。該主界面由CCDirector類實例實現。
cocos2d中所有需要用到的類,基本上都繼承自CCObject類。它維護一個引用計數。所有從CCObject出來的類,都可以添加到自動釋放池中進行自動維護。(與objective-c中的對象有點類似)
多數情況下,我們使用的對象,還是從CCNode出來的。CCNode是繼承自CCObject的一個類。

下面簡要介紹下各個主要類的功能
1) CCDirector
主要功能一:負責生成一個游戲主界面及游戲的初始化并。并在該界面上,渲染游戲場景。
主要功能二:負責控制各游戲場景間的相互切換。
主要功能三:負責初始化設置游戲的一些重要屬性。如:游戲渲染的幀率。游戲視窗的尺寸(即:960 X 640 還是 480 X 320等)
主要功能四:負責清空游戲中的緩存數據(個人認為這個還是很重要的。因為到了手機上的游戲,硬內存不多,及時清除是很有必要的)
注意:該對象是單實例的,不需要用戶維護。

2) CCScene
游戲中的場景類。當程序啟動后,必須要為其設置一個場景,然后所有的對象在場景中場景。
主要功能:負責接收游戲中的任何對象。并將它們展現出來(如果可以展現的話,如:CCSprite等)
習慣上,用其維護多個的CCLayer

3) CCLayer
游戲中的層。習慣上,用其對資源展現進行布局管理。

4) CCSprite
游戲中的精靈對象。游戲中,必不可少的。會用到許多的可視對象。這些,多數都是精靈對象。

5) CCTargetedTouchDelegate
觸摸響應類。提供響應觸摸響應開始結束、觸摸移動以及取消觸摸幾個接口。多是需要在其派生類中進行具體實現。如:一個精靈,
可支持觸摸功能,則它需要自行實現這些接口。

以上只是簡單介紹cocos2d中的幾個較為主要及常用的類。初學,如有介紹不對的,請大家不吝指點。共同學習,共同進步。
posted @ 2011-12-26 21:53 Jacc.Kim 閱讀(667) | 評論 (0)編輯 收藏

原文轉載自:http://blog.sina.com.cn/s/blog_6028e2630100wn0h.html

 

C函數Strtok詳解

編程時在C中需要用的類似Java的Split函數來解析一個長字符串,分割成子段使用,查函數庫發現有strtok可用,看了示例卻對它的用法有些疑惑為什么傳值是NULL,于是上網查資料,找到這篇包含strtok函數源碼的解釋,轉過來學習,仔細研讀收獲良多。

 

查函數庫看到的strtok的解釋和示例:

strtok
Syntax:
 #include <cstring> char *strtok( char *str1, const char *str2 ); 

 

The strtok() function returns a pointer to the next "token" in str1, where str2 contains the delimiters that determine the token. strtok() returns NULL if no token is found. In order to convert a string to tokens, the first call to strtok() should have str1 point to the string to be tokenized. All calls after this should have str1 be NULL.

For example:

  char str[] = "now # is the time for all # good men to come to the # aid of their country";
   
char delims[] = "#";
   
char *result = NULL;
   result
= strtok( str, delims );
   
while( result != NULL ) {
       printf
( "result is /"%s/"/n", result );
       result
= strtok( NULL, delims );
   
}            

The above code will display the following output:

  result is "now "
   result
is " is the time for all "
   result
is " good men to come to the "
   result
is " aid of their country"

下面是查到的網絡文章對源碼的解釋:

原型:char * strtok(char * s,const char * ct)

用途:在s中找出以ct中的字符為分隔的字符串,即是源串中除去了含有分隔串中的所有字符后余下的一段段的字符串,每調用一次找到一串,找不到則返回空串。第一次調用必須傳給它有效的字符串,第二次傳NULL就可以了,每次調用返回找到的子串的時候都會把源串中該子串的尾部字符(原來是搜索串中的某一字符)修改成'/0'字符返回值為每次調用得到的字串。

下面看一下它的使用

 char sbody[]= "Presetptz/r/nPreset1=hello/r/nPreset2=ttttt/r/nend/r/n";

///char *pbody= "Presetptz/r/nPreset1=hello/r/nPreset2=ttttt/r/nend/r/n";//errror
 char except[] = "12/r/n";
 char *ptoken = NULL;
 ptoken = strtok(sbody,except);
 while(NULL!=ptoken)
 {
  printf("%s/n",ptoken);
  ptoken = strtok(NULL,except);
 }

 輸出為:
  Presetptz
  Preset
  =hello
  Preset
  =ttttt
  end
下面我們看一下它的源碼:

char *___strtok;//關鍵這個全局指針變量

char * strtok(char * s,const char * ct)
{
 char *sbegin, *send;
 
 sbegin  = s ? s : ___strtok;//不等于NULL用原始字符串,否則用___strtok
 if (!sbegin) {
  return NULL;//結尾
 }
 sbegin += strspn(sbegin,ct);//
 if (*sbegin == '/0') {
  ___strtok = NULL;
  return( NULL );
 }
 send = strpbrk( sbegin, ct);
 if (send && *send != '/0')
  *send++ = '/0';
 ___strtok = send;
 return (sbegin);
}

其中:  ssize_t strspn(const char* s,char*accept)// 返回accept中任一字符在s中第一次出現的位置

char * strpbrk(const char * cs,const char * ct)//返回指向ct中任一字符在cs中第一次出現的位置

這個函數不難分析,___strtok指針指向除去第一個有效字串后面的位置,到這里我們應該清楚為什么第二次調用時只要傳NULL就可以了,當然這里也暴露了它的缺點,就是說不能有兩個線程同時使用strtok否則就會出現錯誤。還有就是我在使用這個函數時碰到的問題,如上面的代碼如果我把sbody換成 pbody,則編譯沒有問題,運行時就會出錯,為什么?還是自己的基本功不扎實,pbody在是個靜態字符串,說白了,它是在編譯時就已經賦值而且相當于是一個const常量,不能被修改,而strtok是需要修改字符串的,所以產生問題不足為奇。

posted @ 2011-12-17 16:09 Jacc.Kim 閱讀(388) | 評論 (0)編輯 收藏

原文出處:http://www.cnblogs.com/finallyliuyu/archive/2010/10/11/1848130.html

一、C++中不能使用random()函數

==================================================================================

本文由青松原創并依GPL-V2及其后續版本發放,轉載請注明出處且應包含本行聲明。

C++中常用rand()函數生成隨機數,但嚴格意義上來講生成的只是偽隨機數(pseudo-random integral number)。生成隨機數時需要我們指定一個種子,如果在程序內循環,那么下一次生成隨機數時調用上一次的結果作為種子。但如果分兩次執行程序,那么由于種子相同,生成的“隨機數”也是相同的。

在工程應用時,我們一般將系統當前時間(Unix時間)作為種子,這樣生成的隨機數更接近于實際意義上的隨機數。給一下例程如下:

#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

int main()
{
    double random(double,double);
    srand(unsigned(time(0)));
    for(int icnt = 0; icnt != 10; ++icnt)
        cout << "No." << icnt+1 << ": " << int(random(0,10))<< endl;
    return 0;
}

double random(double start, double end)
{
    return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
/* 運行結果
* No.1: 3
* No.2: 9
* No.3: 0
* No.4: 9
* No.5: 5
* No.6: 6
* No.7: 9
* No.8: 2
* No.9: 9
* No.10: 6
*/
利用這種方法能不能得到完全意義上的隨機數呢?似乎9有點多哦?卻沒有1,4,7?!我們來做一個概率實驗,生成1000萬個隨機數,看0-9這10個數出現的頻率是不是大致相同的。程序如下:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <iomanip>
using namespace std;

int main()
{
    double random(double,double);
    int a[10] = {0};
    const int Gen_max = 10000000;
    srand(unsigned(time(0)));
   
    for(int icnt = 0; icnt != Gen_max; ++icnt)
        switch(int(random(0,10)))
        {
        case 0: a[0]++; break;
        case 1: a[1]++; break;
        case 2: a[2]++; break;
        case 3: a[3]++; break;
        case 4: a[4]++; break;
        case 5: a[5]++; break;
        case 6: a[6]++; break;
        case 7: a[7]++; break;
        case 8: a[8]++; break;
        case 9: a[9]++; break;
        default: cerr << "Error!" << endl; exit(-1);
        }
   
    for(int icnt = 0; icnt != 10; ++icnt)
        cout << icnt << ": " << setw(6) << setiosflags(ios::fixed) << setprecision(2) << double(a[icnt])/Gen_max*100 << "%" << endl;
   
    return 0;
}

double random(double start, double end)
{
    return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
/* 運行結果
* 0: 10.01%
* 1:   9.99%
* 2:   9.99%
* 3:   9.99%
* 4:   9.98%
* 5: 10.01%
* 6: 10.02%
* 7: 10.01%
* 8: 10.01%
* 9:   9.99%
*/
可知用這種方法得到的隨機數是滿足統計規律的。

另:在Linux下利用GCC編譯程序,即使我執行了1000000次運算,是否將random函數定義了inline函數似乎對程序沒有任何影響,有理由相信,GCC已經為我們做了優化。但是冥冥之中我又記得要做inline優化得加O3才行...

不行,于是我們把循環次數改為10億次,用time命令查看執行時間:
chinsung@gentoo ~/workspace/test/Debug $ time ./test
0: 10.00%
1: 10.00%
2: 10.00%
3: 10.00%
4: 10.00%
5: 10.00%
6: 10.00%
7: 10.00%
8: 10.00%
9: 10.00%

real    2m7.768s
user    2m4.405s
sys     0m0.038s
chinsung@gentoo ~/workspace/test/Debug $ time ./test
0: 10.00%
1: 10.00%
2: 10.00%
3: 10.00%
4: 10.00%
5: 10.00%
6: 10.00%
7: 10.00%
8: 10.00%
9: 10.00%

real    2m7.269s
user    2m4.077s
sys     0m0.025s

前一次為進行inline優化的情形,后一次為沒有作inline優化的情形,兩次結果相差不大,甚至各項指標后者還要好一些,不知是何緣由...

=================================================================================


     random函數不是ANSI C標準,不能在gcc,vc等編譯器下編譯通過。 可改用C++下的rand函數來實現。     1、C++標準函數庫提供一隨機數生成器rand,返回0-RAND_MAX之間均勻分布的偽隨機整數。 RAND_MAX必須至少為32767。rand()函數不接受參數,默認以1為種子(即起始值)。 隨機數生成器總是以相同的種子開始,所以形成的偽隨機數列也相同,失去了隨機意義。(但這樣便于程序調試)
      2、C++中另一函數srand(),可以指定不同的數(無符號整數變元)為種子。但是如果種子相同,偽隨機數列也相同。一個辦法是讓用戶輸入種子,但是仍然不理想。
     3、 比較理想的是用變化的數,比如時間來作為隨機數生成器的種子。 time的值每時每刻都不同。所以種子不同,所以,產生的隨機數也不同。
// C++隨機函數(VC program)
#include <stdio.h>
#include <iostream>
#include <time.h>
using namespace std;
#define MAX 100
int main(int argc, char* argv[])
{        srand( (unsigned)time( NULL ) );//srand()函數產生一個以當前時間開始的隨機種子.應該放在for等循環語句前面 不然要很長時間等待
   for (int i=0;i<10;i++)
   cout<<rand()%MAX<<endl;//MAX為最大值,其隨機域為0~MAX-1
   return 0;
}
二、rand()的用法
     rand()不需要參數,它會返回一個從0到最大隨機數的任意整數,最大隨機數的大小通常是固定的一個大整數。 這樣,如果你要產生0~10的10個整數,可以表達為:
  int N = rand() % 11;
     這樣,N的值就是一個0~10的隨機數,如果要產生1~10,則是這樣:
  int N = 1 + rand() % 10;
  總結來說,可以表示為:
  a + rand() % n
     其中的a是起始值,n是整數的范圍。   a + rand() % (b-a+1) 就表示 a~b之間的一個隨機數若要0~1的小數,則可以先取得0~10的整數,然后均除以10即可得到隨機到十分位的10個隨機小數,若要得到隨機到百分位的隨機小數,則需要先得到0~100的10個整數,然后均除以100,其它情況依此類推。
     通常rand()產生的隨機數在每次運行的時候都是與上一次相同的,這是有意這樣設計的,是為了便于程序的調試。若要產生每次不同的隨機數,可以使用srand( seed )函數進行隨機化,隨著seed的不同,就能夠產生不同的隨機數。
     如大家所說,還可以包含time.h頭文件,然后使用srand(time(0))來使用當前時間使隨機數發生器隨機化,這樣就可以保證每兩次運行時可以得到不同的隨機數序列(只要兩次運行的間隔超過1秒)。

posted @ 2011-12-07 11:14 Jacc.Kim 閱讀(222) | 評論 (0)編輯 收藏

原諒轉載自:http://lukas06.blog.sohu.com/94010246.html

    C++編譯器在生成DLL時,會對導出函數進行名字改編,并且不同的編譯器使用的改編規則不一樣,因此改編的名字后的名字是不一樣的。因此,如果利用不同的分別生成DLL文件和訪問DLL文件的客戶端,那么后者在訪問該DLL文件的時候就會出現問題。例如:使用C++編寫了一個DLL,而使用C語言編寫的客戶端進行訪問就會出現問題。由于C++編譯器已經對該導出函數名字進行了改編,所以用C語言編寫的客戶端就找不到DLL的導出函數。這就是DLL導出函數的名字改編問題。

    如果希望動態鏈接庫文件在編譯時,導出函數的名稱不要發生改變,那么在定義導出函數時,需要加上限定符:extern "C"。注意:雙引號中的“C”一定要大寫。

例如:Dll1.h頭文件
#ifdef DLL1_API
#else
#define DLL1_API extern "C" _declspec(dllimport)
#endif

DLL1_API int add(int a,int b);
DLL1_API int subtract(int a,int b);

Dll1.cpp源文件
#define DLL1_API extern "C" _declspec(dllexport)
#include "Dll1.h"

int add(int a,int b)
{
    return a+b;
}
int subtract(int a,int b)
{
    return a-b;
}
這樣利用dumpbin工具可以查看Dll2.dll的導出函數,>dumpbin -exports Dll2.dll,可以發現名字沒有被改編。

利用限定符extern "C"可以解決C++和C語言之間相互調用時函數命名的問題。但是這種方法有一個缺陷:就是不能用于導出一個類的成員函數,而只能用于導出全局函數這種情況。

但是還有一個問題是,如果使用了標準調用約定,也就是pascal調用約定,WINAPI調用約定:_stdcall,此時即使使用了extern "C",仍然會出現導出函數名字被改編的問題。例如:使用C語言編寫一個DLL文件,而客戶端使用Delphi進行編寫,那么在編寫導出函數時,應該指定其使用標準的函數調用約定。此時,就會出現問題,即C語言編寫的DLL文件的導出函數發生了名字改編。在這種情況下,可以使用一個稱為模塊定義文件(DEF)的方式解決名字改編問題。
例如:Dll2.def
LIBRARY

EXPORTS
add
subtract
如果想使用與源文件中定義的不一樣的函數名,可以按照以下語法:entryname=internalname
其中,entryname是要導出的符號名,而internalname是DLL中將要導出的函數名。

示例:

LIBRARY "VerifyLocalResType"

EXPORTS

        VerifyDDSSize
        VerifyDDSType
        VerifyTGASize
        VerifyTGAType

 

posted @ 2011-11-26 16:03 Jacc.Kim 閱讀(2383) | 評論 (1)編輯 收藏

 

無意中看到的一篇,挺不錯的。呵呵。收藏下。
 
c++字符大小寫轉換

  原為某著名軟件公司試題,大意如下:請實現以下兩個函數:char toupper(char c); char tolower(char c); 分別用于將傳入的字母轉為大寫和小寫。兩個函數傳入的參數取值范圍都是[a-zA-Z],并且為ASCII編碼,實現時不用檢查參數合法性。兩個函數的實現不能使用任何形式的分支、跳轉等類型的語句或指令(特別說明:C/C++的條件操作符?:也是分支指令的一種形式,故而不能使用)。請盡可能多的寫出你知道的辦法。  

  分析解決:此題比較特別,限制嚴格,根據題目要求,排除if else、for、while、do while、switch case、?:外,能使用的語句就只有 =、+=、-=、&、|、^、++、--這些了,想要實現大小寫轉換,只能從這些語句中進行選擇思考,由于字符集為ASCII編碼,且范圍明確為[a-zA-Z],我們知道,a-z對應ASCII值為97-122,A-Z對應ASCII為65-90,觀察這些數字,可以發現97-122都大于96 ,65-90都大于64且小于96,進一步從二進制上考慮,則發現所有小寫字母對應的二進制形式為011XXXXX,大寫字母對應的二進制形式為010XXXXX,一到這里,哈哈,答案就出來了,通過位運算&和|就可實現了。代碼描述如下

 1char toupper(char c)
 2{
 3    return c & 0x5F;
 4}
 5
 6char tolower(char c)
 7{
 8    //c | 0x60也行,但不太好,因為0x60會改變結果的第7位值,根據題目意思,改變第6位值為1,而其它位保持不變就夠了。
 9    return c | 0x20;
10}
   至于其它方法,我就沒多想了,還希望各位大俠多多分享一下哈。

posted @ 2011-11-23 14:45 Jacc.Kim 閱讀(1002) | 評論 (0)編輯 收藏

#include <time.h>

//* 方法一
 time_t tt = time(NULL);//這句返回的只是一個時間cuo
 tm* t= localtime(&tt);
 printf("%d-%02d-%02d %02d:%02d:%02d\n",
  t->tm_year + 1900,
  t->tm_mon + 1,
  t->tm_mday,
  t->tm_hour,
  t->tm_min,
  t->tm_sec);

//* 方法二
 SYSTEMTIME st = {0};
 GetLocalTime(&st);
 printf("%d-%02d-%02d %02d:%02d:%02d\n",
  st.wYear,
  st.wMonth,
  st.wDay,
  st.wHour,
  st.wMinute,
  st.wSecond);

下面幾個,是網上找的:轉載地址:http://apps.hi.baidu.com/share/detail/17815869

 

個人覺得第二種還是比較實用的,而且也是最常用的~

不過當計算算法耗時的時候,不要忘記second,不能只要用Milliseconds來減,不然后出現負值,若是算法耗時太長就得用minutes啦。再不然,就hours……

//方案— 優點:僅使用C標準庫;缺點:只能精確到秒級
#include <time.h>
#include <stdio.h>
int main( void )
{
    time_t t = time(0);
    char tmp[64];
    strftime( tmp, sizeof(tmp), "%Y/%m/%d %X %A 本年第%j天 %z",localtime(&t) );
    puts( tmp );
    return 0;
}
size_t strftime(char *strDest, size_t maxsize, const char *format, const struct tm *timeptr);
根據格式字符串生成字符串。
struct tm *localtime(const time_t *timer);
取得當地時間,localtime獲取的結果由結構tm返回
返回的字符串可以依下列的格式而定:
%a 星期幾的縮寫。Eg:Tue
%A 星期幾的全名。 Eg: Tuesday
%b 月份名稱的縮寫。
%B 月份名稱的全名。
%c 本地端日期時間較佳表示字符串。
%d 用數字表示本月的第幾天 (范圍為 00 至 31)。日期
%H 用 24 小時制數字表示小時數 (范圍為 00 至 23)。
%I 用 12 小時制數字表示小時數 (范圍為 01 至 12)。
%j 以數字表示當年度的第幾天 (范圍為 001 至 366)。
%m 月份的數字 (范圍由 1 至 12)。
%M 分鐘。
%p 以 ''AM'' 或 ''PM'' 表示本地端時間。
%S 秒數。
%U 數字表示為本年度的第幾周,第一個星期由第一個周日開始。
%W 數字表示為本年度的第幾周,第一個星期由第一個周一開始。
%w 用數字表示本周的第幾天 ( 0 為周日)。
%x 不含時間的日期表示法。
%X 不含日期的時間表示法。 Eg: 15:26:30
%y 二位數字表示年份 (范圍由 00 至 99)。
%Y 完整的年份數字表示,即四位數。 Eg:2008
%Z(%z) 時區或名稱縮寫。Eg:中國標準時間
%% % 字符。

//方案二 優點:能精確到毫秒級;缺點:使用了windows API
#include <windows.h>
#include <stdio.h>
int main( void )
{
SYSTEMTIME sys;
GetLocalTime( &sys );
printf( "%4d/%02d/%02d %02d:%02d:%02d.%03d 星期%1d\n",sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute, sys.wSecond,sys.wMilliseconds,sys.wDayOfWeek);
return 0;
}
//方案三,優點:利用系統函數,還能修改系統時間
//此文件必須是c++文件
#include<stdlib.h>
#include<iostream>
using namespace std;
void main()
{
    system("time");
}
//方案四,將當前時間折算為秒級,再通過相應的時間換算即可
//此文件必須是c++文件
#include<iostream>
#include<ctime>
using namespace std;
int main()
{
time_t now_time;
now_time = time(NULL);
cout<<now_time;
return 0;
}




注意:GetLocalTime()與GetSystemTime()是有區別的
posted @ 2011-11-23 11:00 Jacc.Kim 閱讀(34387) | 評論 (1)編輯 收藏

http://www.4ucode.com/Study/Topic/1996448

VS2008中創建DLL工程

      文件->新建->項目->visual c++->win32->win32控制臺應用程序(win32項目也可以)

      填寫項目名稱MyDLL->確定->下一步->DLL(附加選項 對空項目打鉤)->完成。

      到這里DLL工程就創建完畢了,下面新建兩個文件testDLL.cpp和testDLL.h。



C++ .h 文件

#define DLL_EXPORT __declspec(dllexport) 
extern "C" DLL_EXPORT int MyMinus(int a,int b);



.cpp 文件
// testDLL.cpp : 定義 DLL 應用程序的導出函數。
//

#include "stdafx.h"


#include "testDLL.h"

int MyMinus(int a,int b)
{
 return (a-b);
}




delphi調用代碼
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    edt1: TEdit;
    edt2: TEdit;
    lbl1: TLabel;
    lbl2: TLabel;
    lbl3: TLabel;
    btn1: TButton;
    lbl4: TLabel;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
const
  TestDll = 'testDLL.dll';
function MyMinus(a:Integer;b:Integer):Integer;cdecl;external TestDll;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
begin
  lbl4.Caption := IntToStr(MyMinus(StrToInt(edt1.Text),StrToInt(edt2.Text)));
end;

end.
posted @ 2011-11-22 09:50 Jacc.Kim 閱讀(1720) | 評論 (0)編輯 收藏

原諒轉載自http://tech.ddvip.com/2008-11/122662837992492.html

Visual C++中提供的MFC類CtreeCtrl(樹型控件)用來顯示具有一定層次結構的數據項時方便、直觀,所以它已經被廣泛地應用在各種軟件中,如資源管理器中的磁盤目錄就用的是樹型控件,我們在編程中也會經常用到這個控件,但是這個控件也有缺陷,那就是它并不直接支持拖動節點等高級特性,這使得程序員在編程時使用它受到了很大限制,同時又給軟件用戶帶來了一些不便。為此,本實例通過從 CTreeCtrl 中派生了一個類 CXTreeCtrl ,實現樹型控件中節點的拖動。這個類具有如下的功能:⑴ 基本項目條拖動的實現;⑵ 處理項目條的無意拖動;⑶ 能處理項目條拖動過程中的滾動問題;⑷ 拖動過程中節點會智能展開。程序編譯運行后的效果如圖所示:

570)?'570px':'auto'; }" src="http://img.ddvip.com/2008_11_14/1226628379_ddvip_9835.png">

  圖一:樹型控件節點拖動示例

  一、實現方法

  我們針對上述自定義類的實現功能,介紹實現思路和方法。

  (1)基本項目條拖動的實現

  當我們要拖動樹型控件的一個項目條時,樹型控件會給它的父窗口發送一個TVN_BEGINDRAG通知消息,所以可以在此消息的響應函數中,調用 CTreeCtrl ::CreateDragImage ()函數創建表示當前項目條正處在拖動操作中的圖象,該函數創建的圖象由項目條的圖象和標簽文本組成。創建了拖動圖象后,調用CImageList::BeginDrag()函數指定拖動圖象的熱點位置,然后調用CImageList::DragEnter()函數顯示拖動圖象。接下來處理 WM_MOUSEMOVE 消息用于更新拖動圖象,我們想讓移動中的圖象經過某些項目時高亮度顯示,這可以調用 CTreeCtrl ::SelectDropTarget() 來實現。在調用 SelectDropTarget()函數之前,需要先調用CImageList::DragShowNolock ( false )函數來隱藏圖象列表,然后再調用CImageList::DragShowNolock ( true ) 函數來恢復圖象列表的顯示,這樣就不會在拖動過程中留下難看的軌跡。最后我們處理 WM_LBUTTONUP 消息用于完成拖動操作,在該消息響應函數中,我們需要完成結束拖動圖象的顯示、刪除拖動圖象、釋放鼠標、節點的拷貝/刪除等操作。在節點的拷貝/刪除操作中,如果是父節點拖到子節點上,我們可以先將父節點拷到根結點下的臨時節點中,再從臨時結點處拷到子節點,然后將根結點下的臨時節點刪除,這樣做的目的是防止產生異常。

  (2)處理項目條的無意拖動

  牐犎綣在鼠標按下時不小心移動了鼠標,這時系統就認為產生了一個移動操作,這就產生了誤操作。解決這個問題的方法是設置時間延遲,也就是說當用戶按下鼠標后必須在原位置停留一段時間,才能激活拖動操作。

  (3)處理拖動過程中的滾動問題

  當我們拖動樹型控件的項目條時,如果目的節點不可見,則需要拖動滾動條或收攏其它一些節點以使得目的節點顯示出來,無疑,這會給我們帶來很大的不便。為此就要給樹型控件添加自動滾動支持。首先設置一個定時器,在 WM_TIMER 消息中檢測鼠標的位置,如果靠近樹型控件的下邊緣,則使得控件向下滾動。靠近上邊緣則向上滾動。滾動速度根據鼠標的位置確定。

  (4)拖動過程中節點的智能展開

  為了實現在拖動過程中鼠標停留在某個節點上一段時間后,該節點會自動展開的功能。設置一個定時器,當鼠標在拖動過程中停止在某個節點上時,定時器被啟動,再設置一變量保存當前的鼠標位置。

  二、編程步驟

  1、 新建一對話框工程DragTree,編輯資源,在對話框中加入一樹型控件IDC_TREE ,屬性設置為:Has Buttons、Has Lines、Lines at root、Edit Labels、Border;

  2、 使用Class Wizard給該控件添加一個成員變量 m_wndTree ,在代碼部分將該控件的類型修改為CXTreeCtrl。

  3、 在對話框的OnInitDialog()函數中添加代碼,初始化樹型控件的項目條;

  4、 制作一個圖像資源(ID為IDB_TREEIMAGE),其中包含兩個小圖標,用來作為樹型控件項目條的顯示圖標;

  5、 添加代碼,編譯運行程序。

  三、程序代碼

// XTreeCtrl.h : header file 
#if !defined(AFX_XTREECTRL_H__3EF12526_EF66_4FD9_A572_59476441D79A__INCLUDED_) 
#define AFX_XTREECTRL_H__3EF12526_EF66_4FD9_A572_59476441D79A__INCLUDED_ 
#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 
class CXTreeCtrl : public CTreeCtrl 

 
// Construction 
 public
  CXTreeCtrl(); 
  
// Attributes 
 public
  
// Operations 
 public
  
// Overrides 
  
// ClassWizard generated virtual function overrides 
  
//{{AFX_VIRTUAL(CXTreeCtrl) 
  
//}}AFX_VIRTUAL 
  
// Implementation 
 public
  
virtual ~CXTreeCtrl(); 
  
// Generated message map functions 
 protected
  UINT m_TimerTicks; 
//處理滾動的定時器所經過的時間 
  UINT m_nScrollTimerID; //處理滾動的定時器 
  CPoint m_HoverPoint; //鼠標位置 
  UINT m_nHoverTimerID; //鼠標敏感定時器 
  DWORD m_dwDragStart; //按下鼠標左鍵那一刻的時間 
  BOOL m_bDragging; //標識是否正在拖動過程中 
  CImageList* m_pDragImage; //拖動時顯示的圖象列表 
  HTREEITEM m_hItemDragS; //被拖動的標簽 
  HTREEITEM m_hItemDragD; //接受拖動的標簽 
  
//{{AFX_MSG(CXTreeCtrl) 
   afx_msg void OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult); 
   afx_msg 
void OnMouseMove(UINT nFlags, CPoint point); 
   afx_msg 
void OnLButtonUp(UINT nFlags, CPoint point); 
   afx_msg 
void OnLButtonDown(UINT nFlags, CPoint point); 
   afx_msg 
void OnTimer(UINT nIDEvent); 
  
//}}AFX_MSG 
  DECLARE_MESSAGE_MAP() 
 
private
  HTREEITEM CopyBranch(HTREEITEM htiBranch,HTREEITEM htiNewParent,HTREEITEM htiAfter); 
  HTREEITEM CopyItem(HTREEITEM hItem,HTREEITEM htiNewParent,HTREEITEM htiAfter); 
}; 
#endif 
//////////////////////////////////////////////////////////// CXTreeCtrl 
#include "stdafx.h" 
#include 
"DragTree.h" 
#include 
"XTreeCtrl.h" 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
#define DRAG_DELAY 60 
CXTreeCtrl::CXTreeCtrl() 

 m_bDragging 
= false

CXTreeCtrl::
~CXTreeCtrl() 
{} 
BEGIN_MESSAGE_MAP(CXTreeCtrl, CTreeCtrl) 
//{{AFX_MSG_MAP(CXTreeCtrl) 
 ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag) 
 ON_WM_MOUSEMOVE() 
 ON_WM_LBUTTONUP() 
 ON_WM_LBUTTONDOWN() 
 ON_WM_TIMER() 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
void CXTreeCtrl::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 

 NM_TREEVIEW
* pNMTreeView = (NM_TREEVIEW*)pNMHDR; 
 
*pResult = 0
 
//如果是無意拖曳,則放棄操作 
 if( (GetTickCount() - m_dwDragStart) < DRAG_DELAY ) 
  
return
 m_hItemDragS 
= pNMTreeView->itemNew.hItem; 
 m_hItemDragD 
= NULL; 
 
//得到用于拖動時顯示的圖象列表 
 m_pDragImage = CreateDragImage( m_hItemDragS ); 
 
if!m_pDragImage ) 
  
return
 m_bDragging 
= true
 m_pDragImage
->BeginDrag ( 0,CPoint(8,8) ); 
 CPoint pt 
= pNMTreeView->ptDrag; 
 ClientToScreen( 
&pt ); 
 m_pDragImage
->DragEnter ( this,pt ); //"this"將拖曳動作限制在該窗口 
 SetCapture(); 
 m_nScrollTimerID 
= SetTimer( 2,40,NULL ); 

void CXTreeCtrl::OnMouseMove(UINT nFlags, CPoint point) 

 HTREEITEM hItem; 
 UINT flags; 
 
//檢測鼠標敏感定時器是否存在,如果存在則刪除,刪除后再定時 
 if( m_nHoverTimerID ) 
 { 
  KillTimer( m_nHoverTimerID ); 
  m_nHoverTimerID 
= 0
 } 
 m_nHoverTimerID 
= SetTimer( 1,800,NULL ); //定時為 0.8 秒則自動展開 
 m_HoverPoint = point; 
 
if( m_bDragging ) 
 { 
  CPoint pt 
= point; 
  CImageList::DragMove( pt ); 
  
//鼠標經過時高亮顯示 
  CImageList::DragShowNolock( false ); //避免鼠標經過時留下難看的痕跡 
  if( (hItem = HitTest(point,&flags)) != NULL ) 
  { 
   SelectDropTarget( hItem ); 
   m_hItemDragD 
= hItem; 
  } 
  CImageList::DragShowNolock( 
true ); 
  
//當條目被拖曳到左邊緣時,將條目放在根下 
  CRect rect; 
  GetClientRect( 
&rect ); 
  
if( point.x < rect.left + 20 ) 
   m_hItemDragD 
= NULL; 
 } 
 CTreeCtrl::OnMouseMove(nFlags, point); 

void CXTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point) 

 CTreeCtrl::OnLButtonUp(nFlags, point); 
 
if( m_bDragging ) 
 { 
  m_bDragging 
= FALSE; 
  CImageList::DragLeave( 
this ); 
  CImageList::EndDrag(); 
  ReleaseCapture(); 
  delete m_pDragImage; 
  SelectDropTarget( NULL ); 
  
if( m_hItemDragS == m_hItemDragD ) 
  { 
   KillTimer( m_nScrollTimerID ); 
   
return
  } 
  Expand( m_hItemDragD,TVE_EXPAND ); 
  HTREEITEM htiParent 
= m_hItemDragD; 
  
while( (htiParent = GetParentItem(htiParent)) != NULL ) 
  { 
   
if( htiParent == m_hItemDragS ) 
   { 
    HTREEITEM htiNewTemp 
= CopyBranch( m_hItemDragS,NULL,TVI_LAST ); 
    HTREEITEM htiNew 
= CopyBranch( htiNewTemp,m_hItemDragD,TVI_LAST ); 
    DeleteItem( htiNewTemp ); 
    SelectItem( htiNew ); 
    KillTimer( m_nScrollTimerID ); 
    
return
   } 
  } 
  HTREEITEM htiNew 
= CopyBranch( m_hItemDragS,m_hItemDragD,TVI_LAST ); 
  DeleteItem( m_hItemDragS ); 
  SelectItem( htiNew ); 
  KillTimer( m_nScrollTimerID ); 
 } 

HTREEITEM CXTreeCtrl::CopyItem(HTREEITEM hItem, HTREEITEM htiNewParent, HTREEITEM htiAfter) 
//拷貝條目 

 TV_INSERTSTRUCT tvstruct; 
 HTREEITEM hNewItem; 
 CString sText; 
 
//得到源條目的信息 
 tvstruct.item.hItem = hItem; 
 tvstruct.item.mask
=TVIF_CHILDREN|TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; 
 GetItem( 
&tvstruct.item ); 
 sText 
= GetItemText( hItem ); 
 tvstruct.item.cchTextMax 
= sText.GetLength (); 
 tvstruct.item.pszText 
= sText.LockBuffer (); 
 
//將條目插入到合適的位置 
 tvstruct.hParent = htiNewParent; 
 tvstruct.hInsertAfter 
= htiAfter; 
 tvstruct.item.mask 
= TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT; 
 hNewItem 
= InsertItem( &tvstruct ); 
 sText.ReleaseBuffer (); 
 
//限制拷貝條目數據和條目狀態 
 SetItemData( hNewItem,GetItemData(hItem) ); 
 SetItemState( hNewItem,GetItemState(hItem,TVIS_STATEIMAGEMASK),TVIS_STATEIMAGEMASK); 
 
return hNewItem; 

HTREEITEM CXTreeCtrl::CopyBranch(HTREEITEM htiBranch, HTREEITEM htiNewParent, HTREEITEM htiAfter) 
//拷貝分支 

 HTREEITEM hChild; 
 HTREEITEM hNewItem 
= CopyItem( htiBranch,htiNewParent,htiAfter ); 
 hChild 
= GetChildItem( htiBranch ); 
 
while( hChild != NULL ) 
 { 
  CopyBranch( hChild,hNewItem,htiAfter ); 
  hChild 
= GetNextSiblingItem( hChild ); 
 } 
 
return hNewItem; 

void CXTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point) //處理無意拖曳 

 m_dwDragStart 
= GetTickCount(); 
 CTreeCtrl::OnLButtonDown(nFlags, point); 

void CXTreeCtrl::OnTimer(UINT nIDEvent) 

 
//鼠標敏感節點 
 if( nIDEvent == m_nHoverTimerID ) 
 { 
  KillTimer( m_nHoverTimerID ); 
  m_nHoverTimerID 
= 0
  HTREEITEM trItem 
= 0
  UINT uFlag 
= 0
  trItem 
= HitTest( m_HoverPoint,&uFlag ); 
  
if( trItem && m_bDragging ) 
  { 
   SelectItem( trItem ); 
   Expand( trItem,TVE_EXPAND ); 
  } 
 } 
 
//處理拖曳過程中的滾動問題 
 else if( nIDEvent == m_nScrollTimerID ) 
 { 
  m_TimerTicks
++
  CPoint pt; 
  GetCursorPos( 
&pt ); 
  CRect rect; 
  GetClientRect( 
&rect ); 
  ClientToScreen( 
&rect ); 
  HTREEITEM hItem 
= GetFirstVisibleItem(); 
  
if( pt.y < rect.top +10 ) 
  { 
   
//向上滾動 
   int slowscroll = 6 - (rect.top + 10 - pt.y )/20
   
if0 == (m_TimerTicks % ((slowscroll > 0? slowscroll : 1)) ) 
   { 
    CImageList::DragShowNolock ( 
false ); 
    SendMessage( WM_VSCROLL,SB_LINEUP ); 
    SelectDropTarget( hItem ); 
    m_hItemDragD 
= hItem; 
    CImageList::DragShowNolock ( 
true ); 
   } 
  } 
  
else if( pt.y > rect.bottom - 10 ) 
  { 
   
//向下滾動 
   int slowscroll = 6 - (pt.y - rect.bottom + 10)/20
   
if0 == (m_TimerTicks % ((slowscroll > 0? slowscroll : 1)) ) 
   { 
    CImageList::DragShowNolock ( 
false ); 
    SendMessage( WM_VSCROLL,SB_LINEDOWN ); 
    
int nCount = GetVisibleCount(); 
    
forint i=0 ; i<nCount-1 ; i++ ) 
     hItem 
= GetNextVisibleItem( hItem ); 
     
if( hItem ) 
      SelectDropTarget( hItem ); 
     m_hItemDragD 
= hItem; 
     CImageList::DragShowNolock ( 
true ); 
   } 
  } 
 } 
 
else
  CTreeCtrl::OnTimer(nIDEvent); 

//////////////////////////////////////////////////////////// 
BOOL CDragTreeDlg::OnInitDialog() 

 CDialog::OnInitDialog(); 
 …………………….
//此處代碼省略 
 
// TODO: Add extra initialization here 
 m_image.Create ( IDB_TREEIMAGE,16,1,RGB(255,255,255) ); 
 m_wndTree.SetImageList ( 
&m_image,TVSIL_NORMAL ); 
 HTREEITEM hti1 
= m_wndTree.InsertItem ( _T("唐詩"),0,1 ); 
 HTREEITEM hti2 
= m_wndTree.InsertItem ( _T("宋詞"),0,1 ); 
 HTREEITEM hti3 
= m_wndTree.InsertItem ( _T("元曲"),0,1 ); 
 HTREEITEM hti4 
= m_wndTree.InsertItem ( _T("李白"),0,1,hti1 ); 
 m_wndTree.InsertItem ( _T(
"靜夜思(床前明月光)"),0,1,hti4 ); 
 m_wndTree.InsertItem ( _T(
"將進酒(君不見黃河之水天上來)"),0,1,hti4 ); 
 m_wndTree.InsertItem ( _T(
"望廬山瀑布(日照香爐生紫煙)"),0,1,hti4 ); 
 m_wndTree.InsertItem ( _T(
"蜀道難(噫吁戲,危乎高哉)"),0,1,hti4 ); 
 HTREEITEM hti5 
= m_wndTree.InsertItem ( _T("杜甫"),0,1,hti1 ); 
 m_wndTree.InsertItem ( _T(
"蜀相(丞相祠堂何處尋)"),0,1,hti5 ); 
 m_wndTree.InsertItem ( _T(
"春望(國破山河在)"),0,1,hti5 ); 
 m_wndTree.InsertItem ( _T(
"茅屋為秋風所破歌(八月秋高風怒號)"),0,1,hti5 ); 
 HTREEITEM hti6 
= m_wndTree.InsertItem ( _T("白居易"),0,1,hti1 ); 
 m_wndTree.InsertItem ( _T(
"長恨歌(漢皇重色思傾國)"),0,1,hti6 ); 
 m_wndTree.InsertItem ( _T(
"琵琶行並序(潯陽江頭夜送客)"),0,1,hti6 ); 
 m_wndTree.InsertItem ( _T(
"李清照"),0,1,hti2 ); 
 m_wndTree.InsertItem ( _T(
"柳永"),0,1,hti2 ); 
 
return TRUE; // return TRUE unless you set the focus to a control 
}

 

posted @ 2011-11-04 11:23 Jacc.Kim 閱讀(730) | 評論 (0)編輯 收藏

void CMenuView::OnRButtonDown(UINT nFlags, CPoint point)  

{  

    // TODO:    

    //動態創建彈出菜單   

    CMenu menu;  

    menu.CreatePopupMenu(); //創建一個彈出菜單   

    menu.AppendMenuW(MF_BYCOMMAND | MF_STRING, ID_RIGHT_CLEAR, _T("剪切(&X)")); //添加子菜單項   

    menu.AppendMenuW(MF_BYCOMMAND | MF_STRING, ID_RIGHT_COPY, _T("復制(&C)"));  

    menu.AppendMenuW(MF_BYCOMMAND | MF_STRING, ID_RIGHT_PASTE, _T("粘貼(&P)"));  

    menu.AppendMenuW(MF_SEPARATOR);  

    menu.AppendMenuW(MF_BYCOMMAND | MF_STRING, ID_RIGHT_CLEAR, _T("清除\tCtrl + C"));  

    ClientToScreen(&point); //將客戶區的坐標轉化為屏幕的坐標   

    menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTALIGN, point.x, point.y, this); //加載彈出菜單   

  

    CView::OnRButtonDown(nFlags, point);  

posted @ 2011-11-03 15:05 Jacc.Kim 閱讀(809) | 評論 (0)編輯 收藏

僅列出標題
共14頁: First 6 7 8 9 10 11 12 13 14 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            极品少妇一区二区三区| 久久精品视频播放| 欧美一区二区三区在线视频| 亚洲视频中文字幕| 亚洲视频在线观看免费| 午夜视黄欧洲亚洲| 久久久久久久综合狠狠综合| 久久综合婷婷| 亚洲乱码一区二区| 久久福利毛片| 欧美激情在线观看| 国产精品美女主播| 曰韩精品一区二区| 亚洲天堂第二页| 久久频这里精品99香蕉| 亚洲国产精品一区二区www在线| 欧美高清不卡| 亚洲一区二区不卡免费| 久久精品国产99| 欧美日韩国产色站一区二区三区| 国产精品专区h在线观看| 亚洲国内自拍| 久久99在线观看| 亚洲国产导航| 亚洲男女毛片无遮挡| 欧美va亚洲va香蕉在线| 国产精品一区二区女厕厕| 91久久久久| 久久精品一区二区三区不卡| 日韩视频免费在线观看| 久久综合久久综合久久| 国产精品自在在线| 亚洲精品视频在线看| 久久免费视频在线| 亚洲伊人伊色伊影伊综合网| 欧美电影免费观看高清| 伊人夜夜躁av伊人久久| 性8sex亚洲区入口| 日韩特黄影片| 欧美激情精品久久久久久久变态| 激情欧美丁香| 久久久精品五月天| 亚洲午夜视频在线| 欧美日韩精品一区二区天天拍小说| 激情小说另类小说亚洲欧美| 久久精品午夜| 午夜精品久久久久久99热软件| 欧美人与禽猛交乱配| 欧美丝袜一区二区| 欧美连裤袜在线视频| 在线视频国内自拍亚洲视频| 欧美一级理论性理论a| 野花国产精品入口| 欧美日韩亚洲一区二区三区四区| 亚洲激情中文1区| 欧美国产综合视频| 免费在线亚洲欧美| 亚洲久久一区二区| 91久久久亚洲精品| 欧美日韩精品免费看| 在线综合视频| 亚洲少妇诱惑| 国产日韩欧美在线| 久久免费高清| 农村妇女精品| 日韩小视频在线观看专区| 亚洲日本aⅴ片在线观看香蕉| 另类天堂av| 日韩视频一区| 亚洲一二三区在线| 国产日韩欧美日韩大片| 久久久综合网站| 久久人人爽人人| 亚洲乱码久久| 亚洲一区二区三区三| 国产日韩综合| 亚洲第一区色| 欧美视频在线一区| 欧美中文字幕久久| 老司机成人网| 亚洲视频免费| 欧美一区二区三区久久精品| 激情久久综合| 亚洲精选视频在线| 国产欧美日韩专区发布| 免费国产一区二区| 欧美四级在线观看| 老牛影视一区二区三区| 欧美激情视频在线播放| 欧美一区二区三区在线看 | 日韩亚洲国产精品| 中文亚洲视频在线| 国产自产高清不卡| 91久久久久久久久久久久久| 国产欧美日本一区视频| 欧美高清在线观看| 国产伦精品一区二区三区在线观看| 老司机午夜精品| 欧美偷拍一区二区| 欧美成人一区在线| 国产精品日本一区二区| 欧美成人免费网| 国产精品三上| 亚洲三级免费观看| 激情av一区二区| 亚洲欧美久久久| 91久久精品美女| 欧美在线精品免播放器视频| 亚洲一区精品视频| 久久国产精品亚洲va麻豆| 亚洲第一主播视频| 亚洲一区二区在线播放| 亚洲精华国产欧美| 欧美一级艳片视频免费观看| av成人激情| 欧美v国产在线一区二区三区| 欧美一区亚洲| 欧美性猛交视频| 亚洲人线精品午夜| 亚洲大胆av| 久久激情五月激情| 欧美一区三区二区在线观看| 欧美日本一区| 亚洲国产高潮在线观看| 在线观看久久av| 久久成人免费网| 久久免费视频一区| 精品动漫一区二区| 欧美一级淫片播放口| 性视频1819p久久| 国产精品久久久久久一区二区三区| 亚洲电影第1页| 亚洲国产高清一区| 久久日韩粉嫩一区二区三区| 久久综合久久综合九色| 红桃视频成人| 久久视频在线视频| 欧美成人免费大片| 91久久国产综合久久| 免费欧美在线| 亚洲国产二区| 一区二区精品| 国产精品成人免费精品自在线观看| 日韩亚洲一区二区| 亚洲一区视频在线| 国产精品久久久久影院色老大| 这里是久久伊人| 欧美在线日韩| 在线免费精品视频| 欧美xx69| 亚洲视频大全| 久久久久国产精品一区| 精品999在线播放| 久久一区亚洲| 亚洲精品女人| 亚洲视频综合在线| 国产免费亚洲高清| 久久人人爽人人| 99精品热6080yy久久| 亚洲欧美在线高清| 激情综合在线| 欧美日韩国产在线播放| 亚洲一区二区在线免费观看| 久久久99免费视频| 亚洲日本欧美| 国产精品腿扒开做爽爽爽挤奶网站| 欧美一区二区三区四区视频 | 久久久久国产精品午夜一区| 亚洲级视频在线观看免费1级| 欧美日韩高清在线观看| 午夜精品久久久久久久99热浪潮| 久久综合九色综合欧美狠狠| 亚洲视频视频在线| 国产午夜久久| 欧美日本国产在线| 久久精品一本久久99精品| 亚洲精品系列| 亚洲一区欧美一区| 久久爱www.| 在线国产欧美| 亚洲欧美在线高清| 亚洲视频一区二区在线观看 | 欧美亚洲系列| 久久影院午夜片一区| 小处雏高清一区二区三区| 欧美精品久久一区二区| 欧美电影免费观看| 国产欧美日韩视频一区二区三区| 亚洲高清色综合| 最新国产の精品合集bt伙计| 久久久久国内| 模特精品裸拍一区| 亚洲激情影视| 欧美日韩在线三区| 亚洲网站在线看| 欧美一区二区在线免费观看| 国产亚洲精品自拍| 欧美国产视频在线观看| 亚洲精品久久久久久久久久久久| 亚洲精品视频免费在线观看|