/******************************************************************************
 * Ȩ(C)2009,ͨѶɷ޹˾
 * ģ   ĴָЧ
 * ļƣ 2DThumbTouch.c
 * ļʶ
 * ժҪ
 * 
 * ޸      汾     ޸ı       ޸       ޸
 * ----------------------------------------------------------------------------
 * 2009/04/01                              ͯ       
 * 2009/08/27                           zhangchao172758    ޸
 1 ޸˱߽жϵ˻ĽӿϢ 2009-8-27
 *****************************************************************************/


/******************************************************************************
 *                                 ļ
 *****************************************************************************/
#include "gui_g.h"
#include "zcoregui.h"
#include "gdi_inter.h"
#include "window_inter.h"
#include "zcore_picture.h"
#include "zcore_config.h"
#include "GuiTool_mem.h"
#include "ctrl/2dthumbtouch.h"
/******************************************************************************
 *                                   
 *****************************************************************************/
 
/******************************************************************************
 *                                  궨
 *****************************************************************************/
#define SCREEN_WIDTH WIDTHOFPHYGC                 /*Ļ*/
#define SCREEN_HEIGHT HEIGHTOFPHYGC               /*Ļ߶*/
#define SCREEN_DEPTH BYTESPERPHYPIXEL             /*Ļ*/
#define SCREEN_BUFF_SIZE LENGHTPHYGCBUFF 		 /*ĻС*/	
#define SCREEN_LINE_SIZE (WIDTHOFPHYGC)*(BYTESPERPHYPIXEL) 		 /*ĻС*/	


#define TIME_FOR_2D 113                /*2dʱ*/
#ifndef WIN32
#define TIME_INTERVAL 3          /*ʱ*/ 
#else
#define TIME_INTERVAL 6               /*ʱ*/ 
#endif
#define THUMBTOUCHGOON         1        /**/
#define THUMBTOUCHSTOP         0        /*Ҫ*/
#define TT_INERTIA_SPEED       50   /*ƶٶϵ*/
#define TT_INERTIA_SPEED_THRESHOLD       300    /*ƶٶֵ*/

#define GET_OPPOSITION_NUMBER(d)     ((~d)+1)     /* ȡ෴ */
#define MOUSE_MOVE_THRESHOLD 2   /* ƶֵ */
#define THUMBTOUCH_FRAME_TOTALCOUNT  5 /* ƴͼԻ淽ʽЧ֡,2010_01_08*/
#define THUMBTOUCH_SLOWDOWN_RATE 0.85F
#define THUMBTOUCH_REBOUND_RATE 0.6F
#define THUMBTOUCH_FREE_RUN_SENSITIVITY 0.05F 
#define THUMBTOUCH_POS_DELTA      6
#define THUMBTOUCH_FREE_RUN_SCROLL_COEFFICIENT     0.95F
#define THUMBTOUCH_MOVE_INTERVAL_TIME_THRESHOLD 5   /* ƶֵ */
#define THUMBTOUCH_SPEED_THRESHOLD 24   /* Ի̧ʱٶȷֵԽʾԽ׹ */
#define THUMBTOUCH_INERTIA_PAGENUMBER 3 /* Ŀǰֵ֧ƴͼʽԻҳ */
/******************************************************************************
 *                                Ͷ
 *****************************************************************************/
typedef enum
{	
	DIRECT_NONE,
	DIRECT_UP_2D,                /*ƶ,˵*/
	DIRECT_DOWN_2D	
}ThumbTouch_MoveDirection;

typedef enum
{	
	MOVE_WITH_SCROLLBAR,          
	MOVE_WITHOUT_SCROLLBAR     
}ThumbTouch_MergeAreaType;       /* ƴͼ: Ƿ */

typedef enum
{	
	DIRECT_DRAW_MODE = 1,           /* ֱӻģʽthumbtouch_draw_full_screenĲֵ */
	INDIRECT_DRAW_MODE     
}ThumbTouch_DrawMode;      

typedef enum
{	
	THUMB_BOUNDARY_TOP,          
	THUMB_BOUNDARY_BOTTOM     
}ThumbTouch_BoundaryType;    /* ߽*/

typedef enum
{	
	THUMB_PART_ITEM,          
	THUMB_WHOLE_ITEM     
}ThumbTouch_AdjustType;    /* ֹͣʱҪ*/

typedef struct T_2D_ThumberTouch_StateData
{
    HWND    hCurrent2DWin;           /*¼ǰ2dЧĴ*/
    ZBOOL   bScrolledPrepare;        /*ʾǷڰѹ״̬*/
    ZBOOL   bBeginRebound;           /*Ƿʼ*/
  	POINT   pFirstPos;		         /*ʱλ 2009-12-4*/
	ZSINT32 iFirstMoment;		     /*ʱʱ 2009-12-4*/
    ZSINT32 iDirect2D;               /*ֱƶķ1ʾ£2ʾ,Ļͼ˵*/
    ZBOOL   bInertiaFlag;            /*ǷԻ*/
    ZSINT32 iCacheDistance;          /*ڼ¼ľ仯*/
    ZBOOL   bGetBuffer;				 /*Ƿõ */
    ZSINT32 iMoveNum;                /*¼ƶ*/
    ZSINT32 iTotalMoveHeight;        /*¼ֱƶ֮͡ Ǹֵ,ֵ*/
    ZSINT32 iOldY;                   /*¼֮ǰλ*/
    ZSINT32 iOldTimeVal;             /*¼ϴϢʱ*/
    ZSINT32 iNowTimeVal;             /*¼ǰϢʱ*/
    ZSINT32 iSpeed;                  /*¼ƶٶ*/
    ZSINT32 iMoveHeight;             /*¼move ƶľ  Ǹֵ,ֵ*/	
    ZSINT32 iViewHight;			     /*¼ؼݸ߶Ⱥͼ߶ȵĸ߶Ȳ */
	ZSINT32 iClientHight;			 /*ĸ߶ */
    ZSINT32 iCurrentOffsetY;	     /*¼ǰĻλƫ */
    ZBOOL   bMouseMoveCrossBorder;   /*ƶǷԽ*/	
    ZSINT32 iItemHeight;             /*ÿһбĸ߶*/
	ZSINT32	iCountFrame;		     /*¼Чǰ֡*/
	ZSINT32 iOffset;                 /*ԻƷʽЧ*/
	ZBOOL   bThumbTouchState;        /*Ч״̬־ΪTRUEʾЧ*/
	PBITMAP pbmpBkg;                 /*ԻƷʽʱûñͼƬ*/
}ThumbTouch_StateData;

/******************************************************************************
 *                              ⲿ
 *****************************************************************************/
ZCHAR  *p2DStartBuffer  = NULL;
ZCHAR  *p2DEndBuffer    = NULL;
ZCHAR  *p2DPreBuffer    = NULL;	
extern EXECTHUMBTOUCH ExecuteThumbTouch;
extern ZSINT32 g_ThumbtouchInertiaPage;

extern ZSINT32 g_ThumbtouchDisable;
/******************************************************************************
 *                             ⲿԭ                                   *
 *****************************************************************************/
extern ZVOID WIN32_GetStartSreenImage(ZSINT32 ipage);
extern ZVOID WIN32_GetEndScreenImage(ZVOID);
extern ZVOID WIN32_GetStartSreenImageEx(ZSINT32 iPage);
extern ZVOID SDev_LcdDirectRefresh(const RECT *pRect);
extern ZBOOL SDev_UpdateSpecifiedRect(RECT rt);
extern ZCHAR* get_GALgfxBuf(ZVOID);
extern PMSGQUEUE GetMsgQueue (HWND hWnd);
extern ZBOOL isValidaWin(HWND hWnd );
extern UINT32 tp_os_current_tick_get(ZVOID);
extern HWND dskGetCaretWin(HWND hWnd);


/******************************************************************************
 *                               ر
 *****************************************************************************/
static ThumbTouch_StateData sTTStateData = {0};
static ZCHAR  *s_EndBuffer  = NULL;
static ZCHAR  *s_StartBuffer  = NULL;

static ZBOOL s_bBeginMove = FALSE;
static ZSINT32 g_current_time = 0;

static ZSINT32 s_iCountWindowForThumbTouch = 0;    /* ʹĴָܵĴڸ */
static ZSINT32 s_thumbtouch_current_time = 0;


/***************************************************************************
 *                              ֲԭ
 ***************************************************************************/
static ZVOID thumbtouch_init(ZVOID);
static ZSINT32 thumbtouch_get_item_height(HWND hWnd);
static ZSINT32 thumbtouch_get_view_height(HWND hWnd);
static ZSINT32 thumbtouch_get_content_rate(HWND hWnd);
static ZSINT32 thumbtouch_get_current_pos(HWND hWnd);
static ZVOID thumbtouch_set_current_pos(HWND hWnd, ZSINT32 y,ZSINT32 flag);
static ZVOID thumbtouch_get_effect_rect(HWND hWnd, RECT *rect);
static ZVOID thumbtouch_format_effect_rect(HWND hWnd, RECT *rect);
static ZVOID thumbtouch_merge_pic(ZVOID *buffend,ZVOID *buffstart, HWND hWnd, ZSINT32 y,ZSINT32 flag);
static ZSINT32 thumbtouch_calc_pos_for_slowdown(ZSINT32 length,ZFLOAT32 rate);
static ZVOID thumbtouch_paint_now(HWND hWnd);
static ZBOOL thumbtouch_check_rebound(HWND hWnd);
static ZVOID thumbtouch_rebound(HWND hWnd,ZSINT32 flag);
static ZSINT32 thumbtouch_adjust_on_finish(HWND hWnd);
static ZVOID thumbtouch_stop_inertia(HWND hWnd);
static ZVOID thumbtouch_inertia(HWND hWnd);
static ZVOID thumbtouch_draw_full_screen(ZSINT32 drawMode);
static ZSINT32 thumbtouch_calc_inertia_rate(HWND hWnd, ZSINT32 distance);
static ZVOID thumbtouch_end_effect(HWND hWnd);
static ZSINT32 thumbtouch_handle_lbuttonup(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam);
static ZSINT32 thumbtouch_set_buffer(ZSINT32 iTotalHeight);
static ZBOOL thumbtouch_check_move_onlbuttonup(HWND hWnd);
static ZBOOL thumbtouch_check_inertia_onlbuttonup(HWND hWnd);
static ZSINT32 thumbtouch_adjust_ex_on_finish(HWND hWnd);
static ZSINT32 thumbtouch_adjust_ex2(HWND hWnd);
static ZSINT32 thumbtouch_handle_lbuttondown(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam);
static ZVOID thumbtouch_set_movespeed(ZVOID);
static ZVOID thumbtouch_check_firstmove(HWND hWnd);
static ZSINT32 thumbtouch_check_real_move(ZVOID);
static ZBOOL thumbtouch_check_reach_bound(HWND hWnd, ZSINT32 lY, ZSINT32 y);
static ZBOOL thumbtouch_check_end_rebound(ZSINT32 y);
static ZBOOL thumbtouch_check_if_moveout(HWND hWnd,ZSINT32 x,ZSINT32 y);
static ZSINT32 thumbtouch_handle_mousemove(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect);
static ZBOOL thumbtouch_check_if_moveout_ex(HWND hWnd,WPARAM wParam, LPARAM lParam);
static ZSINT32 thumbtouch_handle_mousemovein(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam);
static ZSINT32 thumbtouch_handle_timer(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect);
static ZVOID zCore_CleanAllDirtyChild(HWND hWnd);

/***************************************************************************
 *                              ֲʵ
 ***************************************************************************/
/**
 * ƣ thumbtouch_allocatebuffer
 * Ĵָڴ
 * ˵ 
 *   ֵ 
 * ˵ 
 */
static ZBOOL thumbtouch_allocatebuffer()
{
	if(g_ThumbtouchDisable)
		return TRUE;
	if(g_ThumbtouchInertiaPage!=1 && g_ThumbtouchInertiaPage != (THUMBTOUCH_INERTIA_PAGENUMBER))
		g_ThumbtouchInertiaPage = 1;

	if(p2DPreBuffer == NULL)
	{
	   p2DPreBuffer = (ZCHAR*)GUI_MALLOC(LENGHTPHYGCBUFF*(2*g_ThumbtouchInertiaPage+1));
	   if(!p2DPreBuffer)
		  return  FALSE;
	}	
	if(p2DPreBuffer != NULL)
	{
		p2DStartBuffer = p2DPreBuffer + LENGHTPHYGCBUFF*g_ThumbtouchInertiaPage;
		p2DEndBuffer = p2DPreBuffer + LENGHTPHYGCBUFF*(g_ThumbtouchInertiaPage+1);
	}
	return TRUE;
}

/**
 * ƣ thumbtouch_freebuffer
 * Ĵָͷڴ
 * ˵ 
 *   ֵ 
 * ˵ 
 */
static ZVOID thumbtouch_freebuffer()
{
	if(s_iCountWindowForThumbTouch == 0)
	{
		if(p2DPreBuffer != NULL)
			GUI_FREE(p2DPreBuffer);
		p2DStartBuffer = NULL;
		p2DEndBuffer = NULL;
		p2DPreBuffer = NULL;
	}
}

/**
 * ƣ thumbtouch_init
 * ȫֱ ʼ
 * ˵ 
 *   ֵ 
 * ˵ 
 */
static ZVOID thumbtouch_init(ZVOID)
{ 
	sTTStateData.hCurrent2DWin = HWND_NULL;
	sTTStateData.bScrolledPrepare = FALSE;
	sTTStateData.bBeginRebound = FALSE;
	sTTStateData.pFirstPos.x = 0;
	sTTStateData.pFirstPos.y = 0;
	sTTStateData.iFirstMoment = 0;
	sTTStateData.iDirect2D = 0;
	sTTStateData.bInertiaFlag = FALSE;
	sTTStateData.iCacheDistance = 0;
	sTTStateData.bGetBuffer = FALSE;
	sTTStateData.iMoveNum = 0;
	sTTStateData.iTotalMoveHeight = 0;
	sTTStateData.iOldY = 0; 
	sTTStateData.iOldTimeVal = 0;
	sTTStateData.iNowTimeVal = 0;
	sTTStateData.iSpeed = 0;
	sTTStateData.iMoveHeight = 0;
	sTTStateData.iViewHight = 0;
	sTTStateData.iCurrentOffsetY = 0;
	sTTStateData.bMouseMoveCrossBorder = FALSE;
	sTTStateData.iItemHeight = 0;
	sTTStateData.bThumbTouchState = FALSE;
	sTTStateData.iOffset = 0;
	sTTStateData.iCountFrame = 0;
	sTTStateData.iClientHight = 0;
}

/**
 * ƣ thumbtouch_get_item_height
 *  ȡڵÿһбĸ߶
 * ˵ (IN) hWndھ
 *   ֵ ÿһбĸ߶
 * ˵ 
 */
static ZSINT32 thumbtouch_get_item_height(HWND hWnd)
{ 
	return SendMessage(hWnd, MSG_2D_GET_ITEM_HEIGHT, 0, 0);	
}

/**
 * ƣ thumbtouch_get_view_height
 *  ȡڵݸ߶ͼ߶ȵĲֵ
 * ˵ (IN) hWndھ
 *   ֵ ڵݸ߶ͼ߶ȵĲֵ
 * ˵ 
 */
static ZSINT32 thumbtouch_get_view_height(HWND hWnd)
{ 
	return SendMessage(hWnd, MSG_2D_GET_VIEW_HEIGHT, 0, 0);	
}

/**
 * ƣ thumbtouch_get_content_rate
 *  ȡڵݸ߶ͼ߶ȵıֵ
 * ˵ (IN) hWndھ
 *   ֵ ڵݸ߶ͼ߶ȵıֵ
 * ˵ 
 */
static ZSINT32 thumbtouch_get_content_rate(HWND hWnd)
{ 
	return SendMessage(hWnd, MSG_2D_GET_CONTENT_RATE, 0, 0);	
}

/**
 * ƣ thumbtouch_get_current_pos
 *  ȡϽǵλ
 * ˵ (IN) hWndھ
 *   ֵ Ͻǵλ
 * ˵ 
 */
static ZSINT32 thumbtouch_get_current_pos(HWND hWnd)
{
    return SendMessage(hWnd, MSG_2D_GET_CURRENT_POS, 0, 0);
} 

/**
 * ƣ thumbtouch_set_current_pos
 *  ôݵλ
 * ˵ (IN) hWndھ
 *                            (IN) y: λõYֵ
                               (IN)flag: ʾǷҪ䵽
 *   ֵ 
 * ˵ 
 */
static ZVOID thumbtouch_set_current_pos(HWND hWnd, ZSINT32 y, ZSINT32 flag)
{
    SendMessage(hWnd, MSG_2D_SET_CURRENT_POS, y, flag);
}

/**
 * ƣ thumbtouch_get_effect_rect
 *  ȡн2DЧ
 * ˵ (IN) hWndھ
 *            (OUT) rect: ָ
 *   ֵ 
 * ˵ 
 */
static ZVOID thumbtouch_get_effect_rect(HWND hWnd, RECT *rect)
{
    SendMessage(hWnd, MSG_2D_GET_RECT, (ZSINT32)rect, 0);
}

/**
 * ƣ thumbtouch_format_effect_rect
 *  2DΪڵȫּ֮
 * ˵ (IN) hWndھ
 *            (IN,OUT) rect: ָ
 *   ֵ 
 * ˵ 
 */
static ZVOID thumbtouch_format_effect_rect(HWND hWnd, RECT *rect)
{
    PMAINWIN pMw = NULL;	
    RECT crect = {0, 0, 0, 0};
	
    pMw = (PMAINWIN)hWnd;	
	if(NULL == pMw)
	{
		return;
	}
	if(!(pMw->dwStyle & WS_VISIBLE))
	{
		return;
	}
	crect = pMw->pGCRInfo->crgn.rcBound;
    if(rect->left < crect.left)
    {
        rect->left = crect.left;
    }
    if(rect->top < crect.top)
    {
        rect->top = crect.top;
    }
    if(rect->right > crect.right)
    {
        rect->right = crect.right;
    }
    if(rect->bottom > crect.bottom)
    {
        rect->bottom = crect.bottom;
    }
}

/**
 * ƣ thumbtouch_merge_pic
 *  ϳͼƬͼƬYƫy
 * ˵ (IN) buffendendͼƬ, ͼƬ
 *            (IN) buffstart: startͼƬ
 *            (IN) hWnd: ھ
 *            (IN) y: ͼƬƫ
 *   ֵ 
 * ˵ 
 */
static ZVOID thumbtouch_merge_pic(ZVOID *buffend,ZVOID *buffstart,HWND hWnd,ZSINT32 y,ZSINT32 flag)
{   
	ZSINT32 iheight = 0;
	ZSINT32 width = 0;
	ZSINT32 vCunt = 0;
    ZCHAR *b1 = 0;
    ZCHAR *b2 = 0;
    ZCHAR *b3 =0 ;
	ZCHAR *pdestBuffer = NULL;
    RECT rect = {0};

    GetClientRect(hWnd, &rect);
    thumbtouch_get_effect_rect(hWnd, &rect);
    ClientToScreen(hWnd,&rect.left,&rect.top);
    ClientToScreen(hWnd,&rect.right,&rect.bottom);
    thumbtouch_format_effect_rect(hWnd, &rect);
    pdestBuffer = (ZCHAR*)get_GALgfxBuf();
    iheight = rect.bottom - rect.top;
    width = rect.right - rect.left;
	if(y > iheight || y < -iheight ) 
	{
		return;
	}
	
	b1 = (ZCHAR *)buffstart + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
	b2 = (ZCHAR *)buffend + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
    b3 = pdestBuffer + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
    
	if(y >= 0)      /* ָ»ݵĶ */
	{   
		b2 += (iheight - y)*SCREEN_WIDTH*SCREEN_DEPTH;
		for (vCunt =0; vCunt < y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b2, width*SCREEN_DEPTH);
			b2 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
		for (vCunt = 0; vCunt < iheight - y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b1, width*SCREEN_DEPTH);	
			b1 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
	}
	else        /* ָϻݵĵײ */
	{   
		b1 += (-y)*SCREEN_WIDTH*SCREEN_DEPTH;
       	for (vCunt =0; vCunt < iheight + y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b1, width*SCREEN_DEPTH);
			b1 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
		for (vCunt = 0; vCunt < - y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b2, width*SCREEN_DEPTH);	
			b2 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
	}
    thumbtouch_draw_full_screen(INDIRECT_DRAW_MODE);
}

/**
 * ƣ thumbtouch_merge_to_dst
 *  ϳͼƬͼƬYƫy
 * ˵ (IN) buffendendͼƬ, ͼƬ
 *            (IN) buffstart: startͼƬ
 *            (IN) hWnd: ھ
 *            (IN) y: ͼƬƫ
 *   ֵ 
 * ˵˵: ʹô˽ӿ 
 */
static ZVOID thumbtouch_merge_to_dst(ZVOID *buffend,ZVOID *buffstart,ZVOID *buffdst,HWND hWnd,ZSINT32 y,ZSINT32 flag)
{   
	ZSINT32 iheight = 0;
	ZSINT32 width = 0;
	ZSINT32 vCunt = 0;
    ZCHAR *b1 = 0;
    ZCHAR *b2 = 0;
    ZCHAR *b3 =0 ;
	ZCHAR *pdestBuffer = buffdst;
    RECT rect = {0};

    GetClientRect(hWnd, &rect);
    thumbtouch_get_effect_rect(hWnd, &rect);
    ClientToScreen(hWnd,&rect.left,&rect.top);
    ClientToScreen(hWnd,&rect.right,&rect.bottom);
    thumbtouch_format_effect_rect(hWnd, &rect);
   
    iheight = rect.bottom - rect.top;
    width = rect.right - rect.left;
	if(y > iheight || y < -iheight ) 
	{
		return;
	}
	if(pdestBuffer == NULL)
	{
		return;
	}
	
	if((rect.right > (SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH-THUMBTOUCH_X_MARGIN))
	 	&&(flag != MOVE_WITHOUT_SCROLLBAR))   
	{
		width = SCREEN_WIDTH;
    }
	b1 = (ZCHAR *)buffstart + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
	b2 = (ZCHAR *)buffend + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
    b3 = pdestBuffer + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
    
	if(y >= 0)      /* ָ»ݵĶ */
	{   
		b2 += (iheight - y)*SCREEN_WIDTH*SCREEN_DEPTH;
		for (vCunt =0; vCunt < y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b2, width*SCREEN_DEPTH);
			b2 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
		for (vCunt = 0; vCunt < iheight - y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b1, width*SCREEN_DEPTH);	
			b1 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
	}
	else        /* ָϻݵĵײ */
	{   
		b1 += (-y)*SCREEN_WIDTH*SCREEN_DEPTH;
       	for (vCunt =0; vCunt < iheight + y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b1, width*SCREEN_DEPTH);
			b1 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
		for (vCunt = 0; vCunt < - y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b2, width*SCREEN_DEPTH);	
			b2 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
	}
	
}

/**
 * ƣ thumbtouch_merge_to_dst2
 *  ϳͼƬͼƬYƫy
 * ˵ (IN) buffendendͼƬ, ͼƬ
 *            (IN) buffstart: startͼƬ
 *            (IN) hWnd: ھ
 *            (IN) y: ͼƬƫ
 *   ֵ 
 * ˵ 
 */
static ZVOID thumbtouch_merge_to_dst2(ZVOID *buffend,ZVOID *buffstart,ZVOID *buffdst,HWND hWnd,ZSINT32 y,ZSINT32 flag)
{   
	ZSINT32 iheight = 0;
	ZSINT32 width = 0;
	ZSINT32 vCunt = 0;
    ZCHAR *b1 = 0;
    ZCHAR *b2 = 0;
    ZCHAR *b3 =0 ;
	ZCHAR *pdestBuffer = buffdst;
    RECT rect = {0};

    GetClientRect(hWnd, &rect);
    thumbtouch_get_effect_rect(hWnd, &rect);
    ClientToScreen(hWnd,&rect.left,&rect.top);
    ClientToScreen(hWnd,&rect.right,&rect.bottom);
    thumbtouch_format_effect_rect(hWnd, &rect);
   
    iheight = rect.bottom - rect.top;
    width = rect.right - rect.left;
	if(y > iheight || y < -iheight ) 
	{
		return;
	}
	if(pdestBuffer == NULL)
	{
		return;
	}
	
	if((rect.right > (SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH-THUMBTOUCH_X_MARGIN))
	 	&&(flag != MOVE_WITHOUT_SCROLLBAR))   
	{
		width = SCREEN_WIDTH;
    }
	b1 = (ZCHAR *)buffstart + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
	b2 = (ZCHAR *)buffend + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
    b3 = pdestBuffer + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
    
	if(y >= 0)      /* ָ»ݵĶ */
	{   
		b1 += (iheight - y)*SCREEN_WIDTH*SCREEN_DEPTH;
		b3 += iheight*SCREEN_WIDTH*SCREEN_DEPTH;
		for (vCunt =0; vCunt < iheight - y; vCunt++)
		{            
			b1 -= SCREEN_WIDTH*SCREEN_DEPTH;
			b3 -= SCREEN_WIDTH*SCREEN_DEPTH;
			GUI_MEM_CPY(b3, b1, width*SCREEN_DEPTH);
		}	
			
		b2 += (iheight - y)*SCREEN_WIDTH*SCREEN_DEPTH;
		b3 = pdestBuffer + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
		for (vCunt =0; vCunt < y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b2, width*SCREEN_DEPTH);
			b2 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}	
	}
	else        /* ָϻݵĵײ */
	{   
		b1 += (-y)*SCREEN_WIDTH*SCREEN_DEPTH;
       	for (vCunt =0; vCunt < iheight + y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b1, width*SCREEN_DEPTH);
			b1 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
		for (vCunt = 0; vCunt < - y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b2, width*SCREEN_DEPTH);	
			b2 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
	}
}
/**
 * ƣ mergePicForMms
 *  ϳͼƬͼƬYƫy
 * ˵ (IN) buffendendͼƬ, ͼƬ
 *            (IN) buffstart: startͼƬ
 *            (IN) hWnd: ھ
 *            (IN) y: ͼƬƫ
 *   ֵ 
 * ˵ 
 */
static ZVOID mergePicForMms(ZVOID *buffend,ZVOID *buffstart,HWND hWnd,ZSINT32 y,ZSINT32 flag)
{   
	ZSINT32 height = 0;
	ZSINT32 width = 0;
	ZSINT32 vCunt = 0;
    ZCHAR *b1 = 0;
    ZCHAR *b2 = 0;
    ZCHAR *b3 =0 ;
	ZCHAR *pdestBuffer = NULL;
    RECT rect = {0};
	
    GetClientRect(hWnd, &rect);
    thumbtouch_get_effect_rect(hWnd, &rect);

    ClientToScreen(hWnd,&rect.left,&rect.top);
    ClientToScreen(hWnd,&rect.right,&rect.bottom);
    thumbtouch_format_effect_rect(hWnd, &rect);
    pdestBuffer = (ZCHAR*)get_GALgfxBuf();

    height = rect.bottom - rect.top;
    width = rect.right - rect.left;
    if(rect.right >= (SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH-THUMBTOUCH_X_MARGIN) /*&& (flag ==1)*/)   
	{
		width = SCREEN_WIDTH; 
    }

    if(y > height || y < -height)
        {
            ZTE_Trace(0, 0,"\nMergePic: out of range\n");	
            return;
    }

	b1 = (ZCHAR *)buffstart + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
	b2 = (ZCHAR *)buffend + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
    b3 = pdestBuffer + (rect.top*SCREEN_WIDTH*SCREEN_DEPTH) + (rect.left*SCREEN_DEPTH);
    
	if(y >= 0)      /* ָ»ݵĶ */
	{   
		b2 += (height - y)*SCREEN_WIDTH*SCREEN_DEPTH;

		for (vCunt =0; vCunt < y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b2, width*SCREEN_DEPTH);
			b2 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
		for (vCunt = 0; vCunt < height - y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b1, width*SCREEN_DEPTH);	
			b1 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}

	}
	else        /* ָϻݵĵײ */
	{   
		b1 += (-y)*SCREEN_WIDTH*SCREEN_DEPTH;

       	for (vCunt =0; vCunt < height + y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b1, width*SCREEN_DEPTH);
			b1 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
		for (vCunt = 0; vCunt < - y; vCunt++)
		{   
            GUI_MEM_CPY(b3, b2, width*SCREEN_DEPTH);	
			b2 += SCREEN_WIDTH*SCREEN_DEPTH;
			b3 += SCREEN_WIDTH*SCREEN_DEPTH;
		}
	}
    thumbtouch_draw_full_screen(DIRECT_DRAW_MODE);
}

/**
 * ƣ thumbtouch_absolute_value
 *  int ͱľֵ
 * ˵ (IN) valueı
 *   ֵرľֵ
 * ˵ 
 */ 
static ZSINT32 thumbtouch_absolute_value(ZSINT32 value)
{
    return value >= 0 ? value : -value;
}

/**
 * ƣ thumbtouch_calc_pos_for_slowdown
 *  㵱ǰλþٺλ
 * ˵ (IN) lengthǰλ
 *   ֵ ټλ
 * ˵ 
 */ 
static ZSINT32 thumbtouch_calc_pos_for_slowdown(ZSINT32 length, ZFLOAT32 rate)
{   
	ZSINT32 mappingArray[31] = {0, 0,0,0,1,2, 3,4,5,6,9, 6,7,8,7,8, 9,10,11,11,12, 13,13,14,15,16, 17,18,19,20,21};

    if(length > 30)
	{
        return length*rate;
	}
    else if(length >= 3)
	{
        return mappingArray[length];
	}
    else
    {  
       return 0;
    }
}

/**
 * ƣ thumbtouch_paint_now
 *  ϲ㸸ڴڻϢִлơ
 * ˵ (IN) hWndھ
 *   ֵ 
 * ˵ 
 */ 
static ZVOID thumbtouch_paint_now(HWND hWnd)
{    
	HWND hParent = hWnd;
	PMAINWIN pMw = (PMAINWIN)hWnd;
	   
	if(HWND_NULL != hParent)
	{	    
		hParent = ((MAINWIN*)hParent)->hParent;
        thumbtouch_paint_now(hParent);
	}
    if(HWND_NULL != hWnd)
    {   
        if(pMw->InvRgn.rgn.head)
        {
            SendMessage((HWND)hWnd, MSG_PAINT, 0, 0);
    	}
	}
}

/**


 * ƣ thumbtouch_rebound
 *  Ч
 * ˵ (IN) hWndھ
                               (IN) flag: ʱΪƴͼṩı־λ
 *   ֵ 
 * ˵ 
 */ 
static ZVOID thumbtouch_rebound(HWND hWnd,ZSINT32 flag)
{
	ZSINT32 iEndPos = -1;
    if(sTTStateData.iTotalMoveHeight <= 0) /* ָϻ */
    {
        sTTStateData.iTotalMoveHeight = GET_OPPOSITION_NUMBER(thumbtouch_calc_pos_for_slowdown(thumbtouch_absolute_value(sTTStateData.iTotalMoveHeight),THUMBTOUCH_REBOUND_RATE));
		iEndPos = sTTStateData.iViewHight;
        }
    if(sTTStateData.iTotalMoveHeight > 0)   /* ָ» */
    {
        sTTStateData.iTotalMoveHeight = thumbtouch_calc_pos_for_slowdown(sTTStateData.iTotalMoveHeight,THUMBTOUCH_REBOUND_RATE);
		iEndPos = 0;
        }
	
    thumbtouch_set_current_pos(hWnd,iEndPos-sTTStateData.iTotalMoveHeight, flag);
}

/**
 * ƣ thumbtouch_check_rebound
 *  ƴͼʽ:ǷҪ,ƴͼģʽµķʵ֣
 * ˵ (IN) hWndھ
 *   ֵ 
 * ˵ ƴͼʽʹ
 */ 
static ZBOOL thumbtouch_check_rebound(HWND hWnd)
{
	ZSINT32 iCurrentPos = thumbtouch_get_current_pos(hWnd);
	ZSINT32 itmpPos = 0;

	sTTStateData.bBeginRebound = TRUE;
	itmpPos = iCurrentPos -sTTStateData.iTotalMoveHeight;
    if(itmpPos < 0)
	{
		SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_TOP, 0);		/* ϱ߽ */
		sTTStateData.iTotalMoveHeight -= iCurrentPos;
		while(sTTStateData.iTotalMoveHeight > 0)
		{
			sTTStateData.iTotalMoveHeight = thumbtouch_calc_pos_for_slowdown(sTTStateData.iTotalMoveHeight,THUMBTOUCH_REBOUND_RATE);
            if (NULL != s_EndBuffer)
			thumbtouch_merge_pic(s_EndBuffer, p2DStartBuffer, hWnd, sTTStateData.iTotalMoveHeight+iCurrentPos,1);
            if(sTTStateData.iTotalMoveHeight == 0)
				zcore_thread_sleep(40);
			else
            	zcore_thread_sleep(20);
		}
		return TRUE;
	}
	else if(itmpPos > sTTStateData.iViewHight)
	{
		SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_BOTTOM, 0);    /* ±߽ */
		sTTStateData.iTotalMoveHeight = -sTTStateData.iTotalMoveHeight;
		sTTStateData.iTotalMoveHeight = sTTStateData.iTotalMoveHeight - (sTTStateData.iViewHight - iCurrentPos);
		while(sTTStateData.iTotalMoveHeight > 0)
		{
			sTTStateData.iTotalMoveHeight = thumbtouch_calc_pos_for_slowdown(sTTStateData.iTotalMoveHeight,THUMBTOUCH_REBOUND_RATE);
            if (NULL != s_EndBuffer)
			thumbtouch_merge_pic(s_EndBuffer, p2DStartBuffer, hWnd, -(sTTStateData.iTotalMoveHeight+sTTStateData.iViewHight - iCurrentPos),1);
            if(sTTStateData.iTotalMoveHeight == 0)
				zcore_thread_sleep(40);
			else
            	zcore_thread_sleep(20);
		}
		return TRUE;
	}
	sTTStateData.bBeginRebound = FALSE;
	return FALSE;
}

/**
 * ƣ thumbtouch_calc_inertia_rate
 *  Чı
 * ˵ (IN) hWndھ
 *   ֵ  Чı
 * ˵ 
 */ 
static ZSINT32 thumbtouch_calc_inertia_rate(HWND hWnd, ZSINT32 distance)
{
	ZSINT32 tmpRate = 2*thumbtouch_get_content_rate(hWnd);
	
    if(distance == 2)
    {
        tmpRate = tmpRate/2;
    }
    else if(distance == 1)
    {
        tmpRate = tmpRate/4; 
    } 
	if(tmpRate == 0)
    {
        tmpRate = 1;
    }
	return tmpRate;
}

/**
 * ƣ thumbtouch_adjust_on_finish
 *  ʱĵ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ: Ҫ1.򷵻0.
 * ˵ ؼԻƷʽĵ
 */ 
static ZSINT32 thumbtouch_adjust_on_finish(HWND hWnd)
{ 
	ZSINT32   iSize = 0;
	ZSINT32   uHeightItem = 0;
	ZSINT32   uTotalCount = THUMBTOUCH_FRAME_TOTALCOUNT;
	ZSINT32   lCurrentY = thumbtouch_get_current_pos(hWnd);

	uHeightItem = sTTStateData.iItemHeight;
	if((uHeightItem > 0) && (sTTStateData.iCountFrame < uTotalCount))
	{						
		ZSINT32 iValueRes = 0;
		if(sTTStateData.iCountFrame == 0)
		{
			if(sTTStateData.iDirect2D == 0)
			{
				if(sTTStateData.iMoveHeight >= 0) 
				{
					sTTStateData.iDirect2D = DIRECT_DOWN_2D;
				}
				else if(sTTStateData.iMoveHeight < 0)
				{
					sTTStateData.iDirect2D = DIRECT_UP_2D;
				}
			}
			if(sTTStateData.iDirect2D ==DIRECT_DOWN_2D )
			{
				iSize = lCurrentY%uHeightItem;
			}
			else if(sTTStateData.iDirect2D == DIRECT_UP_2D)
			{
				iSize = lCurrentY%uHeightItem;
				iSize = uHeightItem - iSize;
			}
			iValueRes = iSize%uTotalCount;
			sTTStateData.iOffset = iSize/uTotalCount;
			iSize = sTTStateData.iOffset + iValueRes;
		}
		else
		{
			iSize = sTTStateData.iOffset;
		}

		if(iSize == 0)
			return 1;
		
		if(sTTStateData.iDirect2D == DIRECT_DOWN_2D)
			thumbtouch_set_current_pos(hWnd, lCurrentY - iSize,THUMB_PART_ITEM);
		else if(sTTStateData.iDirect2D == DIRECT_UP_2D)
			thumbtouch_set_current_pos(hWnd, lCurrentY + iSize,THUMB_PART_ITEM);
		sTTStateData.iCountFrame ++;	
		return 0;
	}		
	return 1;
}

/**
 * ƣ thumbtouch_end_effect
 *  Чɾʱͱ߽Ϣ֪ͨЧϢ
 * ˵ (IN) hWndھ
 *   ֵ 
 * ˵ ڹԺͷʹ,Իģʽ£THUMB_BOUNDARY_BOTTOMϢô
 */ 
static ZVOID thumbtouch_end_effect(HWND hWnd)
{
    ZSINT32 lCurrentY = thumbtouch_get_current_pos(hWnd);
    ZSINT32 iViewHeight = sTTStateData.iViewHight;
        
    iViewHeight = iViewHeight < 0 ? 0 : iViewHeight;
    KillTimer(hWnd,TIME_FOR_2D);
	
	if(lCurrentY >= iViewHeight) 
	{
		SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_BOTTOM, 0);    /* ±߽ 2009-11-18*/
	}
	else if(lCurrentY <= 0)
	{
		SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_TOP, 0);   /* ϱ߽ 2009-11-18*/
	}
	thumbtouch_init();
	if(GetParent(hWnd))
	{
		 SendNotifyMessage(GetParent(hWnd), MSG_2D_THUMBTOUCH_FINISH, 0, 0);
	}	
	SendNotifyMessage(hWnd, MSG_2D_THUMBTOUCH_FINISH, 0, 0);
}

/**
 * ƣ thumbtouch_calc_inertia_rate
 *  Чı
 * ˵ (IN) hWndھ
 *   ֵ 
 * ˵ 
 */ 
static ZVOID thumbtouch_stop_inertia(HWND hWnd)
{
	sTTStateData.iCacheDistance = 0;
	sTTStateData.bInertiaFlag = FALSE;
	sTTStateData.iCountFrame = 0;
	sTTStateData.iOffset = 0;
}

/**
 * ƣ thumbtouch_inertia
 *  Ч
 * ˵ (IN) hWndھ
 *   ֵ 
 * ˵ 
 */ 
static ZVOID thumbtouch_inertia(HWND hWnd)
{   
    ZSINT32 lCurrentY = thumbtouch_get_current_pos(hWnd);
    ZSINT32 iViewHeight = sTTStateData.iViewHight;
    ZSINT32 tmpdistance = 0;
	PCONTROL pCtrl = (PCONTROL)hWnd;
	
    iViewHeight = iViewHeight < 0 ? 0 : iViewHeight;
    tmpdistance = sTTStateData.iCacheDistance;
	sTTStateData.iCacheDistance = THUMBTOUCH_FREE_RUN_SCROLL_COEFFICIENT * sTTStateData.iCacheDistance;
    if(sTTStateData.iCacheDistance > 4)
    {      
        if(lCurrentY > 0 && lCurrentY < iViewHeight)
        {   
            if(sTTStateData.iCacheDistance == tmpdistance )
            {   
            
				if(!(pCtrl->dwExStyle&WS_2D_NOT_ADJUST) )
				{
	            	if(0==thumbtouch_adjust_on_finish(hWnd))
	        			return;
				}
				
                thumbtouch_stop_inertia(hWnd);
                return;
            }
            if(sTTStateData.iMoveHeight > 0)     /* » */
            {  
                if(lCurrentY - sTTStateData.iCacheDistance <= 0)
                {   
                    lCurrentY =0;
                    thumbtouch_stop_inertia(hWnd);       
                }
                else
                {
                    lCurrentY -= sTTStateData.iCacheDistance;            
                }
            }
            else if (sTTStateData.iMoveHeight < 0)   /* ϻ */
            {   
                if(lCurrentY + sTTStateData.iCacheDistance + 1 >= iViewHeight)
                {
                     lCurrentY = iViewHeight;
                     thumbtouch_stop_inertia(hWnd); 
                }
                else
                {    
                     lCurrentY += sTTStateData.iCacheDistance;
                }           
            }
 		    thumbtouch_set_current_pos(hWnd, lCurrentY,THUMB_PART_ITEM);
            return;
        }
	    else
	   	{
	   		thumbtouch_set_current_pos(hWnd, lCurrentY,THUMB_PART_ITEM);  
	   	}
    }
    else
    {  
		if(!(pCtrl->dwExStyle&WS_2D_NOT_ADJUST) )
		{
	    	if(0==thumbtouch_adjust_on_finish(hWnd))	
			return;
		}
		
        thumbtouch_end_effect(hWnd); 
    }
    thumbtouch_stop_inertia(hWnd);
}

/**
 * ƣ thumbtouch_new_page_2buff
 *  ƶbufҳbuff
 * ˵ (IN) hWndھ
 *   ֵ 
 * ˵ ҳʱһֻ3ҳҳ֪ҳƶ
 */ 
ZSINT32 thumbtouch_new_page_2buff(HWND hWnd)
{
	ZTE_Trace(0, 0,"\nthumbtouch_new_page_2buff\n");			
	if(p2DPreBuffer == NULL)
		return -1;
	if(sTTStateData.iMoveHeight > 0)
	{
		ZSINT32 i = 0;
		ZTE_Trace(0, 0,"\nbegin thumbtouch_merge_to_dst2. current time:%d\n", g_current_time);			
		for(i=6;i>0;i--)
		{
			thumbtouch_merge_to_dst2(p2DPreBuffer+((i-1)*LENGHTPHYGCBUFF),p2DPreBuffer+i*LENGHTPHYGCBUFF,p2DPreBuffer+(i*LENGHTPHYGCBUFF), hWnd,sTTStateData.iMoveHeight,1);
		}
		
		ZTE_Trace(0, 0,"\nEnd thumbtouch_merge_to_dst2. current time:%d\n", g_current_time);			
		SendMessage(hWnd,MSG_2D_NEW_PAGE_TO_BUFF, -2, sTTStateData.iTotalMoveHeight); /* Ƶǰҳ-3ҳ */
		
	}
	else if(sTTStateData.iMoveHeight < 0)
	{
		ZSINT32 i = 0;
		ZTE_Trace(0, 0,"\nbegin thumbtouch_merge_to_dst. current time:%d\n", g_current_time);			
		for(i=0;i<6;i++)
		{
			thumbtouch_merge_to_dst(p2DPreBuffer+(i+1)*LENGHTPHYGCBUFF,p2DPreBuffer+(i*LENGHTPHYGCBUFF),p2DPreBuffer+(i*LENGHTPHYGCBUFF), hWnd,sTTStateData.iMoveHeight,1);
		}
		ZTE_Trace(0, 0,"\nEnd thumbtouch_merge_to_dst. current time:%d\n", g_current_time);			
		SendMessage(hWnd,MSG_2D_NEW_PAGE_TO_BUFF, -1, sTTStateData.iTotalMoveHeight); /* Ƶǰҳ+3ҳ */
	}
	ZTE_Trace(0, 0,"\nEnd thumbtouch_new_page_2buff. current time:%d\n", g_current_time);			
	return 0;
}

/**
 * ƣ thumbtouch_inertia_for_multiPage
 *  Ч
 * ˵ (IN) hWndھ
 *   ֵ 
 * ˵ 
 */ 
static ZVOID thumbtouch_inertia_for_multiPage(HWND hWnd)
{   
    ZSINT32 lCurrentY = thumbtouch_get_current_pos(hWnd);
    ZSINT32 iViewHeight = sTTStateData.iViewHight;
    ZSINT32 tmpRate = 0;
    ZSINT32 tmpdistance = 0;
	ZSINT32 iMergeDistance = 0;
	PCONTROL pCtrl = (PCONTROL)hWnd;
	
    iViewHeight = iViewHeight < 0 ? 0 : iViewHeight;
    tmpdistance = sTTStateData.iCacheDistance;
	tmpRate = 1;
    if(sTTStateData.iCacheDistance > 0)
    {      
      
        {   
 		    sTTStateData.iCacheDistance = thumbtouch_calc_pos_for_slowdown(sTTStateData.iCacheDistance,THUMBTOUCH_SLOWDOWN_RATE);         
            if(sTTStateData.iCacheDistance == tmpdistance )
            {   
				if(!(pCtrl->dwExStyle&WS_2D_NOT_ADJUST) )
				{
	            	if(0==thumbtouch_adjust_on_finish(hWnd))
	        		{
	        			return;
	        		}
				}
 		        /* ʾֹͣʱҪ䵽 */
                thumbtouch_stop_inertia(hWnd);
                return;
            }
			thumbtouch_new_page_2buff(hWnd);	
			if(sTTStateData.iMoveHeight > 0)
		    {   
		 	   sTTStateData.iTotalMoveHeight += tmpRate*(tmpdistance - sTTStateData.iCacheDistance);		
			   sTTStateData.iMoveHeight = tmpRate*(tmpdistance - sTTStateData.iCacheDistance);
		    }
		    else if (sTTStateData.iMoveHeight < 0)
		    {   
		 	   sTTStateData.iTotalMoveHeight -= tmpRate*(tmpdistance - sTTStateData.iCacheDistance);	
			   sTTStateData.iMoveHeight = (-tmpRate)*(tmpdistance - sTTStateData.iCacheDistance);
		    }	   
			else if(sTTStateData.iMoveHeight == 0)
			 	return;
			iMergeDistance = thumbtouch_set_buffer(sTTStateData.iMoveHeight);
			thumbtouch_merge_pic(s_EndBuffer, s_StartBuffer, hWnd, iMergeDistance,1);   
			
            return;
        }
    }
    else
    { 
		ZSINT32 itmpPos = -1;
		
		thumbtouch_new_page_2buff(hWnd);
		sTTStateData.iMoveHeight = 0;
		itmpPos = lCurrentY - sTTStateData.iTotalMoveHeight;
	 	thumbtouch_set_current_pos(hWnd, itmpPos,0);
		if((itmpPos <= 0))
		{
			SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_TOP, 0);   /* ϱ߽ 2010-1-20*/
		}
		else if(itmpPos >= sTTStateData.iViewHight)
		{
			SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_BOTTOM, 0);
		}
		thumbtouch_init();
		sTTStateData.bGetBuffer = TRUE;
		SendMessage(GetParent(hWnd), MSG_2D_THUMBTOUCH_FINISH, 0, 0);
		SendMessage(hWnd, MSG_2D_THUMBTOUCH_FINISH, 0, 0);
    }
    thumbtouch_stop_inertia(hWnd);
}

/**
 * ƣ thumbtouch_draw_full_screen
 *  ֻȫĻ
 * ˵ (IN) drawModeģʽֵֻ
 *                           ֱӻģʽDIRECT_DRAW_MODEֵ1 
 *                           ӽӻģʽINDIRECT_DRAW_MODEֵ2 
 *                           drawModeֵúֱreturn
 *   ֵ 
 * ˵ ÷ǣthumbtouch_draw_full_screen(DIRECT_DRAW_MODE);thumbtouch_draw_full_screen(INDIRECT_DRAW_MODE);
 */
static ZVOID thumbtouch_draw_full_screen(ZSINT32 drawMode)
{
    RECT wndRect = {0};
    wndRect.right = SCREEN_WIDTH;
    wndRect.bottom = SCREEN_HEIGHT;

    if(DIRECT_DRAW_MODE == drawMode)
    {
        SDev_LcdDirectRefresh(&wndRect);
    }
    else if(INDIRECT_DRAW_MODE == drawMode)
    {
        SDev_UpdateSpecifiedRect(wndRect);
    }
    else
    {
        return;
    }
}


/**
 * ƣ thumbtouch_check_rebound_onlbuttonup
 *  upϢʱǷ񻬳߽
 * ˵ (IN) hWndھ
 
 *   ֵ Ҫ1.򷵻0
 * ˵ 
 */ 
static ZVOID thumbtouch_check_rebound_onlbuttonup(HWND hWnd)
{
	ZSINT32 iCurrentPos = 0xffffffff;
	iCurrentPos = thumbtouch_get_current_pos(hWnd);
	if(iCurrentPos >=0 && iCurrentPos <= sTTStateData.iViewHight)
		sTTStateData.bBeginRebound = FALSE;
	else
	{
		sTTStateData.bBeginRebound = TRUE;
		if( iCurrentPos<=0 )
		{
			sTTStateData.iTotalMoveHeight = -iCurrentPos;
		}
		else if(iCurrentPos >= sTTStateData.iViewHight)
		{
			sTTStateData.iTotalMoveHeight = sTTStateData.iViewHight - iCurrentPos;
		}	
	}
}

/**
 * ƣ thumbtouch_handle_lbuttonup
 *  ͷϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:w
 *            (IN) lParam:L
 *   ֵ Ҫ1.򷵻0
 * ˵ ԻƷʽ
 */ 
static ZSINT32 thumbtouch_handle_lbuttonup(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam)
{   
	ZSINT32 y = HISWORD(lParam);
	ZSINT32 iDis = 0;
	if((y - sTTStateData.pFirstPos.y) == 0)	
	{
		sTTStateData.iDirect2D = 0;
	}
	else
	{
		if(sTTStateData.iMoveHeight > 0) 
		{
			sTTStateData.iDirect2D = DIRECT_DOWN_2D;
		}
		else if(sTTStateData.iMoveHeight < 0)
		{
			sTTStateData.iDirect2D = DIRECT_UP_2D;
		}
	}
	thumbtouch_check_rebound_onlbuttonup(hWnd);	
	iDis = (THUMBTOUCH_POS_DELTA) * (y-sTTStateData.pFirstPos.y);
	if(iDis<0)
		iDis = -iDis;
	sTTStateData.pFirstPos.x = 0;
	sTTStateData.pFirstPos.y = 0;
	sTTStateData.iFirstMoment = 0;
	if(sTTStateData.hCurrent2DWin == hWnd)
    {
	    if(sTTStateData.bScrolledPrepare && sTTStateData.bBeginRebound)
        {
            SetTimer(hWnd,TIME_FOR_2D,TIME_INTERVAL);
		    sTTStateData.bScrolledPrepare = FALSE;
			return 0;
	    }
	    else if(sTTStateData.bScrolledPrepare)
	    {   
            sTTStateData.iSpeed = thumbtouch_absolute_value((ZSINT32)sTTStateData.iSpeed); 
            if(sTTStateData.iSpeed > 0)
            {   
                sTTStateData.iNowTimeVal = GetTickCount();
				if(0 !=sTTStateData.iNowTimeVal - sTTStateData.iOldTimeVal)
				{	 
					sTTStateData.iSpeed = sTTStateData.iSpeed/(sTTStateData.iNowTimeVal - sTTStateData.iOldTimeVal);
				}
				/*Ի˴ûйspeed*/
				sTTStateData.iCacheDistance = iDis*THUMBTOUCH_FREE_RUN_SENSITIVITY;
				if(sTTStateData.iSpeed <= THUMBTOUCH_SPEED_THRESHOLD)
                {    
					sTTStateData.iCacheDistance= 0;
                }
                sTTStateData.iOldTimeVal = sTTStateData.iNowTimeVal;                
                SetTimer(hWnd,TIME_FOR_2D,TIME_INTERVAL);
                sTTStateData.bInertiaFlag = TRUE;
                sTTStateData.bScrolledPrepare = FALSE;
                return 0;  
            }

			if(sTTStateData.bInertiaFlag)
			{
				return 0;
			}
	    }
    }
    return 1;
}

/**
 * ƣ thumbtouch_set_buffer
 *  õǰbuff
 * ˵ (IN) iTotalHeight ǰƶľ
 *   ֵ ڼضҳʱƴӵĸ߶
 * ˵ 
 */ 
static ZSINT32 thumbtouch_set_buffer(ZSINT32 iTotalHeight)
{
	ZSINT32 iMergeDistance = 0;
	ZSINT32 itmp = 0;
	if(p2DPreBuffer == NULL)
		return -1;
	if(sTTStateData.iMoveHeight > 0)	 /* ָ» */
{
	    itmp = iTotalHeight;
		if(itmp>0 && itmp <= sTTStateData.iClientHight)
	{
	 	    iMergeDistance = iTotalHeight;
			s_EndBuffer = p2DPreBuffer+(g_ThumbtouchInertiaPage-1)*LENGHTPHYGCBUFF; /*ZCORE V2.5.0B01*/
	    	s_StartBuffer = p2DStartBuffer;
	}
	    else if(itmp > sTTStateData.iClientHight && itmp <= (2*sTTStateData.iClientHight))
	{
	 	    iMergeDistance = iTotalHeight -  sTTStateData.iClientHight;
	 		s_EndBuffer = p2DPreBuffer+LENGHTPHYGCBUFF;
	    	s_StartBuffer = p2DPreBuffer+2*LENGHTPHYGCBUFF;
	}
	    else if(itmp > (2*sTTStateData.iClientHight) && itmp <= (3*sTTStateData.iClientHight))
	    {
	 	    iMergeDistance = iTotalHeight -  2*sTTStateData.iClientHight;
			s_EndBuffer = p2DPreBuffer;
			s_StartBuffer = p2DPreBuffer+LENGHTPHYGCBUFF;
	    }
    }
    else if (sTTStateData.iMoveHeight < 0)	/* ָϻ */
    {   
	    itmp = GET_OPPOSITION_NUMBER(iTotalHeight);
	    if(itmp>0 && itmp <= sTTStateData.iClientHight)
	    {
	    	iMergeDistance = iTotalHeight;
	    	s_EndBuffer = p2DEndBuffer;
	    	s_StartBuffer = p2DStartBuffer;
	    }
	    else if(itmp > sTTStateData.iClientHight && itmp <= (2*sTTStateData.iClientHight))
	    {
	 	    iMergeDistance = iTotalHeight +  sTTStateData.iClientHight;
			s_EndBuffer = p2DEndBuffer+LENGHTPHYGCBUFF;
	    	s_StartBuffer = p2DEndBuffer;
	    }
	    else if(itmp > (2*sTTStateData.iClientHight) && itmp <= (3*sTTStateData.iClientHight))
	    {
	 	    iMergeDistance = iTotalHeight +  2*sTTStateData.iClientHight;
			s_EndBuffer = p2DEndBuffer+2*LENGHTPHYGCBUFF;
			s_StartBuffer = p2DEndBuffer+LENGHTPHYGCBUFF;
		}
    }	 
	return iMergeDistance;
}

/**
 * ƣ thumbtouch_check_move_onlbuttonup
 *  ʱǷл
 * ˵ (IN) hWndھ
 *   ֵupʱƶ򷵻TRUE, 򷵻FALSE
 * ˵ 
 */ 
static ZBOOL thumbtouch_check_move_onlbuttonup(HWND hWnd)
{   
	ZSINT32 iCurrentPos = thumbtouch_get_current_pos(hWnd); 
	if(thumbtouch_absolute_value(sTTStateData.iTotalMoveHeight)< MOUSE_MOVE_THRESHOLD)
	{
		if (iCurrentPos == 0)
		{
			SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_TOP, 0); 
			thumbtouch_set_current_pos(hWnd, iCurrentPos,0);
		}
		else if(iCurrentPos == sTTStateData.iViewHight)
		{
			SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_BOTTOM, 0);
			thumbtouch_set_current_pos(hWnd, iCurrentPos,0);
		}
		thumbtouch_init();
		sTTStateData.bGetBuffer = TRUE;
		if(GetParent(hWnd))
		{
			 SendNotifyMessage(GetParent(hWnd), MSG_2D_THUMBTOUCH_FINISH, 0, 0);
		}
		SendMessage(hWnd, MSG_2D_THUMBTOUCH_FINISH, 0, 0);
		return FALSE;
	}
	return TRUE;
}

/**
 * ƣ thumbtouch_check_inertia_onlbuttonup
 *  ͷϢʱǷҪƶ
 * ˵ (IN) hWndھ
 *   ֵupʱҪƶ򷵻TRUE, 򷵻FALSE
 * ˵ 
 */ 
static ZBOOL thumbtouch_check_inertia_onlbuttonup(HWND hWnd)
{
	ZSINT32 iCurrentPos = -1;
	ZSINT32 itmpCurrentP = -1;
	ZSINT32 iheight = 0;
	RECT rect = {0};

	GetClientRect(hWnd, &rect);
	thumbtouch_get_effect_rect(hWnd, &rect);
	iheight = RECTH(rect);
	iCurrentPos = thumbtouch_get_current_pos(hWnd); 
	itmpCurrentP = iCurrentPos -sTTStateData.iTotalMoveHeight;
	sTTStateData.iSpeed = thumbtouch_absolute_value((ZSINT32)sTTStateData.iSpeed); 
	if(sTTStateData.iSpeed > TT_INERTIA_SPEED_THRESHOLD)
	{	
		if(itmpCurrentP >= 0 && itmpCurrentP<= sTTStateData.iViewHight)
		{
			ZSINT32 iRestDis = 0;
			if(sTTStateData.iTotalMoveHeight < 0) /* */
			{
				if(iCurrentPos + iheight >= sTTStateData.iViewHight)
				{
					iheight = sTTStateData.iViewHight - iCurrentPos;
					SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_BOTTOM, 0);    /* ±߽ 2010-1-20*/
				}
				iRestDis = iheight +  sTTStateData.iTotalMoveHeight;
				sTTStateData.iTotalMoveHeight -= iRestDis;
				while(iRestDis > 0)
				{
					iRestDis = thumbtouch_calc_pos_for_slowdown(iRestDis,THUMBTOUCH_SLOWDOWN_RATE);
					itmpCurrentP = iCurrentPos - (sTTStateData.iTotalMoveHeight + iRestDis);
					if(itmpCurrentP > sTTStateData.iViewHight ) /*±߽ */
					{
						break;
					}
					if (NULL != s_EndBuffer)
					{
						thumbtouch_merge_pic(s_EndBuffer, p2DStartBuffer, hWnd, sTTStateData.iTotalMoveHeight + iRestDis,0);
					}
					zcore_thread_sleep(20);
				}
			}
			else if(sTTStateData.iTotalMoveHeight > 0)
			{
				if(iCurrentPos <= iheight)	  /* ϱ߽ */
				{
					iheight = iCurrentPos;
					SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_TOP, 0);   /* ϱ߽ 2010-1-20*/
				}
				iRestDis = iheight -  sTTStateData.iTotalMoveHeight;
				sTTStateData.iTotalMoveHeight += iRestDis;
				while(iRestDis > 0)
				{
					iRestDis = thumbtouch_calc_pos_for_slowdown(iRestDis,THUMBTOUCH_SLOWDOWN_RATE);
					itmpCurrentP = iCurrentPos - (sTTStateData.iTotalMoveHeight - iRestDis);
					/*ҳֻһĻ*/
					if(itmpCurrentP < 0)	/*ϱ߽ */
					{
						break;
					}
					if (NULL != s_EndBuffer)
					{
						thumbtouch_merge_pic(s_EndBuffer, p2DStartBuffer, hWnd, sTTStateData.iTotalMoveHeight - iRestDis,0);
					}
					zcore_thread_sleep(20);
				}
			}
			thumbtouch_set_current_pos(hWnd, iCurrentPos -sTTStateData.iTotalMoveHeight,0);
			thumbtouch_init();	
			SendNotifyMessage(GetParent(hWnd), MSG_2D_THUMBTOUCH_FINISH, 0, 0);
			SendMessage(hWnd, MSG_2D_THUMBTOUCH_FINISH, 0, 0);
			return TRUE;  
		}	
	}
	return FALSE;
}

/**
 * ƣ thumbtouch_adjust_ex_on_finish
 *  ʱĵ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ ֹͣʱλ
 * ˵ ƴͼʽרá
 */ 
static ZSINT32 thumbtouch_adjust_ex_on_finish(HWND hWnd)
{ 
	ZSINT32   iTempMoveHeight = 0;
	ZSINT32   iSize = 0;
	ZSINT32   bDownMove = 0;//0ϲ£-1ϣ1
	ZSINT32   iFrameCount = 0;
	ZSINT32   iHeightItem = 0;
	ZSINT32   iTotalCount = THUMBTOUCH_FRAME_TOTALCOUNT;
	ZSINT32 itmpPos = 0;
	ZSINT32 iCurrentPos = thumbtouch_get_current_pos(hWnd);

	iHeightItem = sTTStateData.iItemHeight;
	if(iHeightItem > 0)
	{
		if((sTTStateData.iTotalMoveHeight%iHeightItem) == 0)
		{
			itmpPos = iCurrentPos - sTTStateData.iTotalMoveHeight;
			return itmpPos;
		}
		iSize = sTTStateData.iTotalMoveHeight%iHeightItem;
		if(sTTStateData.iTotalMoveHeight > 0)
		{	
			bDownMove = 1;
			iSize = iHeightItem - iSize;
			itmpPos = iCurrentPos - (sTTStateData.iTotalMoveHeight/iHeightItem + 1) * iHeightItem;
		}	
		else if(sTTStateData.iTotalMoveHeight < 0)
		{
			bDownMove = -1;
			iSize = iHeightItem + iSize;
			itmpPos = iCurrentPos - (sTTStateData.iTotalMoveHeight/iHeightItem - 1) * iHeightItem;
		}
		else
		{
			bDownMove = 0;
		}
	}	
	else
	{
		itmpPos = iCurrentPos -sTTStateData.iTotalMoveHeight;
	}	
	
	if((itmpPos >= 0) && (itmpPos <= sTTStateData.iViewHight)) /* ߽磬иЧ*/
	{
		if (itmpPos == 0)	
		{
			SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_TOP, 0); 
		}
		else if(itmpPos == sTTStateData.iViewHight)
		{
			SendNotifyMessage(GetParent(hWnd), MSG_2D_BOUNDARY,  THUMB_BOUNDARY_BOTTOM, 0);
		}
		iTempMoveHeight = thumbtouch_set_buffer(sTTStateData.iTotalMoveHeight);
		if (iTempMoveHeight != 0)
		{
			ZSINT32 iOffset = 0;
			ZSINT32 iValueRes = 0;

			iValueRes = iSize%iTotalCount;
			iOffset   = iSize/iTotalCount;
			for(iFrameCount = 0; iFrameCount < iTotalCount; iFrameCount ++)
			{
				if((iFrameCount == 0) && (iValueRes != 0))
				{
					iSize = iOffset + iValueRes;
				}
				else
				{
					iSize = iOffset;
				}
				if(bDownMove > 0)
				{
					iTempMoveHeight = iTempMoveHeight + iSize;
				}
				else if (bDownMove < 0)
				{
					iTempMoveHeight = iTempMoveHeight - iSize;
				}
				if (NULL != s_EndBuffer)
				{
					thumbtouch_merge_pic(s_EndBuffer, s_StartBuffer, hWnd, iTempMoveHeight, -1);
				}		
				if(iFrameCount == iTotalCount - 1)
					zcore_thread_sleep(40);
				else
					zcore_thread_sleep(20);
			}
		}
	}
	return itmpPos;
}

/**
 * ƣ thumbtouch_adjust_ex2
 *  ʱĵ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ 0ʾ1ʾ
 * ˵3 ҳ ƴͼʽרá
 */ 
static ZSINT32 thumbtouch_adjust_ex2(HWND hWnd)
{ 
	ZSINT32   iPace = 0;
	ZSINT32   uHeightItem = 0;
	ZSINT32   iTotalCount = 6;//THUMBTOUCH_FRAME_TOTALCOUNT; /*3Ϊ֡*/
	ZSINT32   iMergeDistance = 0;
	ZSINT32   iFrameCount = 0;
	
	uHeightItem = sTTStateData.iItemHeight;
	if((uHeightItem > 0) && (sTTStateData.iCountFrame < iTotalCount))
	{							
		ZSINT32 iRes = sTTStateData.iTotalMoveHeight%uHeightItem;
		
		if(iRes == 0)
		{
			return 1;
		}
		if(sTTStateData.iTotalMoveHeight > 0)
		{
			iRes = uHeightItem - iRes;
			iPace = iRes/iTotalCount; 
		}
		if(sTTStateData.iTotalMoveHeight < 0)
		{
			iRes = (-uHeightItem) - iRes;
			iPace = iRes/iTotalCount;
		}

		for(iFrameCount = 0; iFrameCount < iTotalCount; iFrameCount++)
		{
			if(iFrameCount == (iTotalCount-1))
			{  
				iPace += (iRes%iTotalCount);
			}
			sTTStateData.iTotalMoveHeight += iPace;
			sTTStateData.iMoveHeight += iPace;
			iMergeDistance = thumbtouch_set_buffer(sTTStateData.iMoveHeight);		
			thumbtouch_merge_pic(s_EndBuffer, s_StartBuffer, hWnd, iMergeDistance,0); 
				zcore_thread_sleep(30);
		}	
		sTTStateData.iMoveHeight = iRes;
		thumbtouch_new_page_2buff(hWnd);
	}		
	return 1;
}

/**
 * ƣ thumbtouch_format_cache_distance
 *   Ҫܾ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ 
 * ˵ 
 */ 
ZVOID thumbtouch_format_cache_distance(HWND hWnd)
{
	ZSINT32 iCurrentPos = thumbtouch_get_current_pos(hWnd);
	ZSINT32 itmpCurrentP = -1;
	ZSINT32 iMaxDis = -1;

	itmpCurrentP = iCurrentPos -sTTStateData.iTotalMoveHeight;
	if(sTTStateData.iDirect2D == DIRECT_DOWN_2D)
	{
		iMaxDis = itmpCurrentP;
	}
	else if(sTTStateData.iDirect2D == DIRECT_UP_2D)
	{
		iMaxDis	= sTTStateData.iViewHight - itmpCurrentP;
	}
	
	if(sTTStateData.iCacheDistance > (sTTStateData.iClientHight * 3))
	{
		sTTStateData.iCacheDistance = sTTStateData.iClientHight * 3;
	}
	
	if(sTTStateData.iTotalMoveHeight <= 0)
	{
		sTTStateData.iCacheDistance += sTTStateData.iTotalMoveHeight;
	}
	else
	{
		sTTStateData.iCacheDistance -= sTTStateData.iTotalMoveHeight;
	}
	sTTStateData.iCacheDistance = sTTStateData.iCacheDistance < 0 ? 0:sTTStateData.iCacheDistance;
	sTTStateData.iCacheDistance = sTTStateData.iCacheDistance > iMaxDis ? iMaxDis:sTTStateData.iCacheDistance;	
}

/**
 * ƣ thumbtouch_handle_lbuttonup_ex
 *  ͷϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ 
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_lbuttonup_singlePic(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam)
{   
	ZSINT32 iCurrentPos = thumbtouch_get_current_pos(hWnd);
	ZSINT32 itmpPos = 0;
	ZSINT32 iheight = 0;
	RECT rect = {0};
	PCONTROL pCtrl = (PCONTROL)hWnd;
	
	GetClientRect(hWnd, &rect);
	thumbtouch_get_effect_rect(hWnd, &rect);
	iheight = RECTH(rect);
	itmpPos = iCurrentPos -sTTStateData.iTotalMoveHeight;
	if(sTTStateData.bScrolledPrepare)
	{
		if(!thumbtouch_check_move_onlbuttonup(hWnd))
		{
			return 1;
		}
		sTTStateData.bGetBuffer = FALSE;
		ReadyForThumbTouchExec(hWnd, 0);	
		if(thumbtouch_check_inertia_onlbuttonup(hWnd))
		{
			return 0;
		}
		
		if(!(pCtrl->dwExStyle&WS_2D_NOT_ADJUST))
		{
			itmpPos = thumbtouch_adjust_ex_on_finish(hWnd);
		}
		
		if(itmpPos < 0)
			itmpPos = 0;
		else if(itmpPos > sTTStateData.iViewHight)
			itmpPos = sTTStateData.iViewHight;
		thumbtouch_check_rebound(hWnd);
		thumbtouch_set_current_pos(hWnd, itmpPos,0);
		thumbtouch_init();
		SendMessage(GetParent(hWnd), MSG_2D_THUMBTOUCH_FINISH, 0, 0);
		SendMessage(hWnd, MSG_2D_THUMBTOUCH_FINISH, 0, 0);
		return 0;
	}
    return 1;
}

/**
 * ƣ thumbtouch_handle_lbuttonup_for_multipage
 *  ͷϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ 
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_lbuttonup_for_multipage(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam)
{
	ZSINT32 y = HISWORD(lParam);
	ZSINT32 itmpPos = 0;
	ZSINT32 iCurrentPos = thumbtouch_get_current_pos(hWnd);
	
	itmpPos = iCurrentPos -sTTStateData.iTotalMoveHeight;
	if(itmpPos < 0)
		itmpPos = 0;
	else if(itmpPos > sTTStateData.iViewHight)
		itmpPos = sTTStateData.iViewHight;
	if((y - sTTStateData.pFirstPos.y) == 0) 
	{
		sTTStateData.iDirect2D = 0;
	}
	else
	{
		if(sTTStateData.iTotalMoveHeight > 0)
		{
			sTTStateData.iDirect2D = DIRECT_DOWN_2D;
		}
		else if(sTTStateData.iTotalMoveHeight < 0)
		{
			sTTStateData.iDirect2D = DIRECT_UP_2D;
		}
	}
	sTTStateData.pFirstPos.x = 0;
	sTTStateData.pFirstPos.y = 0;
	sTTStateData.iFirstMoment = 0;
	if(sTTStateData.hCurrent2DWin == hWnd)
	{
		if(sTTStateData.bScrolledPrepare)
		{
			if(!(((PCONTROL)hWnd)->dwExStyle & WS_2D_FORBID_REBOUND)) /*  ֹյ */
			{
			if(thumbtouch_check_rebound(hWnd))
			{
				ReadyForThumbTouchExec(hWnd, 0);
				thumbtouch_set_current_pos(hWnd, itmpPos,0);
				thumbtouch_init();
				SendMessage(GetParent(hWnd), MSG_2D_THUMBTOUCH_FINISH, 0, 0);
				SendMessage(hWnd, MSG_2D_THUMBTOUCH_FINISH, 0, 0);
				sTTStateData.bBeginRebound = FALSE;
				return 0;
			}			
			}
			sTTStateData.iSpeed = thumbtouch_absolute_value((ZSINT32)sTTStateData.iSpeed); 
			if(sTTStateData.iSpeed > 0)
			{	
				sTTStateData.iNowTimeVal = GetTickCount();
				if(0 !=sTTStateData.iNowTimeVal - sTTStateData.iOldTimeVal)
				{	 
					sTTStateData.iSpeed = sTTStateData.iSpeed/(sTTStateData.iNowTimeVal - sTTStateData.iOldTimeVal);
				}
				sTTStateData.iOldTimeVal = sTTStateData.iNowTimeVal;				
				sTTStateData.iCacheDistance =(ZSINT32)3*sTTStateData.iSpeed;
				thumbtouch_format_cache_distance(hWnd);
				SetTimer(hWnd,TIME_FOR_2D,TIME_INTERVAL);
				sTTStateData.bInertiaFlag = TRUE;
				sTTStateData.bScrolledPrepare = FALSE;
				sTTStateData.iMoveHeight = sTTStateData.iTotalMoveHeight;
				return 0;  
			}
			/*е   δݵ׼*/
			thumbtouch_init();
			sTTStateData.bGetBuffer = TRUE;
		}
	}
	return 1;
}

/**
 * ƣ thumbtouch_handle_lbuttondown
 *  갴ѹϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ Ҫ1.򷵻0
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_lbuttondown(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam)
{
    ZSINT32 y = HISWORD(lParam);
	ZSINT32 x = LOSWORD(lParam);
    RECT lRect = {0};

	sTTStateData.iViewHight = thumbtouch_get_view_height(hWnd);
	sTTStateData.iItemHeight = thumbtouch_get_item_height(hWnd);
    sTTStateData.bMouseMoveCrossBorder = FALSE; 
	sTTStateData.pFirstPos.x = x;
	sTTStateData.pFirstPos.y = y;
	sTTStateData.iFirstMoment = tp_os_current_tick_get();
    GetClientRect(hWnd, &lRect); 
    thumbtouch_get_effect_rect(hWnd, &lRect);
    if(!PtInRect(&lRect,x,y))
    {
    	sTTStateData.bScrolledPrepare = FALSE; 
        return 1;
    }
	if(sTTStateData.hCurrent2DWin == hWnd)
	{
		if(sTTStateData.bBeginRebound) 
		{
			SetTimer(hWnd,TIME_FOR_2D,TIME_INTERVAL);
			sTTStateData.bScrolledPrepare = FALSE;
        	return 0;
		}
		if(sTTStateData.bInertiaFlag)
		{
			sTTStateData.iCacheDistance = 0;
			/*У·mmi*/
			sTTStateData.bScrolledPrepare = TRUE;
		    sTTStateData.iOldTimeVal = sTTStateData.iNowTimeVal = GetTickCount();
		    sTTStateData.iSpeed = 0;
			sTTStateData.iOldY = y;
			sTTStateData.iMoveNum = 0;
			sTTStateData.hCurrent2DWin = hWnd;
			s_thumbtouch_current_time = tp_os_current_tick_get();
			return 0;
		}
	}
	sTTStateData.bScrolledPrepare = TRUE;
    sTTStateData.iOldTimeVal = sTTStateData.iNowTimeVal = GetTickCount();
    sTTStateData.iSpeed = 0;
	sTTStateData.iOldY = y;
	sTTStateData.iMoveNum = 0;
	sTTStateData.hCurrent2DWin = hWnd;
	s_thumbtouch_current_time = tp_os_current_tick_get();
    return 1;  
}

/**
 * ƣ thumbtouch_handle_lbuttondown_pic
 *  갴ѹϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ 
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_lbuttondown_pic(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam, PRECT pTouchRect)
{
    ZSINT32 y = HISWORD(lParam);
	ZSINT32 x = LOSWORD(lParam);
    RECT lRect = {0};
    ZSINT32 lCurrentY = thumbtouch_get_current_pos(hWnd);
    GetClientRect(hWnd, &lRect); 
    thumbtouch_get_effect_rect(hWnd, &lRect);
	if(!Rect_IsEmpty(pTouchRect))
		lRect = *pTouchRect;
    if(!PtInRect(&lRect, x, y))
    {
		sTTStateData.bScrolledPrepare = FALSE;  
        return 1;
    }
	sTTStateData.iViewHight = thumbtouch_get_view_height(hWnd);
	sTTStateData.iItemHeight = thumbtouch_get_item_height(hWnd); 
	sTTStateData.iClientHight = RECTH(lRect);
	if(sTTStateData.bGetBuffer == FALSE)
	{
		thumbtouch_init();
        return 1;
	}
	if(sTTStateData.hCurrent2DWin == hWnd)
	{
		if(sTTStateData.bBeginRebound)  /*ʱʼ˷Чʼȥ*/
		{
			sTTStateData.bScrolledPrepare = FALSE;
        	return 0;
		}
		/*ҳ²Ż*/
		if(sTTStateData.bInertiaFlag)
		{
			thumbtouch_stop_inertia(hWnd); 
			thumbtouch_new_page_2buff(hWnd);
			thumbtouch_set_current_pos(hWnd, lCurrentY - sTTStateData.iTotalMoveHeight,0);
			sTTStateData.iTotalMoveHeight = 0;
			sTTStateData.iMoveHeight = 0;
			/*ʱϢ,Ϊҳʽ׼ҳҪأupϢдԻ*/
			sTTStateData.pFirstPos.x = x;
			sTTStateData.pFirstPos.y = y;
			sTTStateData.iFirstMoment = tp_os_current_tick_get();
		  	sTTStateData.bScrolledPrepare = TRUE;
		    sTTStateData.iSpeed = 0;
			sTTStateData.iOldTimeVal = sTTStateData.iNowTimeVal = GetTickCount();
			sTTStateData.iOldY = y;
			sTTStateData.iMoveNum = 0;	
		    sTTStateData.hCurrent2DWin = hWnd;	
			return 0;
		}
	}
	sTTStateData.pFirstPos.x = x;
	sTTStateData.pFirstPos.y = y;
	sTTStateData.iFirstMoment = tp_os_current_tick_get();
  	sTTStateData.bScrolledPrepare = TRUE;
    sTTStateData.iSpeed = 0;
	sTTStateData.iOldTimeVal = sTTStateData.iNowTimeVal = GetTickCount();
	sTTStateData.iOldY = y;
	sTTStateData.iMoveNum = 0;	
    sTTStateData.hCurrent2DWin = hWnd;	
	SendMessage(hWnd, MSG_2D_THUMBTOUCH_REPAINT_CURRBUFF,0,0);
    return 1;
}

/**
 * ƣ thumbtouch_set_movespeed
 *  㿪ʼmoveĳٶ
 * ˵ (IN) 
 *   ֵ 
 * ˵ 
 */ 
static ZVOID thumbtouch_set_movespeed()
{
    sTTStateData.iNowTimeVal = GetTickCount();
    if(sTTStateData.iNowTimeVal != sTTStateData.iOldTimeVal)
    {
        sTTStateData.iSpeed = sTTStateData.iMoveHeight * TT_INERTIA_SPEED / (sTTStateData.iNowTimeVal - sTTStateData.iOldTimeVal);
    }
    else
    {   
        sTTStateData.iSpeed = sTTStateData.iMoveHeight * TT_INERTIA_SPEED;
    }
    sTTStateData.iOldTimeVal = sTTStateData.iNowTimeVal;
}

/**
 * ƣ thumbtouch_check_firstmove
 *  Ƿǳλ
 * ˵(IN) hWndھ
 *   ֵ 
 * ˵ 
 */ 
static ZVOID thumbtouch_check_firstmove(HWND hWnd)
{
	PCONTROL pControl = (PCONTROL)hWnd;
	
    if(0 == sTTStateData.iMoveNum)
    {
    	if(!(pControl->dwExStyle & WS_2D_FOR_HIGHTLIGHT))
        {
        	SendMessage(hWnd, MSG_2D_UNSET_CURSEL, 0xffffffff, 0);
    	}
		if(!(pControl->dwExStyle & WS_2D_FOR_WIDGET))
        thumbtouch_paint_now(hWnd);
		SendNotifyMessage(GetParent(hWnd), MSG_2D_BEGIN_MOVE, 0, 0);
		SendNotifyMessage(hWnd, MSG_2D_BEGIN_MOVE, 0, 0);
		sTTStateData.bThumbTouchState = TRUE;	
		sTTStateData.iCurrentOffsetY = thumbtouch_get_current_pos(hWnd);
		sTTStateData.iTotalMoveHeight = 0;
    }
}

/**
 * ƣ thumbtouch_check_real_move
 *  Ƿʼƶ
 * ˵ (IN) 
 *   ֵ ʼƶ򷵻1򷵻0
 * ˵ 
 */ 
static ZSINT32 thumbtouch_check_real_move(ZVOID)
{
	if(0 == sTTStateData.iMoveNum && thumbtouch_absolute_value(sTTStateData.iMoveHeight) < 9)  /* */
	{
		s_thumbtouch_current_time = tp_os_current_tick_get();
        return 0;
	}
	return 1;
}

/**
 * ƣ thumbtouch_check_reach_bound
 *  Ƿ񵽴߽
 * ˵ (IN) hWndھ
 *            (IN) lY: ͼĵһеλ
 *            (IN) y:  ǰλ
 *   ֵ߽򷵻TRUE,򷵻FALSE
 * ˵ 
 */ 
static ZBOOL thumbtouch_check_reach_bound(HWND hWnd, ZSINT32 lY, ZSINT32 y)
{   
    ZSINT32 iViewHeight = sTTStateData.iViewHight;
 
    iViewHeight = iViewHeight < 0 ? 0 : iViewHeight;
    if (sTTStateData.iMoveHeight < 0 && lY >= iViewHeight
	 || sTTStateData.iMoveHeight > 0 && lY < 1) 
	{    
        sTTStateData.bBeginRebound = TRUE;
        sTTStateData.iMoveHeight >= 0 ? (sTTStateData.iDirect2D = DIRECT_DOWN_2D) : (sTTStateData.iDirect2D = DIRECT_UP_2D);
        sTTStateData.iMoveHeight = 0;
        sTTStateData.iOldY = y;
        return TRUE;
	} 
	return FALSE;
}

/**
 * ƣ thumbtouch_check_end_rebound
 *  Ƿý
 * ˵ (IN) yy
 *   ֵ Ҫ򷵻TRUE,򷵻FALSE
 * ˵ 
 */ 
static ZBOOL thumbtouch_check_end_rebound(ZSINT32 y)
{
    if(sTTStateData.iDirect2D == DIRECT_UP_2D && sTTStateData.iTotalMoveHeight > 0 
    || sTTStateData.iDirect2D == DIRECT_DOWN_2D && sTTStateData.iTotalMoveHeight < 0)
    {   
        sTTStateData.bBeginRebound = FALSE;
        sTTStateData.iOldY = y;   /*ʱҪ¼yֵΪ´ηЧ׼*/
        sTTStateData.iDirect2D = 0; 
        sTTStateData.iTotalMoveHeight = 0;  
   	 	return TRUE;
    }
    return FALSE;
}

/**
 * ƣ thumbtouch_check_if_moveout
 * ǷƳ֮
 * ˵ (IN) hWndھ
 *            (IN) x: x
 *            (IN) y:y
 *   ֵ Ƴ򷵻TRUE򷵻FALSE
 * ˵ 
 */ 
static ZBOOL thumbtouch_check_if_moveout(HWND hWnd,ZSINT32 x,ZSINT32 y)
{
	RECT lRect = {0, 0, 0, 0};
	
	GetClientRect(hWnd, &lRect); 
	thumbtouch_get_effect_rect(hWnd, &lRect);
	if(lRect.right>=SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH)   
    {
 	   lRect.right = SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH;
    }
    
    if(y < lRect.top || y > lRect.bottom || x > lRect.right || x < lRect.left) 
    {
		if(sTTStateData.bScrolledPrepare)
		{
		   sTTStateData.iCacheDistance = 0;
		   SetTimer(hWnd,TIME_FOR_2D,TIME_INTERVAL);
		   sTTStateData.bInertiaFlag = TRUE;
		   sTTStateData.bScrolledPrepare = FALSE;
		}	   
 	    return TRUE;		
    }
	return FALSE;
}

/**
 * ƣ thumbtouch_check_real_move
 *  Ƿʼƶ
 * ˵ (IN) 
 *   ֵ ʼƶ򷵻1򷵻0
 * ˵ 
 */ 
static ZSINT32 thumbtouch_check_Horizon_move(ZSINT32 x,ZSINT32 y)
{
	if(thumbtouch_absolute_value(x - sTTStateData.pFirstPos.x) >= thumbtouch_absolute_value(y - sTTStateData.pFirstPos.y) )  /* */
	{
		s_thumbtouch_current_time = tp_os_current_tick_get();
        return 0;
	}
	
	return 1;
}

/**
 * ƣ thumbtouch_handle_mousemove
 *  ƶϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ Ҫ1.򷵻0
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_mousemove(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect)
{
    ZSINT32 y = HISWORD(lParam);
	ZSINT32 x = LOSWORD(lParam);
    ZSINT32 lY = 0;
	ZSINT32 flag = -1;
    ZSINT32 iClientHight = 0;      
    RECT lRect = {0, 0, 0, 0};
    PCONTROL pControl = (PCONTROL)hWnd;
	ZSINT32 itime = tp_os_current_tick_get();
	if(!Rect_IsEmpty(pTouchRect))
		flag = MOVE_WITHOUT_SCROLLBAR;
    GetClientRect(hWnd, &lRect); 
    thumbtouch_get_effect_rect(hWnd, &lRect);
	iClientHight = RECTH(lRect);
	/*ƶʱ߽磬Դdistance =0,ڵһʱϢʱ*/
    if(thumbtouch_check_if_moveout(hWnd,x,y))
		return 1;
    if(sTTStateData.bScrolledPrepare && sTTStateData.hCurrent2DWin == hWnd)
    {            
        sTTStateData.iMoveHeight = y - sTTStateData.iOldY; 		
		if(0 == thumbtouch_check_Horizon_move(x,y)) /*ˮƽƶֱӷ*/
			return 1;
        if(0 == thumbtouch_check_real_move()) 
			return 1;  
        thumbtouch_check_firstmove(hWnd);
        sTTStateData.iMoveNum ++;
		lY = thumbtouch_get_current_pos(hWnd);	
		if(!sTTStateData.bBeginRebound) 
			thumbtouch_check_reach_bound(hWnd, lY, y);
		
		/*˵ʼƶС1/3ߵƶ*/
		if( (itime - s_thumbtouch_current_time) < THUMBTOUCH_MOVE_INTERVAL_TIME_THRESHOLD)
		{
			if(thumbtouch_absolute_value(sTTStateData.iMoveHeight) < sTTStateData.iItemHeight/3)  
		{
				s_thumbtouch_current_time = tp_os_current_tick_get();
			return 0;
		}
		}
        thumbtouch_set_movespeed();
	    if(!sTTStateData.bBeginRebound) 
	    {   
	    	ZSINT32 itmpPos = lY-sTTStateData.iMoveHeight;
		   		if(thumbtouch_check_reach_bound(hWnd, lY, y))  
            	{	        	
                    sTTStateData.bMouseMoveCrossBorder = TRUE;
				if(pControl->dwExStyle & WS_2D_FORBID_REBOUND) 
				{
					if(itmpPos<0)
						itmpPos = 0;
					if(itmpPos>sTTStateData.iViewHight)
						itmpPos = sTTStateData.iViewHight;					
	            }
		   	}
			/*ƶʾ,Իƶִòֿ䷶Χ*/
			if(!sTTStateData.bInertiaFlag)
            	thumbtouch_set_current_pos(hWnd, itmpPos,THUMB_PART_ITEM);
			
			s_thumbtouch_current_time = tp_os_current_tick_get();
		    sTTStateData.iOldY = y;
		    return 0;				
	    }
	    else
	    {    
        	if(pControl->dwExStyle & WS_2D_FORBID_REBOUND) 
		 		return 0;
            sTTStateData.iTotalMoveHeight += sTTStateData.iMoveHeight;  
            if(thumbtouch_absolute_value(sTTStateData.iTotalMoveHeight) >= (iClientHight/2))
         	{
         		s_thumbtouch_current_time = tp_os_current_tick_get();
         		sTTStateData.iOldY = y;
         		if(sTTStateData.iTotalMoveHeight < 0)
				{
					sTTStateData.iTotalMoveHeight = -iClientHight/2;
				}
				else
				{
         		sTTStateData.iTotalMoveHeight = iClientHight/2;
				}
				return 0;
         	}
            thumbtouch_set_current_pos(hWnd, lY - sTTStateData.iMoveHeight,THUMB_PART_ITEM); 
			s_thumbtouch_current_time = tp_os_current_tick_get();
            sTTStateData.iOldY = y;
		    return 0;
	    }
    }
    return 1;
}

/**
 * ƣ thumbtouch_check_if_moveout
 * ǷƳ֮
 * ˵ (IN) hWndھ
 *            (IN) x: x
 *            (IN) y:y
 *   ֵ Ƴ򷵻TRUE򷵻FALSE
 * ˵ 
 */ 
static ZBOOL thumbtouch_check_if_moveout_ex(HWND hWnd,WPARAM wParam, LPARAM lParam)
{
	RECT lRect = {0, 0, 0, 0};
	ZSINT32 y = HISWORD(lParam);
    ZSINT32 x = LOSWORD(lParam);
	
	GetClientRect(hWnd, &lRect); 
	thumbtouch_get_effect_rect(hWnd, &lRect);
	if(lRect.right>=SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH)   
    {
 	   lRect.right = SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH;
    }
    if(y < lRect.top || y > lRect.bottom || x > lRect.right || x < lRect.left) 
    {
		if(sTTStateData.bScrolledPrepare)
        {
			thumbtouch_handle_lbuttonup_singlePic(hWnd, 0, wParam, lParam);
        }	   
 	    return TRUE;		
    }
	return FALSE;
}

/**
 * ƣ thumbtouch_check_if_moveout
 * ǷƳ֮
 * ˵ (IN) hWndھ
 *            (IN) x: x
 *            (IN) y:y
 *   ֵ Ƴ򷵻TRUE򷵻FALSE
 * ˵ 
 */ 
static ZBOOL thumbtouch_check_if_moveout_for_mulpic(HWND hWnd,WPARAM wParam, LPARAM lParam)
{
	RECT lRect = {0, 0, 0, 0};
	ZSINT32 y = HISWORD(lParam);
    ZSINT32 x = LOSWORD(lParam);
	
	GetClientRect(hWnd, &lRect); 
	thumbtouch_get_effect_rect(hWnd, &lRect);
	if(lRect.right>=SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH)   
    {
 	   lRect.right = SCREEN_WIDTH-THUMBTOUCH_SCROLLBAR_WIDTH;
    }
    if(y < lRect.top || y > lRect.bottom || x > lRect.right || x < lRect.left) 
    {
		if(sTTStateData.bScrolledPrepare)
        {
			thumbtouch_handle_lbuttonup_for_multipage(hWnd, 0, wParam, lParam);
        }	   
 	    return TRUE;		
    }
	return FALSE;
}

/**
 * ƣ thumbtouch_handle_mousemove_singlePic
 *  ƶϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ Ҫ1.򷵻0
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_mousemove_singlePic(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect)
{
	ZSINT32 x = LOSWORD(lParam);
    ZSINT32 y = HISWORD(lParam);
    ZSINT32 iDiffy = y - sTTStateData.iOldY;
    ZSINT32 iCurrentOffsetY = 0;  
	ZSINT32 iClientHight = 0;  
    ZSINT32 iTmpCurrentP = 0;	
    RECT lRect = {0};

    GetClientRect(hWnd, &lRect); 
    thumbtouch_get_effect_rect(hWnd, &lRect);
	iClientHight = RECTH(lRect);	
    if(thumbtouch_check_if_moveout_ex(hWnd,wParam,lParam))
	{
		return 1;
	}
    if(sTTStateData.bScrolledPrepare && sTTStateData.hCurrent2DWin == hWnd)
    {            
		if(0 == thumbtouch_check_Horizon_move(x,y)) /*ˮƽƶֱӷ*/
		return 1;
		
		sTTStateData.iMoveHeight = iDiffy; 
        if(0 == sTTStateData.iMoveHeight) 
        {
            return 0;
        }
        if(0 == thumbtouch_check_real_move()) 
		{
			return 0;  				
		}
        thumbtouch_check_firstmove(hWnd);
		sTTStateData.iMoveNum++;
        if(thumbtouch_absolute_value(iDiffy) < MOUSE_MOVE_THRESHOLD)
		{
			return 0;
		}
		
		zCore_CleanAllDirtyChild(hWnd);
		thumbtouch_set_movespeed();
		iCurrentOffsetY = sTTStateData.iCurrentOffsetY; //ǰʵʵƫλãϳͼƬıֵ
		if(((PCONTROL)hWnd)->dwExStyle & WS_2D_FORBID_REBOUND) /*  ֹյ */
		{
			if((iCurrentOffsetY -iDiffy-sTTStateData.iTotalMoveHeight) >= sTTStateData.iViewHight
				||(iCurrentOffsetY -iDiffy-sTTStateData.iTotalMoveHeight) <= 0)
			{
			    sTTStateData.iMoveHeight = 0;
				sTTStateData.iOldY = y;
				return 0;
			}
		}
		iTmpCurrentP = iCurrentOffsetY -iDiffy-sTTStateData.iTotalMoveHeight;//Ҫƫֵ
		if( (iTmpCurrentP - sTTStateData.iViewHight) >= (iClientHight/2)
			|| (0 - iTmpCurrentP)>= (iClientHight/2) )
		{
			return 0;//ʱƶ
		}
		
        sTTStateData.iTotalMoveHeight += iDiffy;
		
    	thumbtouch_set_buffer(sTTStateData.iTotalMoveHeight);
		thumbtouch_merge_pic(s_EndBuffer, p2DStartBuffer, hWnd, sTTStateData.iTotalMoveHeight,1);
		SendNotifyMessage(hWnd, MSG_2D_POSITION_CHANGED, iCurrentOffsetY -sTTStateData.iTotalMoveHeight, 0);
		sTTStateData.iOldY = y; 
		return 0;
    }
    return 1;
}
/**
 * ƣ thumbtouch_handle_mousemove_for_mulpic
 *  ƶϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam:
 *            (IN) lParam
 *   ֵ Ҫ1.򷵻0
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_mousemove_for_mulpic(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect)
{
	ZSINT32 x = LOSWORD(lParam);
    ZSINT32 y = HISWORD(lParam);
    ZSINT32 iDiffy = y - sTTStateData.iOldY;
    ZSINT32 iCurrentOffsetY = 0;  
	ZSINT32 iClientHight = 0;  
    ZSINT32 iTmpCurrentP = 0;	
    RECT lRect = {0};
    GetClientRect(hWnd, &lRect); 
    thumbtouch_get_effect_rect(hWnd, &lRect);
	iClientHight = RECTH(lRect);	
    if(thumbtouch_check_if_moveout_for_mulpic(hWnd,wParam,lParam))
	{
		return 1;
	}
    if(sTTStateData.bScrolledPrepare && sTTStateData.hCurrent2DWin == hWnd)
    {            
		if(0 == thumbtouch_check_Horizon_move(x,y)) /*ˮƽƶֱӷ*/
		return 1;
		
		sTTStateData.iMoveHeight = iDiffy; 
        if(0 == sTTStateData.iMoveHeight) 
        {
            return 0;
        }
        if(0 == thumbtouch_check_real_move()) 
		{
			return 0;  				
		}
        thumbtouch_check_firstmove(hWnd);
		sTTStateData.iMoveNum++;
        if(thumbtouch_absolute_value(iDiffy) < MOUSE_MOVE_THRESHOLD)
		{
			return 0;
		}
		thumbtouch_set_movespeed();
		iCurrentOffsetY = sTTStateData.iCurrentOffsetY;
		if(((PCONTROL)hWnd)->dwExStyle & WS_2D_FORBID_REBOUND) /*  ֹյ */
		{
			if((iCurrentOffsetY -iDiffy-sTTStateData.iTotalMoveHeight) >= sTTStateData.iViewHight
				||(iCurrentOffsetY -iDiffy-sTTStateData.iTotalMoveHeight) <= 0)
			{
			    sTTStateData.iMoveHeight = 0;
				sTTStateData.iOldY = y;
				return 0;
			}
		}
		

		iTmpCurrentP = iCurrentOffsetY -iDiffy-sTTStateData.iTotalMoveHeight;
		if( (iTmpCurrentP - sTTStateData.iViewHight) >= (iClientHight/2)
			|| (0 - iTmpCurrentP)>= (iClientHight/2) )
		{
			return 0;
		}
        sTTStateData.iTotalMoveHeight += iDiffy;
    	thumbtouch_set_buffer(sTTStateData.iTotalMoveHeight);
		thumbtouch_merge_pic(s_EndBuffer, p2DStartBuffer, hWnd, sTTStateData.iTotalMoveHeight,1);
        sTTStateData.iOldY = y; 
		return 0;
    }
    return 1;
}

/**
 * ƣ thumbtouch_handle_mousemovein
 *  mousemoveinϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *   ֵ 
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_mousemovein(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam)
{
	HWND tmpWnd = HWND_INVALID;
	HWND ParWnd = GetParent(hWnd);
	ZSINT32 iCurrentY = -1;
    HWND pMainWin = GetMainWindowPtrOfControl(hWnd);

	if(pMainWin!=0 && pMainWin != GetActiveWindow())
	{
		return 0;
	}
	tmpWnd = SendMessage(ParWnd, MSG_2D_GET_CURRENT_CTRL, 0, 0);
	if(tmpWnd == hWnd || !isValidaWin(tmpWnd) || !isValidaWin(tmpWnd))
	{
		iCurrentY = thumbtouch_get_current_pos(hWnd);
		if( iCurrentY<=0 )
		{
			sTTStateData.bBeginRebound = 1;
			sTTStateData.iTotalMoveHeight = -iCurrentY;
		}
		else if(iCurrentY >= sTTStateData.iViewHight)
		{
			sTTStateData.bBeginRebound = 1;
			sTTStateData.iTotalMoveHeight = sTTStateData.iViewHight - iCurrentY;
		}	
		thumbtouch_handle_lbuttonup(hWnd, message, wParam, MAKELONG(0, sTTStateData.iOldY)); 
		return 0;
	}
	return 1;
}

/**
 * ƣ thumbtouch_handle_mousemovein_singlepic
 *  mousemoveinϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *   ֵ 
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_mousemovein_singlepic(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam)
{
	HWND tmpWnd = HWND_INVALID;
	HWND ParWnd = GetParent(hWnd);

	if(ParWnd!=0 && ParWnd != GetActiveWindow())
	{
		return 0;
	}
	tmpWnd = SendMessage(ParWnd, MSG_2D_GET_CURRENT_CTRL, 0, 0);
	if(tmpWnd == hWnd || !isValidaWin(tmpWnd) || !isValidaWin(tmpWnd))
	{
		if(!(((PCONTROL)hWnd)->dwExStyle & WS_2D_FOR_HIGHTLIGHT))
		{
			SendMessage(hWnd, MSG_2D_UNSET_CURSEL, 0xffffffff, 0);
		}
		thumbtouch_handle_lbuttonup_singlePic(hWnd, message, wParam, lParam);
	}
	return 1;
}

/**
 * ƣ thumbtouch_handle_mousemovein_ex2
 *  mousemoveinϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *   ֵ 
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_mousemovein_for_multipage(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam)
{
	HWND tmpWnd = HWND_INVALID;
	HWND ParWnd = GetParent(hWnd);

	if(ParWnd!=0 && ParWnd != GetActiveWindow())
	{
		return 0;
	}
	tmpWnd = SendMessage(ParWnd, MSG_2D_GET_CURRENT_CTRL, 0, 0);
	if(tmpWnd == hWnd || !isValidaWin(tmpWnd) || !isValidaWin(tmpWnd))
	{
		if(!(((PCONTROL)hWnd)->dwExStyle & WS_2D_FOR_HIGHTLIGHT))
		{
			SendMessage(hWnd, MSG_2D_UNSET_CURSEL, 0xffffffff, 0);
		}
		thumbtouch_handle_lbuttonup_for_multipage(hWnd, message, wParam, lParam);
	}
	return 1;
}

/**
 * ƣ thumbtouch_handle_timer
 *  ʱϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *            (IN) pTouchRect:ָ
 *   ֵ 
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_timer(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect)
{
	ZSINT32 flag = -1;
	if(!Rect_IsEmpty(pTouchRect))
    {
		flag = MOVE_WITHOUT_SCROLLBAR;
    }
	if(TIME_FOR_2D == wParam)
	{
	    if(sTTStateData.bBeginRebound &&  sTTStateData.iTotalMoveHeight == 0)
	    {
	         thumbtouch_end_effect(hWnd);
	    }
	    else if(sTTStateData.bBeginRebound)
	    {    
			 thumbtouch_rebound(hWnd,flag);
	    }
	    else if(sTTStateData.bInertiaFlag)
	    {
	         thumbtouch_inertia(hWnd);                         
	    }
	    else
	    {
	    	thumbtouch_end_effect(hWnd); 
	    }
	    return 0;
	}
	else
	{
	    if(sTTStateData.bBeginRebound || sTTStateData.bInertiaFlag)
	    {
	        return 0;
	    }
	}
	return 1;
}

/**
 * ƣ thumbtouch_handle_timer_ex2
 *  ʱϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *            (IN) pTouchRect:ָ
 *   ֵ 
 * ˵ 
 */ 
static ZSINT32 thumbtouch_handle_timer_for_multiPage(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect)
{

	if(TIME_FOR_2D == wParam)
	{
	    if(sTTStateData.bInertiaFlag)
	    {
	         thumbtouch_inertia_for_multiPage(hWnd);                         
	    }
	    else
	    {
	        KillTimer(hWnd,TIME_FOR_2D);
	    }
	    return 0;
	}
	return 1;
}

/**
 * ƣ thumbtouch_proc_for_multipage
 *  2DϢ, һλҳ 
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *            (IN) pTouchRect:ָ
 *   ֵ 
 * ˵ һλҳ 
 */ 
static ZSINT32 thumbtouch_proc_for_multipage (HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam, PRECT pTouchRect)
{  
	PCONTROL pControl = NULL;
    ZSINT32 x = LOSWORD(lParam);        
    ZSINT32 y = HISWORD(lParam);

    pControl = (PCONTROL)hWnd;
    if(!(Is2DThumbTouch(pControl->dwStyle)))
    {
        return THUMBTOUCHGOON;
    }
    switch (message) 
	{
		case MSG_LBUTTONDOWN: // 0x0001
		{
			ZSINT32 iViewH = -1;
			iViewH = thumbtouch_get_content_rate(hWnd);
			if(iViewH < 0)
			{
				sTTStateData.bScrolledPrepare = 0;
				return THUMBTOUCHGOON;
			}
	        if(!thumbtouch_handle_lbuttondown_pic(hWnd, message, wParam, lParam, pTouchRect))
	        {
	        	return THUMBTOUCHSTOP;
	        }
			break; 
		}
		case MSG_2D_THUMBTOUCH_LBUTTONUP:
		case MSG_LBUTTONUP: // 0x0002
		{    	
	        if(!thumbtouch_handle_lbuttonup_for_multipage(hWnd, message, wParam, lParam))
	        {
	        	return THUMBTOUCHSTOP;
	        }
			break; 
		}
		case MSG_MOUSEMOVE: // 0x0004
		{   
			if(!thumbtouch_handle_mousemove_for_mulpic(hWnd, message, wParam, lParam, pTouchRect))
			{
				return THUMBTOUCHSTOP;
			}
			break;
		}
		case MSG_NCMOUSEMOVE:  // 0x000B
	    { 
	        RECT            rectWindow = {0};
    
	        GetWindowRect(hWnd, &rectWindow);
	        if(!PtInRect(&rectWindow,x, y))
	        {
	            thumbtouch_handle_lbuttonup_for_multipage(hWnd, message, wParam, lParam);    
	    	    return THUMBTOUCHSTOP;
	        }
	        break; 
	    }                            
		case MSG_MOUSEMOVEIN: // 0x0050
	    {   
			if(wParam == FALSE)
			{   
				thumbtouch_handle_mousemovein_for_multipage(hWnd, message, wParam, lParam);
			}
	    	return THUMBTOUCHGOON;
		}
		case  MSG_CREATE:
		{
			s_iCountWindowForThumbTouch++;
			thumbtouch_allocatebuffer();
			break;
		}
		case MSG_DESTROY: // 0x0064 
	    {
	        thumbtouch_init();
			s_iCountWindowForThumbTouch--;
			thumbtouch_freebuffer();
	        return THUMBTOUCHGOON;
	    }
		case MSG_TIMER: // 0x0144
		{   
			if(!thumbtouch_handle_timer_for_multiPage(hWnd, message, wParam, lParam,pTouchRect))
			{
				return THUMBTOUCHSTOP;
			}
			break;
		}
		case MSG_2D_STOP_THUMBTOUCH: // 0x1009
	    {
			thumbtouch_init(); 
			thumbtouch_stop_inertia(hWnd);
			SendMessage(GetParent(hWnd), MSG_2D_THUMBTOUCH_FINISH, 0, 0);
			SendMessage(hWnd, MSG_2D_THUMBTOUCH_FINISH, 0, 0);
			
	        return THUMBTOUCHGOON;
	    }
		case MSG_2D_END_PAINT:
		{
			sTTStateData.bGetBuffer = TRUE;
			break;
		}
		case MSG_2D_READY_EXE_THUMBTOUCH:
		{
			ReadyForThumbTouchExec(hWnd,0);
			break;
		}
		case MSG_2D_THUMBTOUCH_SWITCH_BUFF:
		{
			if(-1 ==  wParam)
			{
				WIN32_GetStartSreenImage(lParam);	/* ȡһҳ */
				
			}
			else if(-2 == wParam)
			{
				WIN32_GetStartSreenImageEx(lParam); /* ȡһҳ */
			}
			break;
		}
		default:
			break;
    }
    return THUMBTOUCHGOON;
}

/**************************************************************************
* ƣ ReadyForThumbTouchExec
*  ʼExcuteThumbTouchṹΪ׼
* ˵ (IN) hWndЧؼ                   
*   ֵ
* ˵ hWndЧ
**************************************************************************/
ZVOID ReadyForThumbTouchExec(HWND hWnd, ZSINT32 flag) 
{
    PMSGQUEUE    pMsgQueue = NULL;
	PCONTROL     pCtrl = (PCONTROL)hWnd;
	PMAINWIN 	 pWin = HWND_NULL;
	if(g_ThumbtouchDisable)
		return;
	if(!isValidaWin(hWnd))
	{
		return;
	}
	pWin= pCtrl->pMainWin;
	if((HWND)pWin != GetActiveWindow())
 	{
	 	return ;
 	}
    
	pMsgQueue=(PMSGQUEUE)GetMsgQueue(hWnd);
	ExecuteThumbTouch.bExecuteTTouch = TRUE;
	ExecuteThumbTouch.hWnd = hWnd;
	ExecuteThumbTouch.dwStyle = pCtrl->dwStyle;
	ExecuteThumbTouch.pMsgQueue = pMsgQueue;	
    
}
ZVOID RegisterThumbTouchCtrl(HWND hWnd) 
{
    PMSGQUEUE    pMsgQueue = NULL;
	PCONTROL     pCtrl = (PCONTROL)hWnd;
	PMAINWIN 	 pWin = HWND_NULL;
	
	if(g_ThumbtouchDisable)
		return;
	
	if(!isValidaWin(hWnd))
	{
		return;
	}
	pWin= pCtrl->pMainWin;
	if((HWND)pWin != GetActiveWindow())
 	{
	 	return ;
 	}
	
	pMsgQueue=(PMSGQUEUE)GetMsgQueue(hWnd);
    ExecuteThumbTouch.bExecuteTTouch = TRUE;
    ExecuteThumbTouch.hWnd = hWnd;
    ExecuteThumbTouch.dwStyle = pCtrl->dwStyle;
    ExecuteThumbTouch.pMsgQueue = pMsgQueue;	
}

/**
 * ƣ SetYValue
 *  2DϢ
 * ˵ (IN) hWndھ
 *            (IN) y: ôֱꡣԶר
 *   ֵ 
 * ˵ 
 */ 
ZVOID SetYValue (HWND hWnd,ZSINT32 y)
{
	ZSINT32 ioldy = y;
	ZSINT32 i = 0;
	if(g_ThumbtouchDisable)
		return;
	ScreenToClient(hWnd,&i,&ioldy);
	sTTStateData.iOldY = ioldy;
}

/**
 * ƣ DirectMergePic
 *  ֱƴͼ
 * ˵ (IN) hWndھ
 *			  (IN) y: ôֱꡣԶõ
 *			  (IN) flag:

 *   ֵ 
 * ˵ 
 */ 
ZSINT32 DirectMergePic (HWND hWnd,ZSINT32 y,ZSINT32 flag)
{  

    RECT tmpRect = {0};
	if(g_ThumbtouchDisable)
		return -1;
	if(p2DPreBuffer == NULL)
		return -1;
    sTTStateData.iTotalMoveHeight = y;
		if(y<=0)
		{
			  sTTStateData.iMoveHeight = -1;
		}
		GetClientRect(hWnd,&tmpRect);
		sTTStateData.iClientHight = RECTH(tmpRect);
    thumbtouch_set_buffer(sTTStateData.iTotalMoveHeight);
    mergePicForMms(s_EndBuffer, p2DStartBuffer, hWnd, y,flag);
 		return 0;
}

/**
 * ƣ WndCtrlThumbTouchProc
 *  2DϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *            (IN) pTouchRect:ָ
 *   ֵ 
 * ˵ ú0ʾҪϢ·Ϣ·
 */ 
ZSINT32 WndCtrlThumbTouchProc (HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect)
{
  	PCONTROL pControl = (PCONTROL)hWnd;
    if(g_ThumbtouchDisable)
		return -1;
    if(pControl->dwExStyle & WS_2D_FOR_WIDGET) /* ؼԻƷʽ */
    {
        if(!WndCtrl2DProc(hWnd, message, wParam, lParam, pTouchRect)) 
        {
            return 0;
        }
    }
    else if(pControl->dwExStyle & WS_2D_MULTI_PAGE
		    && (g_ThumbtouchInertiaPage==THUMB_TOUCH_INERTIA_PAGE_NUMBER))  /*ZCORE V2.5.0B01*/
    {
        if(!thumbtouch_proc_for_multipage(hWnd, message, wParam, lParam,pTouchRect))  /* һλҳ */
        {
            return 0;
        }
    }
	else 
	{
		if(!WndCtrl2DProcEx(hWnd, message, wParam, lParam,pTouchRect)) /* һ໬һҳ */ 
        {
            return 0;
        }
	}
    return 1;	
}

/**
 * ƣ WndCtrl2DProc
 *  2DϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *            (IN) pTouchRect:ָ
 *   ֵ 
 * ˵   ؼԻƷʽ 
 */ 
ZSINT32 WndCtrl2DProc (HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam,PRECT pTouchRect)
{  
	PCONTROL pControl = NULL;

	if(g_ThumbtouchDisable)
		return -1;
    pControl = (PCONTROL)hWnd;
    if(!(Is2DThumbTouch(pControl->dwStyle)))
        return THUMBTOUCHGOON;
    switch (message) 
	{
		case MSG_LBUTTONDOWN: // 0x0001
		{
			ZSINT32 iViewH = -1;
			iViewH = thumbtouch_get_content_rate(hWnd); 
			if(iViewH < 0)
			{
				thumbtouch_init();
				return THUMBTOUCHGOON;
			}
	        if(!thumbtouch_handle_lbuttondown(hWnd, message, wParam, lParam))
	           	return THUMBTOUCHSTOP;
			break; 
		}
		case MSG_LBUTTONUP: // 0x0002
		{    
	        if(!thumbtouch_handle_lbuttonup(hWnd, message, wParam, lParam))
	        	return THUMBTOUCHSTOP;
			break; 
		}
		case MSG_MOUSEMOVE: // 0x0004
		{   
			if(!thumbtouch_handle_mousemove(hWnd, message, wParam, lParam,pTouchRect))
				return THUMBTOUCHSTOP;
			break;
		}
		case MSG_MOUSEMOVEIN: // 0x0050
        {   
			if(wParam == FALSE)
			{   
				if(0==thumbtouch_handle_mousemovein(hWnd, message, wParam, lParam))
					return THUMBTOUCHSTOP;
			}
        	return THUMBTOUCHGOON;
		}
		
		case MSG_DESTROY: // 0x0064 
        {
		 	HWND hthumbWnd = GetActiveWindow();
			
			if(hthumbWnd == hWnd || hthumbWnd == GetParent(hWnd))
			{
				thumbtouch_init();
				sTTStateData.pbmpBkg = NULL;
			}       
            return THUMBTOUCHGOON;
        }
		case MSG_TIMER: // 0x0144
		{   
			if(!thumbtouch_handle_timer(hWnd, message, wParam, lParam,pTouchRect))
				return THUMBTOUCHSTOP;
			break;
		}
		case MSG_2D_STOP_THUMBTOUCH: // 0x1009
        {
            thumbtouch_handle_lbuttonup(hWnd, message, wParam, MAKELONG(0, sTTStateData.iOldY));
			thumbtouch_init();
			return THUMBTOUCHGOON;
        }
		case MSG_2D_THUMBTOUCH_SET_BKG:
		{
			ThumbTouchSetBKG(hWnd, (PBITMAP)wParam);
			return THUMBTOUCHSTOP;
		}
		default:
			break;
    }
    return THUMBTOUCHGOON;
}

/**
 * ƣ WndCtrl2DProcEx
 *  2DϢ
 * ˵ (IN) hWndھ
 *            (IN) message: Ϣ
 *            (IN) wParam: w
 *            (IN) lParam: L
 *            (IN) pTouchRect:ָ
 *   ֵ 
 * ˵ һ໬һҳ
 */ 
ZSINT32 WndCtrl2DProcEx (HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam, PRECT pTouchRect)
{  
	PCONTROL pControl = NULL;
    ZSINT32 x = LOSWORD(lParam);        
    ZSINT32 y = HISWORD(lParam);
	if(g_ThumbtouchDisable)
		return -1;
    pControl = (PCONTROL)hWnd;
    if(!(Is2DThumbTouch(pControl->dwStyle)))
        return THUMBTOUCHGOON;
    switch (message) 
	{
		case MSG_LBUTTONDOWN: // 0x0001
		{
			ZSINT32 iViewH = -1;
			if(!sTTStateData.bGetBuffer)
				return THUMBTOUCHGOON;
			iViewH = thumbtouch_get_content_rate(hWnd);
			if(iViewH < 0)
			{
				sTTStateData.bScrolledPrepare = FALSE;
				return THUMBTOUCHGOON;
			}
	        if(!thumbtouch_handle_lbuttondown_pic(hWnd, message, wParam, lParam, pTouchRect))
	        	return THUMBTOUCHSTOP;
			break; 
		}
		case MSG_2D_THUMBTOUCH_LBUTTONUP:
		case MSG_LBUTTONUP: // 0x0002
		{    	
	        if(!thumbtouch_handle_lbuttonup_singlePic(hWnd, message, wParam, lParam))
	        	return THUMBTOUCHSTOP;
			break; 
		}
		case MSG_MOUSEMOVE: // 0x0004
		{   
			if(!thumbtouch_handle_mousemove_singlePic(hWnd, message, wParam, lParam, pTouchRect))
				return THUMBTOUCHSTOP;
			break;
		}
		case MSG_NCMOUSEMOVE:  // 0x000B
	    { 
	        RECT            rectWindow = {0};
	        GetWindowRect(hWnd, &rectWindow);
	        if(!PtInRect(&rectWindow,x, y))
	        {
	            thumbtouch_handle_lbuttonup_singlePic(hWnd, message, wParam, lParam);    
	    	    return THUMBTOUCHSTOP;
	        }
	        break; 
	    }                            
		case MSG_MOUSEMOVEIN: // 0x0050
	    {   
			if(wParam == FALSE) 
				thumbtouch_handle_mousemovein_singlepic(hWnd, message, wParam, lParam);
	    	return THUMBTOUCHGOON;
		}
		case  MSG_CREATE:
		{
			s_iCountWindowForThumbTouch++;
			thumbtouch_allocatebuffer();
			break;
		}
		case MSG_DESTROY: // 0x0064 
	    {
	        thumbtouch_init();
			s_iCountWindowForThumbTouch--;
			thumbtouch_freebuffer();
	        return THUMBTOUCHGOON;
	    }
		case MSG_TIMER: // 0x0144
		{   
			break;
		}
		case MSG_2D_STOP_THUMBTOUCH: // 0x1009
	    {
			thumbtouch_init(); 
			SendMessage(GetParent(hWnd), MSG_2D_THUMBTOUCH_FINISH, 0, 0);
			SendMessage(hWnd, MSG_2D_THUMBTOUCH_FINISH, 0, 0);
	        return THUMBTOUCHGOON;
	    }
		case MSG_2D_END_PAINT:
		{
			sTTStateData.bGetBuffer = TRUE;
			break;
		}
		case MSG_2D_READY_EXE_THUMBTOUCH:
		{
			ReadyForThumbTouchExec(hWnd,0);
			break;
		}
		case MSG_2D_THUMBTOUCH_SWITCH_BUFF:
		{
			if(-1 ==  wParam)
				WIN32_GetStartSreenImage(lParam);	/* ȡһҳ */
			else if(-2 == wParam)
				WIN32_GetStartSreenImageEx(lParam); /* ȡһҳ */
			break;
		}
		case MSG_2D_THUMBTOUCH_REPAINT_CURRBUFF:
		{
			thumtouch_copy_current_page();
			return 0 ;
		}
		case MSG_SETFOCUS:
			RegisterThumbTouchCtrl(hWnd);
			break;
		default:
			break;
    }
    return THUMBTOUCHGOON;
}

/**
 * : ThumbTouchSetBKG
 * ñͼƬ
 * ˵ (IN) hWndھ
 *   ֵ 
 * ˵ 
 */ 
ZVOID ThumbTouchSetBKG(HWND hWnd, PBITMAP pBkg)
{
	if(g_ThumbtouchDisable)
		return;
	sTTStateData.pbmpBkg = pBkg;
}


/**
 * ƣ IsLastCtrl
 * жϿؼǷǸؼһӿؼ
 * ˵ (IN) hWndھ
 *   ֵ򷵻TRUE, 򷵻FALSE
 * ˵ 
 */ 
ZBOOL IsLastCtrl(HWND hWnd)
{
	HWND	hLastCtrl = HWND_NULL;
	if(g_ThumbtouchDisable)
		return FALSE;
	hLastCtrl = SendMessage(GetParent(hWnd), MSG_2D_GET_LAST_CHILD_CTRL, 0, 0);
	if(hLastCtrl == hWnd)
	{
		return TRUE;
	}
	return FALSE;
}

/**
 * ƣ GetThumbTouchState
 * ȡĴָ״̬
 * ˵ (IN) 
 *   ֵ򷵻TRUE, 򷵻FALSE
 * ˵ 
 */ 
ZBOOL GetThumbTouchState(ZVOID)
{
	if(g_ThumbtouchDisable)
		return FALSE;
	return sTTStateData.bThumbTouchState;
	do_nothing();
}

VOID ReSetThumbTouchState(void)
{
	if(g_ThumbtouchDisable)
	{
		return ;
	}
	
	sTTStateData.bThumbTouchState = FALSE;
}

ZSINT32 GetAniEndBuffer(HWND pCtrl, WPARAM w)
{
	if(g_ThumbtouchDisable)
		return -1;
	if((-1 == w || -2 == w)
	    && IsLastCtrl(pCtrl))
	{
        SendMessage(GetParent((HWND)pCtrl), MSG_2D_END_PAINT, 0, 0);
		WIN32_GetEndScreenImage();
		return 0;
	}
	return -1;
}

/**
 * ƣ ThumbTouchGetPageID
 * ȡǵڼҳ
 * ˵ (IN) hWndھ
 *   ֵ򷵻TRUE, 򷵻FALSE
 * ˵ 
 */ 
ZSINT32 ThumbTouchGetPageID(ZSINT32 iOldPos, ZSINT32 iNewPos, ZSINT32 iPageHeight)
{
	ZSINT32 iDis = iNewPos - iOldPos;
	ZSINT32 i = 0;
	if(g_ThumbtouchDisable)
		return -1;
	iDis = iDis >= 0 ? iDis:GET_OPPOSITION_NUMBER(iDis);
	while(iDis>0)
	{
		iDis -= iPageHeight;
		i++;
	}
	if(i>3)
	{
		i = 3;
	}
	return i;
}

/**
 * ƣ IncludeThumbTouchStyle
 * Ĵָ
 * ˵ (IN) hWndھ
 *   ֵ
 * ˵ 
 */ 
ZVOID IncludeThumbTouchStyle(HWND hWnd)
{
	PCONTROL pControl = (PCONTROL)hWnd;
	if(Is2DThumbTouch(pControl->dwStyle))
		return;
	IncludeWindowStyle(hWnd,WS_2D_THUMB_TOUCH);
	if(!(pControl->dwStyle & WS_2D_FOR_WIDGET))
	{
		s_iCountWindowForThumbTouch++;
		thumbtouch_allocatebuffer();
	}
}

/**
 * ƣ ExcludeThumbTouchStyle
 * ȥĴָ
 * ˵ (IN) hWndھ
 *   ֵ
 * ˵ 
 */ 
ZVOID ExcludeThumbTouchStyle(HWND hWnd)
{
	PCONTROL pControl = (PCONTROL)hWnd;
	if(!(Is2DThumbTouch(pControl->dwStyle)))
		return;
	ExcludeWindowStyle(hWnd,WS_2D_THUMB_TOUCH);
	if(!(pControl->dwStyle & WS_2D_FOR_WIDGET))
	{
		s_iCountWindowForThumbTouch--;
		thumbtouch_freebuffer();
	}
}

/**
 *	  	MessageFor2DFlagProc
 *	    	ڽЧʱӦkeydown
 *		
 *		
 *	  ֵ	
 *	˵	˽ӿڲʹãֻ֤ͨ
 */
ZSINT32  MessageFor2DFlagProc(HWND hWnd, ZSINT32 message, WPARAM wParam, LPARAM lParam)
{
	return 1;
}
/**
 *	  	zCore_CleanAllDirtyChild
 *	    	Ӧӿؼıˢ
 *		
 *		
 *	  ֵ	
 *	˵	
 */
static ZVOID zCore_CleanAllDirtyChild(HWND hWnd)
{
    PCONTROL 	pCtrl = (PCONTROL)hWnd;
    HWND 			pDirtyWin ;
	
    if (pCtrl->InvRgn.rgn.head)
	{
		EmptyClipRgn (&(pCtrl->InvRgn.rgn));
	}

    pCtrl = pCtrl->children;
	while (pCtrl) 
	{		
        zCore_CleanAllDirtyChild((HWND) pCtrl);
	    pCtrl = pCtrl->next;
    }	
}
